1*eb00b1c8SRobert Mustacchi /*
2*eb00b1c8SRobert Mustacchi * This file and its contents are supplied under the terms of the
3*eb00b1c8SRobert Mustacchi * Common Development and Distribution License ("CDDL"), version 1.0.
4*eb00b1c8SRobert Mustacchi * You may only use this file in accordance with the terms of version
5*eb00b1c8SRobert Mustacchi * 1.0 of the CDDL.
6*eb00b1c8SRobert Mustacchi *
7*eb00b1c8SRobert Mustacchi * A full copy of the text of the CDDL should have accompanied this
8*eb00b1c8SRobert Mustacchi * source. A copy of the CDDL is also available via the Internet at
9*eb00b1c8SRobert Mustacchi * http://www.illumos.org/license/CDDL.
10*eb00b1c8SRobert Mustacchi */
11*eb00b1c8SRobert Mustacchi
12*eb00b1c8SRobert Mustacchi /*
13*eb00b1c8SRobert Mustacchi * Copyright 2019 Joyent, Inc.
14*eb00b1c8SRobert Mustacchi */
15*eb00b1c8SRobert Mustacchi
16*eb00b1c8SRobert Mustacchi /*
17*eb00b1c8SRobert Mustacchi * This implements logic to allow us to dump IMC data for decoding purposes,
18*eb00b1c8SRobert Mustacchi * such that we can later encode it elsewhere. In general, dumping is done by
19*eb00b1c8SRobert Mustacchi * the kernel and reconstituting this data is done by user land.
20*eb00b1c8SRobert Mustacchi */
21*eb00b1c8SRobert Mustacchi
22*eb00b1c8SRobert Mustacchi #include "imc.h"
23*eb00b1c8SRobert Mustacchi
24*eb00b1c8SRobert Mustacchi #ifndef _KERNEL
25*eb00b1c8SRobert Mustacchi #include <stdint.h>
26*eb00b1c8SRobert Mustacchi #include <strings.h>
27*eb00b1c8SRobert Mustacchi #endif /* !_KERNEL */
28*eb00b1c8SRobert Mustacchi
29*eb00b1c8SRobert Mustacchi
30*eb00b1c8SRobert Mustacchi static nvlist_t *
imc_dump_sad(imc_sad_t * sad)31*eb00b1c8SRobert Mustacchi imc_dump_sad(imc_sad_t *sad)
32*eb00b1c8SRobert Mustacchi {
33*eb00b1c8SRobert Mustacchi uint_t i;
34*eb00b1c8SRobert Mustacchi nvlist_t *nvl;
35*eb00b1c8SRobert Mustacchi nvlist_t *rules[IMC_MAX_SAD_RULES];
36*eb00b1c8SRobert Mustacchi nvlist_t *routes[IMC_MAX_SAD_MCROUTES];
37*eb00b1c8SRobert Mustacchi
38*eb00b1c8SRobert Mustacchi nvl = fnvlist_alloc();
39*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "isad_flags", sad->isad_flags);
40*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "isad_valid", sad->isad_valid);
41*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(nvl, "isad_tolm", sad->isad_tolm);
42*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(nvl, "isad_tohm", sad->isad_tohm);
43*eb00b1c8SRobert Mustacchi
44*eb00b1c8SRobert Mustacchi for (i = 0; i < sad->isad_nrules; i++) {
45*eb00b1c8SRobert Mustacchi nvlist_t *n = fnvlist_alloc();
46*eb00b1c8SRobert Mustacchi imc_sad_rule_t *r = &sad->isad_rules[i];
47*eb00b1c8SRobert Mustacchi
48*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(n, "isr_enable", r->isr_enable);
49*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(n, "isr_a7mode", r->isr_a7mode);
50*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(n, "isr_need_mod3", r->isr_need_mod3);
51*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(n, "isr_limit", r->isr_limit);
52*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(n, "isr_type", r->isr_type);
53*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(n, "isr_imode", r->isr_imode);
54*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(n, "isr_mod_mode", r->isr_mod_mode);
55*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(n, "isr_mod_type", r->isr_mod_type);
56*eb00b1c8SRobert Mustacchi fnvlist_add_uint8_array(n, "isr_targets", r->isr_targets,
57*eb00b1c8SRobert Mustacchi r->isr_ntargets);
58*eb00b1c8SRobert Mustacchi
59*eb00b1c8SRobert Mustacchi rules[i] = n;
60*eb00b1c8SRobert Mustacchi }
61*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "isad_rules", rules, sad->isad_nrules);
62*eb00b1c8SRobert Mustacchi for (i = 0; i < sad->isad_nrules; i++) {
63*eb00b1c8SRobert Mustacchi nvlist_free(rules[i]);
64*eb00b1c8SRobert Mustacchi }
65*eb00b1c8SRobert Mustacchi
66*eb00b1c8SRobert Mustacchi if (sad->isad_mcroute.ismc_nroutes == 0) {
67*eb00b1c8SRobert Mustacchi return (nvl);
68*eb00b1c8SRobert Mustacchi }
69*eb00b1c8SRobert Mustacchi
70*eb00b1c8SRobert Mustacchi for (i = 0; i < sad->isad_mcroute.ismc_nroutes; i++) {
71*eb00b1c8SRobert Mustacchi nvlist_t *r = fnvlist_alloc();
72*eb00b1c8SRobert Mustacchi imc_sad_mcroute_entry_t *e =
73*eb00b1c8SRobert Mustacchi &sad->isad_mcroute.ismc_mcroutes[i];
74*eb00b1c8SRobert Mustacchi
75*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(r, "ismce_imc", e->ismce_imc);
76*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(r, "ismce_pchannel", e->ismce_pchannel);
77*eb00b1c8SRobert Mustacchi routes[i] = r;
78*eb00b1c8SRobert Mustacchi }
79*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "isad_mcroute", routes, i);
80*eb00b1c8SRobert Mustacchi for (i = 0; i < sad->isad_mcroute.ismc_nroutes; i++) {
81*eb00b1c8SRobert Mustacchi nvlist_free(routes[i]);
82*eb00b1c8SRobert Mustacchi }
83*eb00b1c8SRobert Mustacchi
84*eb00b1c8SRobert Mustacchi return (nvl);
85*eb00b1c8SRobert Mustacchi }
86*eb00b1c8SRobert Mustacchi
87*eb00b1c8SRobert Mustacchi static nvlist_t *
imc_dump_tad(imc_tad_t * tad)88*eb00b1c8SRobert Mustacchi imc_dump_tad(imc_tad_t *tad)
89*eb00b1c8SRobert Mustacchi {
90*eb00b1c8SRobert Mustacchi uint_t i;
91*eb00b1c8SRobert Mustacchi nvlist_t *nvl;
92*eb00b1c8SRobert Mustacchi nvlist_t *rules[IMC_MAX_TAD_RULES];
93*eb00b1c8SRobert Mustacchi
94*eb00b1c8SRobert Mustacchi nvl = fnvlist_alloc();
95*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "itad_valid", tad->itad_valid);
96*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "itad_flags", tad->itad_flags);
97*eb00b1c8SRobert Mustacchi for (i = 0; i < tad->itad_nrules; i++) {
98*eb00b1c8SRobert Mustacchi nvlist_t *t = fnvlist_alloc();
99*eb00b1c8SRobert Mustacchi imc_tad_rule_t *r = &tad->itad_rules[i];
100*eb00b1c8SRobert Mustacchi
101*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(t, "itr_base", r->itr_base);
102*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(t, "itr_limit", r->itr_limit);
103*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(t, "itr_sock_way", r->itr_sock_way);
104*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(t, "itr_chan_way", r->itr_chan_way);
105*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(t, "itr_sock_gran", r->itr_sock_gran);
106*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(t, "itr_chan_gran", r->itr_chan_gran);
107*eb00b1c8SRobert Mustacchi fnvlist_add_uint8_array(t, "itr_targets", r->itr_targets,
108*eb00b1c8SRobert Mustacchi r->itr_ntargets);
109*eb00b1c8SRobert Mustacchi
110*eb00b1c8SRobert Mustacchi rules[i] = t;
111*eb00b1c8SRobert Mustacchi }
112*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "itad_rules", rules, tad->itad_nrules);
113*eb00b1c8SRobert Mustacchi for (i = 0; i < tad->itad_nrules; i++) {
114*eb00b1c8SRobert Mustacchi nvlist_free(rules[i]);
115*eb00b1c8SRobert Mustacchi }
116*eb00b1c8SRobert Mustacchi
117*eb00b1c8SRobert Mustacchi return (nvl);
118*eb00b1c8SRobert Mustacchi }
119*eb00b1c8SRobert Mustacchi
120*eb00b1c8SRobert Mustacchi static nvlist_t *
imc_dump_channel(imc_channel_t * chan)121*eb00b1c8SRobert Mustacchi imc_dump_channel(imc_channel_t *chan)
122*eb00b1c8SRobert Mustacchi {
123*eb00b1c8SRobert Mustacchi uint_t i;
124*eb00b1c8SRobert Mustacchi nvlist_t *nvl;
125*eb00b1c8SRobert Mustacchi nvlist_t *dimms[IMC_MAX_DIMMPERCHAN];
126*eb00b1c8SRobert Mustacchi nvlist_t *ranks[IMC_MAX_RANK_WAYS];
127*eb00b1c8SRobert Mustacchi
128*eb00b1c8SRobert Mustacchi nvl = fnvlist_alloc();
129*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "ich_valid", chan->ich_valid);
130*eb00b1c8SRobert Mustacchi for (i = 0; i < chan->ich_ndimms; i++) {
131*eb00b1c8SRobert Mustacchi nvlist_t *d = fnvlist_alloc();
132*eb00b1c8SRobert Mustacchi imc_dimm_t *dimm = &chan->ich_dimms[i];
133*eb00b1c8SRobert Mustacchi
134*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(d, "idimm_valid", dimm->idimm_valid);
135*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(d, "idimm_present",
136*eb00b1c8SRobert Mustacchi dimm->idimm_present);
137*eb00b1c8SRobert Mustacchi if (!dimm->idimm_present)
138*eb00b1c8SRobert Mustacchi goto add;
139*eb00b1c8SRobert Mustacchi
140*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(d, "idimm_nbanks", dimm->idimm_nbanks);
141*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(d, "idimm_nranks", dimm->idimm_nranks);
142*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(d, "idimm_width", dimm->idimm_width);
143*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(d, "idimm_density", dimm->idimm_density);
144*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(d, "idimm_nrows", dimm->idimm_nrows);
145*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(d, "idimm_ncolumns", dimm->idimm_ncolumns);
146*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(d, "idimm_size", dimm->idimm_size);
147*eb00b1c8SRobert Mustacchi add:
148*eb00b1c8SRobert Mustacchi dimms[i] = d;
149*eb00b1c8SRobert Mustacchi }
150*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "ich_dimms", dimms, i);
151*eb00b1c8SRobert Mustacchi for (i = 0; i < chan->ich_ndimms; i++) {
152*eb00b1c8SRobert Mustacchi nvlist_free(dimms[i]);
153*eb00b1c8SRobert Mustacchi }
154*eb00b1c8SRobert Mustacchi
155*eb00b1c8SRobert Mustacchi fnvlist_add_uint64_array(nvl, "ich_tad_offsets", chan->ich_tad_offsets,
156*eb00b1c8SRobert Mustacchi chan->ich_ntad_offsets);
157*eb00b1c8SRobert Mustacchi
158*eb00b1c8SRobert Mustacchi for (i = 0; i < chan->ich_nrankileaves; i++) {
159*eb00b1c8SRobert Mustacchi uint_t j;
160*eb00b1c8SRobert Mustacchi nvlist_t *r = fnvlist_alloc();
161*eb00b1c8SRobert Mustacchi nvlist_t *ileaves[IMC_MAX_RANK_INTERLEAVES];
162*eb00b1c8SRobert Mustacchi imc_rank_ileave_t *rank = &chan->ich_rankileaves[i];
163*eb00b1c8SRobert Mustacchi
164*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(r, "irle_enabled",
165*eb00b1c8SRobert Mustacchi rank->irle_enabled);
166*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(r, "irle_nways", rank->irle_nways);
167*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(r, "irle_nwaysbits", rank->irle_nwaysbits);
168*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(r, "irle_limit", rank->irle_limit);
169*eb00b1c8SRobert Mustacchi
170*eb00b1c8SRobert Mustacchi for (j = 0; j < rank->irle_nentries; j++) {
171*eb00b1c8SRobert Mustacchi nvlist_t *e = fnvlist_alloc();
172*eb00b1c8SRobert Mustacchi
173*eb00b1c8SRobert Mustacchi fnvlist_add_uint8(e, "irle_target",
174*eb00b1c8SRobert Mustacchi rank->irle_entries[j].irle_target);
175*eb00b1c8SRobert Mustacchi fnvlist_add_uint64(e, "irle_offset",
176*eb00b1c8SRobert Mustacchi rank->irle_entries[j].irle_offset);
177*eb00b1c8SRobert Mustacchi ileaves[j] = e;
178*eb00b1c8SRobert Mustacchi }
179*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(r, "irle_entries", ileaves, j);
180*eb00b1c8SRobert Mustacchi for (j = 0; j < rank->irle_nentries; j++) {
181*eb00b1c8SRobert Mustacchi nvlist_free(ileaves[j]);
182*eb00b1c8SRobert Mustacchi }
183*eb00b1c8SRobert Mustacchi
184*eb00b1c8SRobert Mustacchi ranks[i] = r;
185*eb00b1c8SRobert Mustacchi }
186*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "ich_rankileaves", ranks, i);
187*eb00b1c8SRobert Mustacchi for (i = 0; i < chan->ich_nrankileaves; i++) {
188*eb00b1c8SRobert Mustacchi nvlist_free(ranks[i]);
189*eb00b1c8SRobert Mustacchi }
190*eb00b1c8SRobert Mustacchi
191*eb00b1c8SRobert Mustacchi return (nvl);
192*eb00b1c8SRobert Mustacchi }
193*eb00b1c8SRobert Mustacchi
194*eb00b1c8SRobert Mustacchi static nvlist_t *
imc_dump_mc(imc_mc_t * mc)195*eb00b1c8SRobert Mustacchi imc_dump_mc(imc_mc_t *mc)
196*eb00b1c8SRobert Mustacchi {
197*eb00b1c8SRobert Mustacchi uint_t i;
198*eb00b1c8SRobert Mustacchi nvlist_t *nvl;
199*eb00b1c8SRobert Mustacchi nvlist_t *channels[IMC_MAX_CHANPERMC];
200*eb00b1c8SRobert Mustacchi
201*eb00b1c8SRobert Mustacchi nvl = fnvlist_alloc();
202*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(nvl, "icn_ecc", mc->icn_ecc);
203*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(nvl, "icn_lockstep", mc->icn_lockstep);
204*eb00b1c8SRobert Mustacchi fnvlist_add_boolean_value(nvl, "icn_closed", mc->icn_closed);
205*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "icn_dimm_type", mc->icn_dimm_type);
206*eb00b1c8SRobert Mustacchi
207*eb00b1c8SRobert Mustacchi for (i = 0; i < mc->icn_nchannels; i++) {
208*eb00b1c8SRobert Mustacchi channels[i] = imc_dump_channel(&mc->icn_channels[i]);
209*eb00b1c8SRobert Mustacchi }
210*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "icn_channels", channels, i);
211*eb00b1c8SRobert Mustacchi for (i = 0; i < mc->icn_nchannels; i++) {
212*eb00b1c8SRobert Mustacchi nvlist_free(channels[i]);
213*eb00b1c8SRobert Mustacchi }
214*eb00b1c8SRobert Mustacchi
215*eb00b1c8SRobert Mustacchi return (nvl);
216*eb00b1c8SRobert Mustacchi }
217*eb00b1c8SRobert Mustacchi
218*eb00b1c8SRobert Mustacchi static nvlist_t *
imc_dump_socket(imc_socket_t * sock)219*eb00b1c8SRobert Mustacchi imc_dump_socket(imc_socket_t *sock)
220*eb00b1c8SRobert Mustacchi {
221*eb00b1c8SRobert Mustacchi uint_t i;
222*eb00b1c8SRobert Mustacchi nvlist_t *nvl, *sad;
223*eb00b1c8SRobert Mustacchi nvlist_t *tad[IMC_MAX_TAD];
224*eb00b1c8SRobert Mustacchi nvlist_t *mc[IMC_MAX_IMCPERSOCK];
225*eb00b1c8SRobert Mustacchi
226*eb00b1c8SRobert Mustacchi nvl = fnvlist_alloc();
227*eb00b1c8SRobert Mustacchi
228*eb00b1c8SRobert Mustacchi sad = imc_dump_sad(&sock->isock_sad);
229*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist(nvl, "isock_sad", sad);
230*eb00b1c8SRobert Mustacchi nvlist_free(sad);
231*eb00b1c8SRobert Mustacchi
232*eb00b1c8SRobert Mustacchi for (i = 0; i < sock->isock_ntad; i++) {
233*eb00b1c8SRobert Mustacchi tad[i] = imc_dump_tad(&sock->isock_tad[i]);
234*eb00b1c8SRobert Mustacchi }
235*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "isock_tad", tad, i);
236*eb00b1c8SRobert Mustacchi for (i = 0; i < sock->isock_ntad; i++) {
237*eb00b1c8SRobert Mustacchi fnvlist_free(tad[i]);
238*eb00b1c8SRobert Mustacchi }
239*eb00b1c8SRobert Mustacchi
240*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "isock_nodeid", sock->isock_nodeid);
241*eb00b1c8SRobert Mustacchi
242*eb00b1c8SRobert Mustacchi for (i = 0; i < sock->isock_nimc; i++) {
243*eb00b1c8SRobert Mustacchi mc[i] = imc_dump_mc(&sock->isock_imcs[i]);
244*eb00b1c8SRobert Mustacchi }
245*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(nvl, "isock_imcs", mc, i);
246*eb00b1c8SRobert Mustacchi for (i = 0; i < sock->isock_nimc; i++) {
247*eb00b1c8SRobert Mustacchi fnvlist_free(mc[i]);
248*eb00b1c8SRobert Mustacchi }
249*eb00b1c8SRobert Mustacchi return (nvl);
250*eb00b1c8SRobert Mustacchi }
251*eb00b1c8SRobert Mustacchi
252*eb00b1c8SRobert Mustacchi nvlist_t *
imc_dump_decoder(imc_t * imc)253*eb00b1c8SRobert Mustacchi imc_dump_decoder(imc_t *imc)
254*eb00b1c8SRobert Mustacchi {
255*eb00b1c8SRobert Mustacchi uint_t i;
256*eb00b1c8SRobert Mustacchi nvlist_t *nvl, *invl;
257*eb00b1c8SRobert Mustacchi nvlist_t *sockets[IMC_MAX_SOCKETS];
258*eb00b1c8SRobert Mustacchi
259*eb00b1c8SRobert Mustacchi nvl = fnvlist_alloc();
260*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(nvl, "mc_dump_version", 0);
261*eb00b1c8SRobert Mustacchi fnvlist_add_string(nvl, "mc_dump_driver", "imc");
262*eb00b1c8SRobert Mustacchi
263*eb00b1c8SRobert Mustacchi invl = fnvlist_alloc();
264*eb00b1c8SRobert Mustacchi fnvlist_add_uint32(invl, "imc_gen", imc->imc_gen);
265*eb00b1c8SRobert Mustacchi
266*eb00b1c8SRobert Mustacchi for (i = 0; i < imc->imc_nsockets; i++) {
267*eb00b1c8SRobert Mustacchi sockets[i] = imc_dump_socket(&imc->imc_sockets[i]);
268*eb00b1c8SRobert Mustacchi }
269*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist_array(invl, "imc_sockets", sockets, i);
270*eb00b1c8SRobert Mustacchi fnvlist_add_nvlist(nvl, "imc", invl);
271*eb00b1c8SRobert Mustacchi
272*eb00b1c8SRobert Mustacchi for (i = 0; i < imc->imc_nsockets; i++) {
273*eb00b1c8SRobert Mustacchi nvlist_free(sockets[i]);
274*eb00b1c8SRobert Mustacchi }
275*eb00b1c8SRobert Mustacchi nvlist_free(invl);
276*eb00b1c8SRobert Mustacchi
277*eb00b1c8SRobert Mustacchi return (nvl);
278*eb00b1c8SRobert Mustacchi }
279*eb00b1c8SRobert Mustacchi
280*eb00b1c8SRobert Mustacchi static boolean_t
imc_restore_sad(nvlist_t * nvl,imc_sad_t * sad)281*eb00b1c8SRobert Mustacchi imc_restore_sad(nvlist_t *nvl, imc_sad_t *sad)
282*eb00b1c8SRobert Mustacchi {
283*eb00b1c8SRobert Mustacchi nvlist_t **rules, **routes;
284*eb00b1c8SRobert Mustacchi uint_t i, nroutes;
285*eb00b1c8SRobert Mustacchi
286*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint32(nvl, "isad_flags", &sad->isad_flags) != 0 ||
287*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(nvl, "isad_valid", &sad->isad_valid) != 0 ||
288*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(nvl, "isad_tolm", &sad->isad_tolm) != 0 ||
289*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(nvl, "isad_tohm", &sad->isad_tohm) != 0 ||
290*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "isad_rules",
291*eb00b1c8SRobert Mustacchi &rules, &sad->isad_nrules) != 0) {
292*eb00b1c8SRobert Mustacchi return (B_FALSE);
293*eb00b1c8SRobert Mustacchi }
294*eb00b1c8SRobert Mustacchi
295*eb00b1c8SRobert Mustacchi for (i = 0; i < sad->isad_nrules; i++) {
296*eb00b1c8SRobert Mustacchi imc_sad_rule_t *r = &sad->isad_rules[i];
297*eb00b1c8SRobert Mustacchi uint8_t *targs;
298*eb00b1c8SRobert Mustacchi
299*eb00b1c8SRobert Mustacchi if (nvlist_lookup_boolean_value(rules[i], "isr_enable",
300*eb00b1c8SRobert Mustacchi &r->isr_enable) != 0 ||
301*eb00b1c8SRobert Mustacchi nvlist_lookup_boolean_value(rules[i], "isr_a7mode",
302*eb00b1c8SRobert Mustacchi &r->isr_a7mode) != 0 ||
303*eb00b1c8SRobert Mustacchi nvlist_lookup_boolean_value(rules[i], "isr_need_mod3",
304*eb00b1c8SRobert Mustacchi &r->isr_need_mod3) != 0 ||
305*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(rules[i], "isr_limit",
306*eb00b1c8SRobert Mustacchi &r->isr_limit) != 0 ||
307*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(rules[i], "isr_type",
308*eb00b1c8SRobert Mustacchi &r->isr_type) != 0 ||
309*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(rules[i], "isr_imode",
310*eb00b1c8SRobert Mustacchi &r->isr_imode) != 0 ||
311*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(rules[i], "isr_mod_mode",
312*eb00b1c8SRobert Mustacchi &r->isr_mod_mode) != 0 ||
313*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(rules[i], "isr_mod_type",
314*eb00b1c8SRobert Mustacchi &r->isr_mod_type) != 0 ||
315*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8_array(rules[i], "isr_targets", &targs,
316*eb00b1c8SRobert Mustacchi &r->isr_ntargets) != 0 ||
317*eb00b1c8SRobert Mustacchi r->isr_ntargets > IMC_MAX_SAD_RULES) {
318*eb00b1c8SRobert Mustacchi return (B_FALSE);
319*eb00b1c8SRobert Mustacchi }
320*eb00b1c8SRobert Mustacchi
321*eb00b1c8SRobert Mustacchi bcopy(targs, r->isr_targets, r->isr_ntargets *
322*eb00b1c8SRobert Mustacchi sizeof (uint8_t));
323*eb00b1c8SRobert Mustacchi }
324*eb00b1c8SRobert Mustacchi
325*eb00b1c8SRobert Mustacchi /*
326*eb00b1c8SRobert Mustacchi * The mcroutes entry right now is only included conditionally.
327*eb00b1c8SRobert Mustacchi */
328*eb00b1c8SRobert Mustacchi if (nvlist_lookup_nvlist_array(nvl, "isad_mcroute", &routes,
329*eb00b1c8SRobert Mustacchi &nroutes) == 0) {
330*eb00b1c8SRobert Mustacchi if (nroutes > IMC_MAX_SAD_MCROUTES)
331*eb00b1c8SRobert Mustacchi return (B_FALSE);
332*eb00b1c8SRobert Mustacchi sad->isad_mcroute.ismc_nroutes = nroutes;
333*eb00b1c8SRobert Mustacchi for (i = 0; i < nroutes; i++) {
334*eb00b1c8SRobert Mustacchi imc_sad_mcroute_entry_t *r =
335*eb00b1c8SRobert Mustacchi &sad->isad_mcroute.ismc_mcroutes[i];
336*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint8(routes[i], "ismce_imc",
337*eb00b1c8SRobert Mustacchi &r->ismce_imc) != 0 ||
338*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(routes[i], "ismce_pchannel",
339*eb00b1c8SRobert Mustacchi &r->ismce_pchannel) != 0) {
340*eb00b1c8SRobert Mustacchi return (B_FALSE);
341*eb00b1c8SRobert Mustacchi }
342*eb00b1c8SRobert Mustacchi }
343*eb00b1c8SRobert Mustacchi }
344*eb00b1c8SRobert Mustacchi
345*eb00b1c8SRobert Mustacchi return (B_TRUE);
346*eb00b1c8SRobert Mustacchi }
347*eb00b1c8SRobert Mustacchi
348*eb00b1c8SRobert Mustacchi static boolean_t
imc_restore_tad(nvlist_t * nvl,imc_tad_t * tad)349*eb00b1c8SRobert Mustacchi imc_restore_tad(nvlist_t *nvl, imc_tad_t *tad)
350*eb00b1c8SRobert Mustacchi {
351*eb00b1c8SRobert Mustacchi nvlist_t **rules;
352*eb00b1c8SRobert Mustacchi
353*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint32(nvl, "itad_valid", &tad->itad_valid) != 0 ||
354*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(nvl, "itad_flags", &tad->itad_flags) != 0 ||
355*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "itad_rules", &rules,
356*eb00b1c8SRobert Mustacchi &tad->itad_nrules) != 0 || tad->itad_nrules > IMC_MAX_TAD_RULES) {
357*eb00b1c8SRobert Mustacchi return (B_FALSE);
358*eb00b1c8SRobert Mustacchi }
359*eb00b1c8SRobert Mustacchi
360*eb00b1c8SRobert Mustacchi for (uint_t i = 0; i < tad->itad_nrules; i++) {
361*eb00b1c8SRobert Mustacchi imc_tad_rule_t *r = &tad->itad_rules[i];
362*eb00b1c8SRobert Mustacchi uint8_t *targs;
363*eb00b1c8SRobert Mustacchi
364*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint64(rules[i], "itr_base",
365*eb00b1c8SRobert Mustacchi &r->itr_base) != 0 ||
366*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(rules[i], "itr_limit",
367*eb00b1c8SRobert Mustacchi &r->itr_limit) != 0 ||
368*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(rules[i], "itr_sock_way",
369*eb00b1c8SRobert Mustacchi &r->itr_sock_way) != 0 ||
370*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(rules[i], "itr_chan_way",
371*eb00b1c8SRobert Mustacchi &r->itr_chan_way) != 0 ||
372*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(rules[i], "itr_sock_gran",
373*eb00b1c8SRobert Mustacchi &r->itr_sock_gran) != 0 ||
374*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(rules[i], "itr_chan_gran",
375*eb00b1c8SRobert Mustacchi &r->itr_chan_gran) != 0 ||
376*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8_array(rules[i], "itr_targets",
377*eb00b1c8SRobert Mustacchi &targs, &r->itr_ntargets) != 0 ||
378*eb00b1c8SRobert Mustacchi r->itr_ntargets > IMC_MAX_TAD_TARGETS) {
379*eb00b1c8SRobert Mustacchi return (B_FALSE);
380*eb00b1c8SRobert Mustacchi }
381*eb00b1c8SRobert Mustacchi
382*eb00b1c8SRobert Mustacchi bcopy(targs, r->itr_targets, r->itr_ntargets *
383*eb00b1c8SRobert Mustacchi sizeof (uint8_t));
384*eb00b1c8SRobert Mustacchi }
385*eb00b1c8SRobert Mustacchi
386*eb00b1c8SRobert Mustacchi return (B_TRUE);
387*eb00b1c8SRobert Mustacchi }
388*eb00b1c8SRobert Mustacchi
389*eb00b1c8SRobert Mustacchi static boolean_t
imc_restore_channel(nvlist_t * nvl,imc_channel_t * chan)390*eb00b1c8SRobert Mustacchi imc_restore_channel(nvlist_t *nvl, imc_channel_t *chan)
391*eb00b1c8SRobert Mustacchi {
392*eb00b1c8SRobert Mustacchi nvlist_t **dimms, **rir;
393*eb00b1c8SRobert Mustacchi uint64_t *tadoff;
394*eb00b1c8SRobert Mustacchi
395*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint32(nvl, "ich_valid", &chan->ich_valid) != 0 ||
396*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "ich_dimms", &dimms,
397*eb00b1c8SRobert Mustacchi &chan->ich_ndimms) != 0 ||
398*eb00b1c8SRobert Mustacchi chan->ich_ndimms > IMC_MAX_DIMMPERCHAN ||
399*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64_array(nvl, "ich_tad_offsets", &tadoff,
400*eb00b1c8SRobert Mustacchi &chan->ich_ntad_offsets) != 0 ||
401*eb00b1c8SRobert Mustacchi chan->ich_ntad_offsets > IMC_MAX_TAD_RULES ||
402*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "ich_rankileaves", &rir,
403*eb00b1c8SRobert Mustacchi &chan->ich_nrankileaves) != 0 ||
404*eb00b1c8SRobert Mustacchi chan->ich_nrankileaves > IMC_MAX_RANK_WAYS) {
405*eb00b1c8SRobert Mustacchi return (B_FALSE);
406*eb00b1c8SRobert Mustacchi }
407*eb00b1c8SRobert Mustacchi
408*eb00b1c8SRobert Mustacchi for (uint_t i = 0; i < chan->ich_ndimms; i++) {
409*eb00b1c8SRobert Mustacchi imc_dimm_t *d = &chan->ich_dimms[i];
410*eb00b1c8SRobert Mustacchi
411*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint32(dimms[i], "idimm_valid",
412*eb00b1c8SRobert Mustacchi &d->idimm_valid) != 0 ||
413*eb00b1c8SRobert Mustacchi nvlist_lookup_boolean_value(dimms[i], "idimm_present",
414*eb00b1c8SRobert Mustacchi &d->idimm_present) != 0) {
415*eb00b1c8SRobert Mustacchi return (B_FALSE);
416*eb00b1c8SRobert Mustacchi }
417*eb00b1c8SRobert Mustacchi
418*eb00b1c8SRobert Mustacchi if (!d->idimm_present)
419*eb00b1c8SRobert Mustacchi continue;
420*eb00b1c8SRobert Mustacchi
421*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint8(dimms[i], "idimm_nbanks",
422*eb00b1c8SRobert Mustacchi &d->idimm_nbanks) != 0 ||
423*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(dimms[i], "idimm_nranks",
424*eb00b1c8SRobert Mustacchi &d->idimm_nranks) != 0 ||
425*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(dimms[i], "idimm_width",
426*eb00b1c8SRobert Mustacchi &d->idimm_width) != 0 ||
427*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(dimms[i], "idimm_density",
428*eb00b1c8SRobert Mustacchi &d->idimm_density) != 0 ||
429*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(dimms[i], "idimm_nrows",
430*eb00b1c8SRobert Mustacchi &d->idimm_nrows) != 0 ||
431*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(dimms[i], "idimm_ncolumns",
432*eb00b1c8SRobert Mustacchi &d->idimm_ncolumns) != 0 ||
433*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(dimms[i], "idimm_size",
434*eb00b1c8SRobert Mustacchi &d->idimm_size) != 0) {
435*eb00b1c8SRobert Mustacchi return (B_FALSE);
436*eb00b1c8SRobert Mustacchi }
437*eb00b1c8SRobert Mustacchi }
438*eb00b1c8SRobert Mustacchi
439*eb00b1c8SRobert Mustacchi bcopy(tadoff, chan->ich_tad_offsets, chan->ich_ntad_offsets *
440*eb00b1c8SRobert Mustacchi sizeof (uint64_t));
441*eb00b1c8SRobert Mustacchi
442*eb00b1c8SRobert Mustacchi for (uint_t i = 0; i < chan->ich_nrankileaves; i++) {
443*eb00b1c8SRobert Mustacchi nvlist_t **ileaves;
444*eb00b1c8SRobert Mustacchi imc_rank_ileave_t *r = &chan->ich_rankileaves[i];
445*eb00b1c8SRobert Mustacchi
446*eb00b1c8SRobert Mustacchi if (nvlist_lookup_boolean_value(rir[i], "irle_enabled",
447*eb00b1c8SRobert Mustacchi &r->irle_enabled) != 0 ||
448*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(rir[i], "irle_nways",
449*eb00b1c8SRobert Mustacchi &r->irle_nways) != 0 ||
450*eb00b1c8SRobert Mustacchi nvlist_lookup_uint8(rir[i], "irle_nwaysbits",
451*eb00b1c8SRobert Mustacchi &r->irle_nwaysbits) != 0 ||
452*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(rir[i], "irle_limit",
453*eb00b1c8SRobert Mustacchi &r->irle_limit) != 0 ||
454*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(rir[i], "irle_entries",
455*eb00b1c8SRobert Mustacchi &ileaves, &r->irle_nentries) != 0 ||
456*eb00b1c8SRobert Mustacchi r->irle_nentries > IMC_MAX_RANK_INTERLEAVES) {
457*eb00b1c8SRobert Mustacchi return (B_FALSE);
458*eb00b1c8SRobert Mustacchi }
459*eb00b1c8SRobert Mustacchi
460*eb00b1c8SRobert Mustacchi for (uint_t j = 0; j < r->irle_nentries; j++) {
461*eb00b1c8SRobert Mustacchi imc_rank_ileave_entry_t *ril = &r->irle_entries[j];
462*eb00b1c8SRobert Mustacchi
463*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint8(ileaves[j], "irle_target",
464*eb00b1c8SRobert Mustacchi &ril->irle_target) != 0 ||
465*eb00b1c8SRobert Mustacchi nvlist_lookup_uint64(ileaves[j], "irle_offset",
466*eb00b1c8SRobert Mustacchi &ril->irle_offset) != 0) {
467*eb00b1c8SRobert Mustacchi return (B_FALSE);
468*eb00b1c8SRobert Mustacchi }
469*eb00b1c8SRobert Mustacchi }
470*eb00b1c8SRobert Mustacchi }
471*eb00b1c8SRobert Mustacchi
472*eb00b1c8SRobert Mustacchi return (B_TRUE);
473*eb00b1c8SRobert Mustacchi }
474*eb00b1c8SRobert Mustacchi
475*eb00b1c8SRobert Mustacchi static boolean_t
imc_restore_mc(nvlist_t * nvl,imc_mc_t * mc)476*eb00b1c8SRobert Mustacchi imc_restore_mc(nvlist_t *nvl, imc_mc_t *mc)
477*eb00b1c8SRobert Mustacchi {
478*eb00b1c8SRobert Mustacchi nvlist_t **channels;
479*eb00b1c8SRobert Mustacchi
480*eb00b1c8SRobert Mustacchi if (nvlist_lookup_boolean_value(nvl, "icn_ecc", &mc->icn_ecc) != 0 ||
481*eb00b1c8SRobert Mustacchi nvlist_lookup_boolean_value(nvl, "icn_lockstep",
482*eb00b1c8SRobert Mustacchi &mc->icn_lockstep) != 0 ||
483*eb00b1c8SRobert Mustacchi nvlist_lookup_boolean_value(nvl, "icn_closed",
484*eb00b1c8SRobert Mustacchi &mc->icn_closed) != 0 ||
485*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(nvl, "icn_dimm_type",
486*eb00b1c8SRobert Mustacchi &mc->icn_dimm_type) != 0 ||
487*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "icn_channels", &channels,
488*eb00b1c8SRobert Mustacchi &mc->icn_nchannels) != 0 || mc->icn_nchannels > IMC_MAX_CHANPERMC) {
489*eb00b1c8SRobert Mustacchi return (B_FALSE);
490*eb00b1c8SRobert Mustacchi }
491*eb00b1c8SRobert Mustacchi
492*eb00b1c8SRobert Mustacchi for (uint_t i = 0; i < mc->icn_nchannels; i++) {
493*eb00b1c8SRobert Mustacchi if (!imc_restore_channel(channels[i], &mc->icn_channels[i])) {
494*eb00b1c8SRobert Mustacchi return (B_FALSE);
495*eb00b1c8SRobert Mustacchi }
496*eb00b1c8SRobert Mustacchi }
497*eb00b1c8SRobert Mustacchi
498*eb00b1c8SRobert Mustacchi return (B_TRUE);
499*eb00b1c8SRobert Mustacchi }
500*eb00b1c8SRobert Mustacchi
501*eb00b1c8SRobert Mustacchi static boolean_t
imc_restore_socket(nvlist_t * nvl,imc_socket_t * sock)502*eb00b1c8SRobert Mustacchi imc_restore_socket(nvlist_t *nvl, imc_socket_t *sock)
503*eb00b1c8SRobert Mustacchi {
504*eb00b1c8SRobert Mustacchi uint_t i;
505*eb00b1c8SRobert Mustacchi nvlist_t *sad, **tads, **imcs;
506*eb00b1c8SRobert Mustacchi
507*eb00b1c8SRobert Mustacchi if (nvlist_lookup_nvlist(nvl, "isock_sad", &sad) != 0 ||
508*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "isock_tad", &tads,
509*eb00b1c8SRobert Mustacchi &sock->isock_ntad) != 0 ||
510*eb00b1c8SRobert Mustacchi nvlist_lookup_uint32(nvl, "isock_nodeid",
511*eb00b1c8SRobert Mustacchi &sock->isock_nodeid) != 0 ||
512*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(nvl, "isock_imcs", &imcs,
513*eb00b1c8SRobert Mustacchi &sock->isock_nimc) != 0 ||
514*eb00b1c8SRobert Mustacchi sock->isock_ntad > IMC_MAX_TAD ||
515*eb00b1c8SRobert Mustacchi sock->isock_nimc > IMC_MAX_IMCPERSOCK) {
516*eb00b1c8SRobert Mustacchi return (B_FALSE);
517*eb00b1c8SRobert Mustacchi }
518*eb00b1c8SRobert Mustacchi
519*eb00b1c8SRobert Mustacchi if (!imc_restore_sad(sad, &sock->isock_sad)) {
520*eb00b1c8SRobert Mustacchi return (B_FALSE);
521*eb00b1c8SRobert Mustacchi }
522*eb00b1c8SRobert Mustacchi
523*eb00b1c8SRobert Mustacchi for (i = 0; i < sock->isock_ntad; i++) {
524*eb00b1c8SRobert Mustacchi if (!imc_restore_tad(tads[i], &sock->isock_tad[i])) {
525*eb00b1c8SRobert Mustacchi return (B_FALSE);
526*eb00b1c8SRobert Mustacchi }
527*eb00b1c8SRobert Mustacchi }
528*eb00b1c8SRobert Mustacchi
529*eb00b1c8SRobert Mustacchi for (i = 0; i < sock->isock_nimc; i++) {
530*eb00b1c8SRobert Mustacchi if (!imc_restore_mc(imcs[i], &sock->isock_imcs[i])) {
531*eb00b1c8SRobert Mustacchi return (B_FALSE);
532*eb00b1c8SRobert Mustacchi }
533*eb00b1c8SRobert Mustacchi }
534*eb00b1c8SRobert Mustacchi
535*eb00b1c8SRobert Mustacchi return (B_TRUE);
536*eb00b1c8SRobert Mustacchi }
537*eb00b1c8SRobert Mustacchi
538*eb00b1c8SRobert Mustacchi boolean_t
imc_restore_decoder(nvlist_t * nvl,imc_t * imc)539*eb00b1c8SRobert Mustacchi imc_restore_decoder(nvlist_t *nvl, imc_t *imc)
540*eb00b1c8SRobert Mustacchi {
541*eb00b1c8SRobert Mustacchi uint_t i;
542*eb00b1c8SRobert Mustacchi uint32_t vers;
543*eb00b1c8SRobert Mustacchi nvlist_t *invl, **socks;
544*eb00b1c8SRobert Mustacchi char *driver;
545*eb00b1c8SRobert Mustacchi
546*eb00b1c8SRobert Mustacchi bzero(imc, sizeof (imc_t));
547*eb00b1c8SRobert Mustacchi
548*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint32(nvl, "mc_dump_version", &vers) != 0 ||
549*eb00b1c8SRobert Mustacchi vers != 0 ||
550*eb00b1c8SRobert Mustacchi nvlist_lookup_string(nvl, "mc_dump_driver", &driver) != 0 ||
551*eb00b1c8SRobert Mustacchi strcmp(driver, "imc") != 0 ||
552*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist(nvl, "imc", &invl) != 0) {
553*eb00b1c8SRobert Mustacchi return (B_FALSE);
554*eb00b1c8SRobert Mustacchi }
555*eb00b1c8SRobert Mustacchi
556*eb00b1c8SRobert Mustacchi if (nvlist_lookup_uint32(invl, "imc_gen", &imc->imc_gen) != 0 ||
557*eb00b1c8SRobert Mustacchi nvlist_lookup_nvlist_array(invl, "imc_sockets", &socks,
558*eb00b1c8SRobert Mustacchi &imc->imc_nsockets) != 0 ||
559*eb00b1c8SRobert Mustacchi imc->imc_nsockets > IMC_MAX_SOCKETS) {
560*eb00b1c8SRobert Mustacchi return (B_FALSE);
561*eb00b1c8SRobert Mustacchi }
562*eb00b1c8SRobert Mustacchi
563*eb00b1c8SRobert Mustacchi for (i = 0; i < imc->imc_nsockets; i++) {
564*eb00b1c8SRobert Mustacchi if (!imc_restore_socket(socks[i], &imc->imc_sockets[i]))
565*eb00b1c8SRobert Mustacchi return (B_FALSE);
566*eb00b1c8SRobert Mustacchi }
567*eb00b1c8SRobert Mustacchi
568*eb00b1c8SRobert Mustacchi return (B_TRUE);
569*eb00b1c8SRobert Mustacchi }
570