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 *
gmem_mem_serdnm_create(fmd_hdl_t * hdl,const char * serdbase,const char * serial)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 *
gmem_page_serdnm_create(fmd_hdl_t * hdl,const char * serdbase,uint64_t phys_addr)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 *
gmem_mq_serdnm_create(fmd_hdl_t * hdl,const char * serdbase,uint64_t phys_addr,uint16_t cw,uint16_t pos)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
gmem_get_serd_filter_ratio(nvlist_t * nvl)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
gmem_page_serd_create(fmd_hdl_t * hdl,gmem_page_t * page,nvlist_t * nvl)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
gmem_serd_record(fmd_hdl_t * hdl,const char * serdbaser,uint32_t ratio,fmd_event_t * ep)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
gmem_mem_case_restore(fmd_hdl_t * hdl,gmem_case_t * cc,fmd_case_t * cp,const char * serdbase,const char * serial)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
gmem_mem_retirestat_create(fmd_hdl_t * hdl,fmd_stat_t * st,const char * serial,uint64_t value,const char * prefix)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
gmem_mem_gc(fmd_hdl_t * hdl)159 gmem_mem_gc(fmd_hdl_t *hdl)
160 {
161 gmem_dimm_gc(hdl);
162 }
163
164 void
gmem_mem_fini(fmd_hdl_t * hdl)165 gmem_mem_fini(fmd_hdl_t *hdl)
166 {
167 gmem_dimm_fini(hdl);
168 }
169