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 #include <string.h>
17*eb00b1c8SRobert Mustacchi #include <stdio.h>
18*eb00b1c8SRobert Mustacchi #include <stdarg.h>
19*eb00b1c8SRobert Mustacchi #include <stdlib.h>
20*eb00b1c8SRobert Mustacchi #include <err.h>
21*eb00b1c8SRobert Mustacchi 
22*eb00b1c8SRobert Mustacchi #include "imc_test.h"
23*eb00b1c8SRobert Mustacchi 
24*eb00b1c8SRobert Mustacchi /*
25*eb00b1c8SRobert Mustacchi  * Test runner for the IMC driver and its decoder. This operates by creating
26*eb00b1c8SRobert Mustacchi  * fake topologies and then building a copy of the decoder into this.
27*eb00b1c8SRobert Mustacchi  */
28*eb00b1c8SRobert Mustacchi 
29*eb00b1c8SRobert Mustacchi static void
imc_print(const char * fmt,...)30*eb00b1c8SRobert Mustacchi imc_print(const char *fmt, ...)
31*eb00b1c8SRobert Mustacchi {
32*eb00b1c8SRobert Mustacchi 	va_list ap;
33*eb00b1c8SRobert Mustacchi 
34*eb00b1c8SRobert Mustacchi 	va_start(ap, fmt);
35*eb00b1c8SRobert Mustacchi 	(void) vfprintf(stdout, fmt, ap);
36*eb00b1c8SRobert Mustacchi 	va_end(ap);
37*eb00b1c8SRobert Mustacchi }
38*eb00b1c8SRobert Mustacchi 
39*eb00b1c8SRobert Mustacchi static const char *
imc_test_strerror(imc_decode_failure_t fail)40*eb00b1c8SRobert Mustacchi imc_test_strerror(imc_decode_failure_t fail)
41*eb00b1c8SRobert Mustacchi {
42*eb00b1c8SRobert Mustacchi 	switch (fail) {
43*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NONE:
44*eb00b1c8SRobert Mustacchi 		return ("Actually succeeded");
45*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_LEGACY_RANGE:
46*eb00b1c8SRobert Mustacchi 		return ("Asked to decode legacy address");
47*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_SOCKET:
48*eb00b1c8SRobert Mustacchi 		return ("BAD socket data");
49*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_SAD:
50*eb00b1c8SRobert Mustacchi 		return ("BAD SAD data");
51*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_OUTSIDE_DRAM:
52*eb00b1c8SRobert Mustacchi 		return ("Address not DRAM");
53*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NO_SAD_RULE:
54*eb00b1c8SRobert Mustacchi 		return ("No valid SAD rule");
55*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_SAD_INTERLEAVE:
56*eb00b1c8SRobert Mustacchi 		return ("SAD bad interleave target");
57*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_REMOTE_MC_ROUTE:
58*eb00b1c8SRobert Mustacchi 		return ("SAD MC_ROUTE refers to non-existent socket");
59*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_SEARCH_LOOP:
60*eb00b1c8SRobert Mustacchi 		return ("SAD search looped");
61*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_BAD_MOD:
62*eb00b1c8SRobert Mustacchi 		return ("SAD has a bad mod rule");
63*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_BAD_SOCKET:
64*eb00b1c8SRobert Mustacchi 		return ("SAD has a bad Socket target");
65*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_BAD_TAD:
66*eb00b1c8SRobert Mustacchi 		return ("SAD has a bad TAD target");
67*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NO_TAD_RULE:
68*eb00b1c8SRobert Mustacchi 		return ("No valid TAD rule");
69*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_TAD_3_ILEAVE:
70*eb00b1c8SRobert Mustacchi 		return ("Unsupported 3-way channel interleave");
71*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_TAD_BAD_TARGET_INDEX:
72*eb00b1c8SRobert Mustacchi 		return ("Bad TAD target index");
73*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_CHANNEL_ID:
74*eb00b1c8SRobert Mustacchi 		return ("Bad channel ID");
75*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_CHANNEL_TAD_OFFSET:
76*eb00b1c8SRobert Mustacchi 		return ("Bad channel tad offset");
77*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NO_RIR_RULE:
78*eb00b1c8SRobert Mustacchi 		return ("No valid rank interleave rule");
79*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_RIR_ILEAVE_TARGET:
80*eb00b1c8SRobert Mustacchi 		return ("Bad rank interleave target");
81*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_DIMM_INDEX:
82*eb00b1c8SRobert Mustacchi 		return ("Bad DIMM target index");
83*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_DIMM_NOT_PRESENT:
84*eb00b1c8SRobert Mustacchi 		return ("DIMM not present");
85*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_DIMM_RANK:
86*eb00b1c8SRobert Mustacchi 		return ("Bad DIMM rank");
87*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_CHANOFF_UNDERFLOW:
88*eb00b1c8SRobert Mustacchi 		return ("Channel address offset calculation underflow");
89*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_RANKOFF_UNDERFLOW:
90*eb00b1c8SRobert Mustacchi 		return ("Rank address offset calculation underflow");
91*eb00b1c8SRobert Mustacchi 	default:
92*eb00b1c8SRobert Mustacchi 		return ("<unknown>");
93*eb00b1c8SRobert Mustacchi 	}
94*eb00b1c8SRobert Mustacchi }
95*eb00b1c8SRobert Mustacchi 
96*eb00b1c8SRobert Mustacchi static const char *
imc_test_strenum(imc_decode_failure_t fail)97*eb00b1c8SRobert Mustacchi imc_test_strenum(imc_decode_failure_t fail)
98*eb00b1c8SRobert Mustacchi {
99*eb00b1c8SRobert Mustacchi 	switch (fail) {
100*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NONE:
101*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_NONE");
102*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_LEGACY_RANGE:
103*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_LEGACY_RANGE");
104*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_SOCKET:
105*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_SOCKET");
106*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_SAD:
107*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_SAD");
108*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_OUTSIDE_DRAM:
109*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_OUTSIDE_DRAM");
110*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NO_SAD_RULE:
111*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_NO_SAD_RULE");
112*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_SAD_INTERLEAVE:
113*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_SAD_INTERLEAVE");
114*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_REMOTE_MC_ROUTE:
115*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_REMOTE_MC_ROUTE");
116*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_SEARCH_LOOP:
117*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_SAD_SEARCH_LOOP");
118*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_BAD_MOD:
119*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_SAD_BAD_MOD");
120*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_BAD_SOCKET:
121*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_SAD_BAD_SOCKET");
122*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_SAD_BAD_TAD:
123*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_SAD_BAD_TAD");
124*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NO_TAD_RULE:
125*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_NO_TAD_RULE");
126*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_TAD_3_ILEAVE:
127*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_TAD_3_ILEAVE");
128*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_TAD_BAD_TARGET_INDEX:
129*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_TAD_BAD_TARGET_INDEX");
130*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_CHANNEL_ID:
131*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_CHANNEL_ID");
132*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_CHANNEL_TAD_OFFSET:
133*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_CHANNEL_TAD_OFFSET");
134*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_NO_RIR_RULE:
135*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_NO_RIR_RULE");
136*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_RIR_ILEAVE_TARGET:
137*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_RIR_ILEAVE_TARGET");
138*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_DIMM_INDEX:
139*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_DIMM_INDEX");
140*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_DIMM_NOT_PRESENT:
141*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_DIMM_NOT_PRESENT");
142*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_BAD_DIMM_RANK:
143*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_BAD_DIMM_RANK");
144*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_CHANOFF_UNDERFLOW:
145*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_CHANOFF_UNDERFLOW");
146*eb00b1c8SRobert Mustacchi 	case IMC_DECODE_F_RANKOFF_UNDERFLOW:
147*eb00b1c8SRobert Mustacchi 		return ("IMC_DECODE_F_RANKOFF_UNDERFLOW");
148*eb00b1c8SRobert Mustacchi 	default:
149*eb00b1c8SRobert Mustacchi 		return ("<unknown>");
150*eb00b1c8SRobert Mustacchi 	}
151*eb00b1c8SRobert Mustacchi }
152*eb00b1c8SRobert Mustacchi 
153*eb00b1c8SRobert Mustacchi static uint_t
imc_test_run_one(const imc_test_case_t * test)154*eb00b1c8SRobert Mustacchi imc_test_run_one(const imc_test_case_t *test)
155*eb00b1c8SRobert Mustacchi {
156*eb00b1c8SRobert Mustacchi 	imc_decode_state_t dec;
157*eb00b1c8SRobert Mustacchi 	boolean_t pass;
158*eb00b1c8SRobert Mustacchi 
159*eb00b1c8SRobert Mustacchi 	imc_print("Running test: %s\n", test->itc_desc);
160*eb00b1c8SRobert Mustacchi 	imc_print("\tDecoding address: 0x%" PRIx64 "\n", test->itc_pa);
161*eb00b1c8SRobert Mustacchi 
162*eb00b1c8SRobert Mustacchi 	(void) memset(&dec, '\0', sizeof (dec));
163*eb00b1c8SRobert Mustacchi 	pass = imc_decode_pa(test->itc_imc, test->itc_pa, &dec);
164*eb00b1c8SRobert Mustacchi 	if (pass && !test->itc_pass) {
165*eb00b1c8SRobert Mustacchi 		imc_print("\tdecode unexpectedly succeeded\n");
166*eb00b1c8SRobert Mustacchi 		imc_print("\texpected error '%s' (%s/0x%x)\n",
167*eb00b1c8SRobert Mustacchi 		    imc_test_strerror(test->itc_fail),
168*eb00b1c8SRobert Mustacchi 		    imc_test_strenum(test->itc_fail),
169*eb00b1c8SRobert Mustacchi 		    test->itc_fail);
170*eb00b1c8SRobert Mustacchi 		imc_print("\t\tdecoded socket: %u\n", dec.ids_nodeid);
171*eb00b1c8SRobert Mustacchi 		imc_print("\t\tdecoded tad: %u\n", dec.ids_tadid);
172*eb00b1c8SRobert Mustacchi 		imc_print("\t\tdecoded channel: %u\n",
173*eb00b1c8SRobert Mustacchi 		    dec.ids_channelid);
174*eb00b1c8SRobert Mustacchi 		imc_print("\t\tdecoded channel address: 0x%" PRIx64 "\n",
175*eb00b1c8SRobert Mustacchi 		    dec.ids_chanaddr);
176*eb00b1c8SRobert Mustacchi 		imc_print("\t\tdecoded rank: %u\n", dec.ids_rankid);
177*eb00b1c8SRobert Mustacchi 		imc_print("\t\tdecoded rank address: 0x%" PRIx64 "\n",
178*eb00b1c8SRobert Mustacchi 		    dec.ids_rankaddr);
179*eb00b1c8SRobert Mustacchi 		imc_print("\ttest failed\n");
180*eb00b1c8SRobert Mustacchi 
181*eb00b1c8SRobert Mustacchi 		return (1);
182*eb00b1c8SRobert Mustacchi 	} else if (pass) {
183*eb00b1c8SRobert Mustacchi 		uint_t err = 0;
184*eb00b1c8SRobert Mustacchi 
185*eb00b1c8SRobert Mustacchi 		if (test->itc_nodeid != UINT32_MAX &&
186*eb00b1c8SRobert Mustacchi 		    test->itc_nodeid != dec.ids_nodeid) {
187*eb00b1c8SRobert Mustacchi 			imc_print("\tsocket mismatch\n"
188*eb00b1c8SRobert Mustacchi 			    "\t\texpected %u\n\t\tfound %u\n",
189*eb00b1c8SRobert Mustacchi 			    test->itc_nodeid, dec.ids_nodeid);
190*eb00b1c8SRobert Mustacchi 			err |= 1;
191*eb00b1c8SRobert Mustacchi 		}
192*eb00b1c8SRobert Mustacchi 
193*eb00b1c8SRobert Mustacchi 		if (test->itc_tadid != UINT32_MAX &&
194*eb00b1c8SRobert Mustacchi 		    test->itc_tadid != dec.ids_tadid) {
195*eb00b1c8SRobert Mustacchi 			imc_print("\tTAD mismatch\n"
196*eb00b1c8SRobert Mustacchi 			    "\t\texpected %u\n\t\tfound %u\n",
197*eb00b1c8SRobert Mustacchi 			    test->itc_tadid, dec.ids_tadid);
198*eb00b1c8SRobert Mustacchi 			err |= 1;
199*eb00b1c8SRobert Mustacchi 		}
200*eb00b1c8SRobert Mustacchi 
201*eb00b1c8SRobert Mustacchi 		if (test->itc_channelid != UINT32_MAX &&
202*eb00b1c8SRobert Mustacchi 		    test->itc_channelid != dec.ids_channelid) {
203*eb00b1c8SRobert Mustacchi 			imc_print("\tchannel mismatch\n"
204*eb00b1c8SRobert Mustacchi 			    "\t\texpected %u\n\t\tfound %u\n",
205*eb00b1c8SRobert Mustacchi 			    test->itc_channelid, dec.ids_channelid);
206*eb00b1c8SRobert Mustacchi 			err |= 1;
207*eb00b1c8SRobert Mustacchi 		}
208*eb00b1c8SRobert Mustacchi 
209*eb00b1c8SRobert Mustacchi 		if (test->itc_chanaddr != UINT64_MAX &&
210*eb00b1c8SRobert Mustacchi 		    test->itc_chanaddr != dec.ids_chanaddr) {
211*eb00b1c8SRobert Mustacchi 			imc_print("\tchannel address mismatch\n"
212*eb00b1c8SRobert Mustacchi 			    "\t\texpected 0x%" PRIx64 "\n\t\t"
213*eb00b1c8SRobert Mustacchi 			    "found 0x%" PRIx64 "\n",
214*eb00b1c8SRobert Mustacchi 			    test->itc_chanaddr, dec.ids_chanaddr);
215*eb00b1c8SRobert Mustacchi 			err |= 1;
216*eb00b1c8SRobert Mustacchi 		}
217*eb00b1c8SRobert Mustacchi 
218*eb00b1c8SRobert Mustacchi 		if (test->itc_dimmid != UINT32_MAX &&
219*eb00b1c8SRobert Mustacchi 		    test->itc_dimmid != dec.ids_dimmid) {
220*eb00b1c8SRobert Mustacchi 			imc_print("\tDIMM mismatch\n"
221*eb00b1c8SRobert Mustacchi 			    "\t\texpected %u\n\t\tfound %u\n",
222*eb00b1c8SRobert Mustacchi 			    test->itc_dimmid, dec.ids_dimmid);
223*eb00b1c8SRobert Mustacchi 			err |= 1;
224*eb00b1c8SRobert Mustacchi 		}
225*eb00b1c8SRobert Mustacchi 
226*eb00b1c8SRobert Mustacchi 		if (test->itc_rankid != UINT32_MAX &&
227*eb00b1c8SRobert Mustacchi 		    test->itc_rankid != dec.ids_rankid) {
228*eb00b1c8SRobert Mustacchi 			imc_print("\trank mismatch\n"
229*eb00b1c8SRobert Mustacchi 			    "\t\texpected %u\n\t\tfound %u\n",
230*eb00b1c8SRobert Mustacchi 			    test->itc_rankid, dec.ids_rankid);
231*eb00b1c8SRobert Mustacchi 			err |= 1;
232*eb00b1c8SRobert Mustacchi 		}
233*eb00b1c8SRobert Mustacchi 
234*eb00b1c8SRobert Mustacchi 		if (test->itc_rankaddr != UINT64_MAX &&
235*eb00b1c8SRobert Mustacchi 		    test->itc_rankaddr != dec.ids_rankaddr) {
236*eb00b1c8SRobert Mustacchi 			imc_print("\trank address mismatch\n"
237*eb00b1c8SRobert Mustacchi 			    "\t\texpected 0x%" PRIx64 "\n\t\t"
238*eb00b1c8SRobert Mustacchi 			    "found 0x%" PRIx64 "\n",
239*eb00b1c8SRobert Mustacchi 			    test->itc_rankaddr, dec.ids_rankaddr);
240*eb00b1c8SRobert Mustacchi 			err |= 1;
241*eb00b1c8SRobert Mustacchi 		}
242*eb00b1c8SRobert Mustacchi 
243*eb00b1c8SRobert Mustacchi 		if (err) {
244*eb00b1c8SRobert Mustacchi 			imc_print("\tDecoding failed\n");
245*eb00b1c8SRobert Mustacchi 		} else {
246*eb00b1c8SRobert Mustacchi 			imc_print("\tDecoded successfully\n");
247*eb00b1c8SRobert Mustacchi 		}
248*eb00b1c8SRobert Mustacchi 
249*eb00b1c8SRobert Mustacchi 		return (err);
250*eb00b1c8SRobert Mustacchi 	} else if (!pass && !test->itc_pass) {
251*eb00b1c8SRobert Mustacchi 		if (dec.ids_fail != test->itc_fail) {
252*eb00b1c8SRobert Mustacchi 			imc_print("\terror mismatch\n"
253*eb00b1c8SRobert Mustacchi 			    "\t\texpected '%s' (%s/0x%x)\n\t\tfound '%s' "
254*eb00b1c8SRobert Mustacchi 			    "(%s/0x%x)\n", imc_test_strerror(test->itc_fail),
255*eb00b1c8SRobert Mustacchi 			    imc_test_strenum(test->itc_fail), test->itc_fail,
256*eb00b1c8SRobert Mustacchi 			    imc_test_strerror(dec.ids_fail),
257*eb00b1c8SRobert Mustacchi 			    imc_test_strenum(dec.ids_fail), dec.ids_fail);
258*eb00b1c8SRobert Mustacchi 			return (1);
259*eb00b1c8SRobert Mustacchi 		}
260*eb00b1c8SRobert Mustacchi 
261*eb00b1c8SRobert Mustacchi 		imc_print("\tCorrect decoding error generated\n");
262*eb00b1c8SRobert Mustacchi 		return (0);
263*eb00b1c8SRobert Mustacchi 	} else {
264*eb00b1c8SRobert Mustacchi 		imc_print("\tdecode failed with '%s' (%s/0x%x)\n",
265*eb00b1c8SRobert Mustacchi 		    imc_test_strerror(dec.ids_fail),
266*eb00b1c8SRobert Mustacchi 		    imc_test_strenum(dec.ids_fail),
267*eb00b1c8SRobert Mustacchi 		    dec.ids_fail);
268*eb00b1c8SRobert Mustacchi 		if (test->itc_nodeid != UINT32_MAX) {
269*eb00b1c8SRobert Mustacchi 			imc_print("\t\texpected socket: %u\n",
270*eb00b1c8SRobert Mustacchi 			    test->itc_nodeid);
271*eb00b1c8SRobert Mustacchi 		}
272*eb00b1c8SRobert Mustacchi 
273*eb00b1c8SRobert Mustacchi 		if (test->itc_tadid != UINT32_MAX) {
274*eb00b1c8SRobert Mustacchi 			imc_print("\t\texpected tad: %u\n", test->itc_tadid);
275*eb00b1c8SRobert Mustacchi 		}
276*eb00b1c8SRobert Mustacchi 
277*eb00b1c8SRobert Mustacchi 		if (test->itc_channelid != UINT32_MAX) {
278*eb00b1c8SRobert Mustacchi 			imc_print("\t\texpected channel: %u\n",
279*eb00b1c8SRobert Mustacchi 			    test->itc_channelid);
280*eb00b1c8SRobert Mustacchi 		}
281*eb00b1c8SRobert Mustacchi 
282*eb00b1c8SRobert Mustacchi 		if (test->itc_chanaddr != UINT64_MAX) {
283*eb00b1c8SRobert Mustacchi 			imc_print("\t\texpected channel address: 0x%" PRIx64
284*eb00b1c8SRobert Mustacchi 			    "\n", test->itc_chanaddr);
285*eb00b1c8SRobert Mustacchi 		}
286*eb00b1c8SRobert Mustacchi 
287*eb00b1c8SRobert Mustacchi 		if (test->itc_rankid != UINT32_MAX) {
288*eb00b1c8SRobert Mustacchi 			imc_print("\t\texpected rank: %u\n",
289*eb00b1c8SRobert Mustacchi 			    test->itc_rankid);
290*eb00b1c8SRobert Mustacchi 		}
291*eb00b1c8SRobert Mustacchi 
292*eb00b1c8SRobert Mustacchi 		if (test->itc_rankaddr != UINT64_MAX) {
293*eb00b1c8SRobert Mustacchi 			imc_print("\t\texpected rank address: 0x%" PRIx64 "\n",
294*eb00b1c8SRobert Mustacchi 			    test->itc_rankaddr);
295*eb00b1c8SRobert Mustacchi 		}
296*eb00b1c8SRobert Mustacchi 
297*eb00b1c8SRobert Mustacchi 		imc_print("\tdecode failed, expected pass\n");
298*eb00b1c8SRobert Mustacchi 
299*eb00b1c8SRobert Mustacchi 		return (1);
300*eb00b1c8SRobert Mustacchi 	}
301*eb00b1c8SRobert Mustacchi }
302*eb00b1c8SRobert Mustacchi 
303*eb00b1c8SRobert Mustacchi static void
imc_test_run(const imc_test_case_t * tests,uint_t * ntests,uint_t * nfail)304*eb00b1c8SRobert Mustacchi imc_test_run(const imc_test_case_t *tests, uint_t *ntests, uint_t *nfail)
305*eb00b1c8SRobert Mustacchi {
306*eb00b1c8SRobert Mustacchi 	while (tests[0].itc_desc != NULL) {
307*eb00b1c8SRobert Mustacchi 		*nfail += imc_test_run_one(tests);
308*eb00b1c8SRobert Mustacchi 		*ntests += 1;
309*eb00b1c8SRobert Mustacchi 		tests++;
310*eb00b1c8SRobert Mustacchi 	}
311*eb00b1c8SRobert Mustacchi }
312*eb00b1c8SRobert Mustacchi 
313*eb00b1c8SRobert Mustacchi int
main(int argc,char * argv[])314*eb00b1c8SRobert Mustacchi main(int argc, char *argv[])
315*eb00b1c8SRobert Mustacchi {
316*eb00b1c8SRobert Mustacchi 	uint_t ntests = 0, nfail = 0;
317*eb00b1c8SRobert Mustacchi 	int i;
318*eb00b1c8SRobert Mustacchi 
319*eb00b1c8SRobert Mustacchi 	if (argc > 1) {
320*eb00b1c8SRobert Mustacchi 		for (i = 1; i < argc; i++) {
321*eb00b1c8SRobert Mustacchi 			if (strcmp(argv[i], "basic") == 0) {
322*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_basics, &ntests, &nfail);
323*eb00b1c8SRobert Mustacchi 			} else if (strcmp(argv[i], "badaddr") == 0) {
324*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_badaddr, &ntests, &nfail);
325*eb00b1c8SRobert Mustacchi 			} else if (strcmp(argv[i], "sad") == 0) {
326*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_sad, &ntests, &nfail);
327*eb00b1c8SRobert Mustacchi 			} else if (strcmp(argv[i], "skx_loop") == 0) {
328*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_skx_loop, &ntests,
329*eb00b1c8SRobert Mustacchi 				    &nfail);
330*eb00b1c8SRobert Mustacchi 			} else if (strcmp(argv[i], "tad") == 0) {
331*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_tad, &ntests, &nfail);
332*eb00b1c8SRobert Mustacchi 			} else if (strcmp(argv[i], "rir") == 0) {
333*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_rir, &ntests, &nfail);
334*eb00b1c8SRobert Mustacchi 			} else if (strcmp(argv[i], "fail") == 0) {
335*eb00b1c8SRobert Mustacchi 				imc_test_run(imc_test_fail, &ntests, &nfail);
336*eb00b1c8SRobert Mustacchi 			} else {
337*eb00b1c8SRobert Mustacchi 				errx(EXIT_FAILURE, "Unknown test argument %s",
338*eb00b1c8SRobert Mustacchi 				    argv[i]);
339*eb00b1c8SRobert Mustacchi 			}
340*eb00b1c8SRobert Mustacchi 		}
341*eb00b1c8SRobert Mustacchi 	} else {
342*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_basics, &ntests, &nfail);
343*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_badaddr, &ntests, &nfail);
344*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_skx_loop, &ntests, &nfail);
345*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_rir, &ntests, &nfail);
346*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_tad, &ntests, &nfail);
347*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_sad, &ntests, &nfail);
348*eb00b1c8SRobert Mustacchi 		imc_test_run(imc_test_fail, &ntests, &nfail);
349*eb00b1c8SRobert Mustacchi 	}
350*eb00b1c8SRobert Mustacchi 
351*eb00b1c8SRobert Mustacchi 	imc_print("%u/%u tests passed\n", ntests - nfail, ntests);
352*eb00b1c8SRobert Mustacchi 	return (nfail > 0);
353*eb00b1c8SRobert Mustacchi }
354