xref: /titanic_50/usr/src/cmd/fm/schemes/mem/mem.h (revision 90bcde942a3919300ffc73f98ea903b58386c395)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #ifndef _MEM_H
28 #define	_MEM_H
29 
30 #pragma ident	"%Z%%M%	%I%	%E% SMI"
31 
32 #include <sys/types.h>
33 #include <sys/nvpair.h>
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /*
40  * FMRI plugin for the `mem' scheme.
41  *
42  * The mem scheme can be used to name individual memory modules, as well as
43  * groups of memory modules, also known as banks.  The name `dimm' is used as a
44  * synonym for individual memory modules, for no good reason.  Mem FMRIs can
45  * be further refined with the addition of a member which identifies a
46  * particular physical page within the bank or DIMM.  The named page is as
47  * viewed by the VM system, and may thus span multiple memory modules.  It will,
48  * however, be at least partially contained by the named bank or DIMM.
49  *
50  * Memory modules are identified by two things - their physical position, or
51  * slot, in the machine, and their serial number.  DIMMs are identified by this
52  * tuple on platforms which support the retrieval of serial numbers.  Platforms
53  * which don't have this support rely on the slot number, with the corresponding
54  * degradation in their ability to detect hardware changees.
55  *
56  * The physical location is embodied by the unum, which is highly specific to
57  * each platform, and bears a passing resemblance to the name of the slot, as
58  * printed on the actual hardware.  The unum is mapped to a DIMM-specific
59  * device, which is then read to determine the serial number.  See mem_disc.c
60  * for details of the process by which unums are mapped to devices, and
61  * mem_read.c for the code which actually retrieves the serial number from the
62  * device.
63  *
64  * Banks are also identified by unums, which must be broken apart into the
65  * unums which identify each constituent memory module.  Serial numbers are
66  * retrieved for banks - one per member module - in the same way as for
67  * individual modules.  See mem_unum.c for the code which bursts bank unums.
68  *
69  * Serial number retrieval, on platforms which support it, is very expensive
70  * (on the order of several tenths of a second, which adds up in a hurry on
71  * larger machines).  So, while we pre-generate the list of DIMM device paths,
72  * we only read their serial numbers when requested by plugin consumers.  To
73  * further reduce the perceived cost, we don't re-read until/unless we detect
74  * that a DR operation has taken place.
75  *
76  * Using the facilities described above, the plugin implements the following
77  * entry points: (see mem.c)
78  *
79  *   - nvl2str: The printed representation of the named bank or DIMM is
80  *     generated.  No attempt is made to determine whether or not the named
81  *     item is still present in the system.
82  *
83  *   - expand: For platforms which do not include bank or DIMM
84  *     serial numbers in their ereports, this entry point will read the
85  *     serial number(s) for the named item, and will add it/them to the passed
86  *     FMRI.  Errors will be returned if the FMRI (unum) was unparseable, or if
87  *     the serial number could not be retrieved.
88  *
89  *   - present: Given a mem-schemed FMRI with a serial number, this entry
90  *     point will attempt to determine whether the bank or module named in the
91  *     FMRI is still present in the system at the same location.  Programmer
92  *     errors (invalid FMRIs) will be signalled to the caller.  Warnings will
93  *     be emitted for otherwise-valid FMRIs whose serial numbers could not be
94  *     read, with the caller told that the FMRI is not present.
95  *
96  *   - contains: Used to determine whether a given bank contains a given DIMM.
97  *     No attempt is made to determine whether the module named by the FMRIs are
98  *     actually present in the system.  Programmer errors (invalidd FMRIs) will
99  *     be returned to the caller.  Warnings will be emitted for otherwise-valid
100  *     FMRIs whose relationship could not be determined, with the caller told
101  *     that there is no relationship.
102  */
103 
104 /*
105  * 18+nul for SPD, 6+nul for SEEPROM, 15+nul max for Serengeti, Starcat, LW8.
106  * 18 for Sun Partnumber, 18 partner partnumber, 12 serialnumber for OPL.
107  */
108 #define	MEM_SERID_MAXLEN	64
109 #define	MAX_DIMMS_PER_BANK	4
110 
111 typedef struct mem_dimm_map {
112 	struct mem_dimm_map *dm_next;	/* The next DIMM map */
113 	char *dm_label;			/* The UNUM for this DIMM */
114 	char *dm_device;		/* Path to I2C device for DIMM */
115 	char dm_serid[MEM_SERID_MAXLEN]; /* Cached serial number */
116 	char *dm_part;			/* DIMM part number */
117 	uint64_t dm_drgen;		/* DR gen count for cached S/N */
118 } mem_dimm_map_t;
119 
120 typedef struct mem_bank_map {
121 	struct mem_bank_map *bm_next;	/* the next bank map overall */
122 	struct mem_bank_map *bm_grp;	/* next bank map in group */
123 	uint64_t	bm_mask;
124 	uint64_t	bm_match;
125 	uint16_t	bm_shift;	/* dimms-per-reference shift */
126 	mem_dimm_map_t *bm_dimm[MAX_DIMMS_PER_BANK];
127 } mem_bank_map_t;
128 
129 typedef struct mem_grp {
130 	struct mem_grp *mg_next;
131 	size_t		mg_size;
132 	mem_bank_map_t *mg_bank;
133 } mem_grp_t;
134 
135 typedef struct mem_seg_map {
136 	struct mem_seg_map *sm_next;	/* the next segment map */
137 	uint64_t	sm_base;	/* base address for this segment */
138 	uint64_t	sm_size;	/* size for this segment */
139 	mem_grp_t	*sm_grp;
140 } mem_seg_map_t;
141 
142 
143 typedef struct mem {
144 	mem_dimm_map_t *mem_dm;		/* List supported DIMMs */
145 	uint64_t mem_memconfig;		/* HV memory-configuration-id# */
146 	mem_seg_map_t *mem_seg;		/* list of defined segments */
147 	mem_bank_map_t *mem_bank;
148 	mem_grp_t *mem_group;		/* groups of banks for a segment */
149 } mem_t;
150 
151 extern int mem_discover(void);
152 extern int mem_get_serid(const char *, char *, size_t);
153 extern int mem_get_serids_by_unum(const char *, char ***, size_t *);
154 extern void mem_expand_opt(nvlist_t *, char *, char **);
155 
156 extern int mem_unum_burst(const char *, char ***, size_t *);
157 extern int mem_unum_contains(const char *, const char *);
158 extern int mem_unum_rewrite(nvlist_t *, nvlist_t **);
159 
160 extern void mem_strarray_free(char **, size_t);
161 extern int mem_page_cmd(int, nvlist_t *);
162 
163 extern mem_t mem;
164 
165 #ifdef __cplusplus
166 }
167 #endif
168 
169 #endif /* _MEM_H */
170