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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * Support routines for managing state related to memory modules. 28 */ 29 30 #include <gmem_mem.h> 31 #include <gmem_dimm.h> 32 #include <gmem.h> 33 34 #include <assert.h> 35 #include <errno.h> 36 #include <strings.h> 37 #include <ctype.h> 38 #include <fcntl.h> 39 #include <unistd.h> 40 #include <fm/fmd_api.h> 41 #include <sys/fm/protocol.h> 42 #include <sys/mem.h> 43 #include <sys/nvpair.h> 44 45 char * 46 gmem_mem_serdnm_create(fmd_hdl_t *hdl, const char *serdbase, const char *serial) 47 { 48 const char *fmt = "%s_%s_serd"; 49 size_t sz = snprintf(NULL, 0, fmt, serdbase, serial) + 1; 50 char *nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP); 51 (void) snprintf(nm, sz, fmt, serdbase, serial); 52 53 return (nm); 54 } 55 56 char * 57 gmem_page_serdnm_create(fmd_hdl_t *hdl, const char *serdbase, 58 uint64_t phys_addr) 59 { 60 const char *fmt = "%s_%llXserd"; 61 size_t sz = snprintf(NULL, 0, fmt, serdbase, phys_addr) + 1; 62 char *nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP); 63 (void) snprintf(nm, sz, fmt, serdbase, phys_addr); 64 65 return (nm); 66 } 67 68 char * 69 gmem_mq_serdnm_create(fmd_hdl_t *hdl, const char *serdbase, 70 uint64_t phys_addr, uint16_t cw, uint16_t pos) 71 { 72 const char *fmt = "%s_%llX_%x_%x_serd"; 73 size_t sz = snprintf(NULL, 0, fmt, serdbase, phys_addr, cw, pos) + 1; 74 char *nm = fmd_hdl_alloc(hdl, sz, FMD_SLEEP); 75 (void) snprintf(nm, sz, fmt, serdbase, phys_addr, cw, pos); 76 77 return (nm); 78 } 79 80 uint32_t 81 gmem_get_serd_filter_ratio(nvlist_t *nvl) 82 { 83 uint32_t filter_ratio = 0; 84 uint32_t erpt_ratio; 85 86 if (gmem.gm_filter_ratio == 0) { 87 if (nvlist_lookup_uint32(nvl, 88 GMEM_ERPT_PAYLOAD_FILTER_RATIO, &erpt_ratio) == 0) 89 filter_ratio = erpt_ratio; 90 } else 91 filter_ratio = gmem.gm_filter_ratio; 92 93 return (filter_ratio); 94 } 95 96 void 97 gmem_page_serd_create(fmd_hdl_t *hdl, gmem_page_t *page, nvlist_t *nvl) 98 { 99 uint32_t erpt_serdn, serd_n; 100 uint64_t erpt_serdt, serd_t; 101 102 serd_n = gmem.gm_ce_n; 103 serd_t = gmem.gm_ce_t; 104 105 if (serd_n == DEFAULT_SERDN && serd_t == DEFAULT_SERDT) { 106 if (nvlist_lookup_uint32(nvl, GMEM_ERPT_PAYLOAD_SERDN, 107 &erpt_serdn) == 0) 108 serd_n = erpt_serdn; 109 if (nvlist_lookup_uint64(nvl, GMEM_ERPT_PAYLOAD_SERDT, 110 &erpt_serdt) == 0) 111 serd_t = erpt_serdt; 112 } 113 114 page->page_case.cc_serdnm = gmem_page_serdnm_create(hdl, "page", 115 page->page_physbase); 116 117 fmd_serd_create(hdl, page->page_case.cc_serdnm, serd_n, serd_t); 118 } 119 120 int 121 gmem_serd_record(fmd_hdl_t *hdl, const char *serdbaser, uint32_t ratio, 122 fmd_event_t *ep) 123 { 124 int i, rc; 125 if (ratio == 0) 126 return (fmd_serd_record(hdl, serdbaser, ep)); 127 for (i = 0; i < ratio; i++) { 128 rc = fmd_serd_record(hdl, serdbaser, ep); 129 if (rc != FMD_B_FALSE) 130 break; 131 } 132 return (rc); 133 } 134 135 void 136 gmem_mem_case_restore(fmd_hdl_t *hdl, gmem_case_t *cc, fmd_case_t *cp, 137 const char *serdbase, const char *serial) 138 { 139 gmem_case_restore(hdl, cc, cp, gmem_mem_serdnm_create(hdl, serdbase, 140 serial)); 141 } 142 143 void 144 gmem_mem_retirestat_create(fmd_hdl_t *hdl, fmd_stat_t *st, const char *serial, 145 uint64_t value, const char *prefix) 146 { 147 148 (void) snprintf(st->fmds_name, sizeof (st->fmds_name), "%s%s", 149 prefix, serial); 150 (void) snprintf(st->fmds_desc, sizeof (st->fmds_desc), 151 "retirements for %s%s", prefix, serial); 152 st->fmds_type = FMD_TYPE_UINT64; 153 st->fmds_value.ui64 = value; 154 155 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC, 1, st); 156 } 157 158 void 159 gmem_mem_gc(fmd_hdl_t *hdl) 160 { 161 gmem_dimm_gc(hdl); 162 } 163 164 void 165 gmem_mem_fini(fmd_hdl_t *hdl) 166 { 167 gmem_dimm_fini(hdl); 168 } 169