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