1 /*
2  * This file and its contents are supplied under the terms of the
3  * Common Development and Distribution License ("CDDL"), version 1.0.
4  * You may only use this file in accordance with the terms of version
5  * 1.0 of the CDDL.
6  *
7  * A full copy of the text of the CDDL should have accompanied this
8  * source.  A copy of the CDDL is also available via the Internet at
9  * http://www.illumos.org/license/CDDL.
10  */
11 
12 /*
13  * Copyright 2022 Oxide Computer Company
14  */
15 
16 /*
17  * SMBIOS processor tests. We build two main processors:
18  *
19  *   1. An early SMBIOS one based on 2.5 that has the initial core count and
20  *     related. A modern client should see the current values.
21  *   2. One based on SMBIOS 3.6 that has different values for the processor
22  *     counts to verify we use the newer fields both for cores counts and also
23  *     the processor family. Most of those were 3.x based. We use 3.6 so we can
24  *     get the newer threads enabled field. A pre-3.x client should not see the
25  *     same core values as something 3.0+.
26  */
27 
28 #include <stdlib.h>
29 #include "smbios_test.h"
30 
31 /*
32  * Older revisions lengths per the SMBIOS spec.
33  */
34 #define	SMBIOS_PROC_LEN_25	0x28
35 
36 static const char *smbios_proc_sock = "Gideon";
37 static const char *smbios_proc_mfg = "Harrow";
38 static const char *smbios_proc_vers = "Nona";
39 static const char *smbios_proc_serial = "Alecto";
40 static const char *smbios_proc_asset = "Matthias";
41 static const char *smbios_proc_pn = "Ortus";
42 static const uint64_t smbios_proc_cpuid = 0x09099090;
43 
44 /*
45  * Construct a processor that we'll use throughout our tests. This fills in most
46  * of the fields. Some bits may override it and others will only copy a smaller
47  * length.
48  */
49 static void
smbios_test_proc_fill(smb_processor_t * proc)50 smbios_test_proc_fill(smb_processor_t *proc)
51 {
52 	proc->smbpr_hdr.smbh_type = SMB_TYPE_PROCESSOR;
53 	proc->smbpr_hdr.smbh_len = sizeof (smb_processor_t);
54 	proc->smbpr_socket = 1;
55 	proc->smbpr_type = SMB_PRT_CENTRAL;
56 	proc->smbpr_family = SMB_PRF_HOBBIT;
57 	proc->smbpr_manufacturer = 2;
58 	proc->smbpr_cpuid = htole64(smbios_proc_cpuid);
59 	proc->smbpr_version = 3;
60 	proc->smbpr_voltage = 0x8b;
61 	proc->smbpr_clkspeed = htole16(0x1234);
62 	proc->smbpr_maxspeed = htole16(0x5678);
63 	proc->smbpr_curspeed = htole16(0x3210);
64 	proc->smbpr_status = SMB_PRS_ENABLED | 0x40;
65 	proc->smbpr_upgrade = SMB_PRU_SP3;
66 	proc->smbpr_l1cache = htole16(0x11ca);
67 	proc->smbpr_l2cache = htole16(0x12ca);
68 	proc->smbpr_l3cache = htole16(0x13ca);
69 	proc->smbpr_serial = 4;
70 	proc->smbpr_asset = 5;
71 	proc->smbpr_part = 6;
72 	proc->smbpr_corecount = 0x77;
73 	proc->smbpr_coresenabled = 0x3;
74 	proc->smbpr_threadcount = 0x19;
75 	proc->smbpr_cflags = htole16(SMB_PRC_64BIT | SMB_PRC_NX);
76 	proc->smbpr_family2 = htole16(0);
77 	proc->smbpr_corecount2 = htole16(0);
78 	proc->smbpr_coresenabled2 = htole16(0);
79 	proc->smbpr_threadcount2 = htole16(0);
80 	proc->smpbr_threaden = htole16(11);
81 
82 }
83 
84 boolean_t
smbios_test_proc_mktable_25(smbios_test_table_t * table)85 smbios_test_proc_mktable_25(smbios_test_table_t *table)
86 {
87 	smb_processor_t proc;
88 
89 	smbios_test_proc_fill(&proc);
90 	proc.smbpr_hdr.smbh_len = SMBIOS_PROC_LEN_25;
91 	(void) smbios_test_table_append(table, &proc, SMBIOS_PROC_LEN_25);
92 	smbios_test_table_append_string(table, smbios_proc_sock);
93 	smbios_test_table_append_string(table, smbios_proc_mfg);
94 	smbios_test_table_append_string(table, smbios_proc_vers);
95 	smbios_test_table_append_string(table, smbios_proc_serial);
96 	smbios_test_table_append_string(table, smbios_proc_asset);
97 	smbios_test_table_append_string(table, smbios_proc_pn);
98 	smbios_test_table_str_fini(table);
99 	smbios_test_table_append_eot(table);
100 
101 	return (B_TRUE);
102 }
103 
104 /*
105  * This is a 3.0 based table. The biggest difference here is that this table
106  * fills in the values that allows us to use family 2, core count 2, etc.
107  * fields.
108  */
109 boolean_t
smbios_test_proc_mktable_36(smbios_test_table_t * table)110 smbios_test_proc_mktable_36(smbios_test_table_t *table)
111 {
112 	smb_processor_t proc;
113 
114 	smbios_test_proc_fill(&proc);
115 	proc.smbpr_hdr.smbh_len = sizeof (smb_processor_t);
116 	proc.smbpr_family = 0xfe;
117 	proc.smbpr_family2 = htole16(SMB_PRF_RV64);
118 	proc.smbpr_corecount = 0xff;
119 	proc.smbpr_corecount2 = htole16(0x171);
120 	proc.smbpr_coresenabled = 0xff;
121 	proc.smbpr_coresenabled2 = htole16(0x717);
122 	proc.smbpr_threadcount = 0xff;
123 	proc.smbpr_threadcount2 = htole16(0x5445);
124 	proc.smpbr_threaden = htole16(0x2232);
125 	(void) smbios_test_table_append(table, &proc, sizeof (smb_processor_t));
126 	smbios_test_table_append_string(table, smbios_proc_sock);
127 	smbios_test_table_append_string(table, smbios_proc_mfg);
128 	smbios_test_table_append_string(table, smbios_proc_vers);
129 	smbios_test_table_append_string(table, smbios_proc_serial);
130 	smbios_test_table_append_string(table, smbios_proc_asset);
131 	smbios_test_table_append_string(table, smbios_proc_pn);
132 	smbios_test_table_str_fini(table);
133 	smbios_test_table_append_eot(table);
134 
135 	return (B_TRUE);
136 }
137 
138 
139 /*
140  * Verify common fields that'll be true across all tests. Verifying core,
141  * thread, and related is left to higher level logic as those are changed up
142  * between tests to cover the extensions.
143  */
144 static boolean_t
smbios_test_proc_verify_common(smbios_hdl_t * hdl,smbios_struct_t * sp,smbios_processor_t * proc)145 smbios_test_proc_verify_common(smbios_hdl_t *hdl, smbios_struct_t *sp,
146     smbios_processor_t *proc)
147 {
148 	boolean_t ret = B_TRUE;
149 	smbios_info_t info;
150 
151 	if (proc->smbp_cpuid != smbios_proc_cpuid) {
152 		warnx("processor state mismatch, found unexpected cpuid: 0x%"
153 		    PRIx64, proc->smbp_cpuid);
154 		ret = B_FALSE;
155 	}
156 
157 	if (SMB_PRV_LEGACY(proc->smbp_voltage)) {
158 		warnx("processor state mismatch, found legacy foltage: 0x%x",
159 		    proc->smbp_voltage);
160 		ret = B_FALSE;
161 	}
162 
163 	if (SMB_PRV_VOLTAGE(proc->smbp_voltage) != 0xb) {
164 		warnx("processor state mismatch, found legacy foltage: 0x%x",
165 		    SMB_PRV_VOLTAGE(proc->smbp_voltage));
166 		ret = B_FALSE;
167 	}
168 
169 	if (proc->smbp_status != (SMB_PRS_ENABLED | 0x40)) {
170 		warnx("processor state mismatch, found unexpected processor "
171 		    "status: 0x%x", proc->smbp_status);
172 		ret = B_FALSE;
173 	}
174 
175 	if (proc->smbp_upgrade != SMB_PRU_SP3) {
176 		warnx("processor state mismatch, found unexpected processor "
177 		    "socket: 0x%x", proc->smbp_upgrade);
178 		ret = B_FALSE;
179 	}
180 
181 	if (proc->smbp_clkspeed != 0x1234) {
182 		warnx("processor state mismatch, found unexpected clock speed: "
183 		    "0x%x", proc->smbp_clkspeed);
184 		ret = B_FALSE;
185 	}
186 
187 	if (proc->smbp_maxspeed != 0x5678) {
188 		warnx("processor state mismatch, found unexpected max speed: "
189 		    "0x%x", proc->smbp_maxspeed);
190 		ret = B_FALSE;
191 	}
192 
193 	if (proc->smbp_curspeed != 0x3210) {
194 		warnx("processor state mismatch, found unexpected current "
195 		    "speed: 0x%x", proc->smbp_curspeed);
196 		ret = B_FALSE;
197 	}
198 
199 
200 	if (proc->smbp_l1cache != 0x11ca) {
201 		warnx("processor state mismatch, found unexpected l1 cache id: "
202 		    "0x%" _PRIxID, proc->smbp_l1cache);
203 		ret = B_FALSE;
204 	}
205 
206 
207 	if (proc->smbp_l2cache != 0x12ca) {
208 		warnx("processor state mismatch, found unexpected l2 cache id: "
209 		    "0x%" _PRIxID, proc->smbp_l2cache);
210 		ret = B_FALSE;
211 	}
212 
213 	if (proc->smbp_l3cache != 0x13ca) {
214 		warnx("processor state mismatch, found unexpected l3 cache id: "
215 		    "0x%" _PRIxID, proc->smbp_l3cache);
216 		ret = B_FALSE;
217 	}
218 
219 	if (proc->smbp_cflags != (SMB_PRC_64BIT | SMB_PRC_NX)) {
220 		warnx("processor state mismatch, found unexpected "
221 		    "characteristic flags: 0x%x", proc->smbp_cflags);
222 		ret = B_FALSE;
223 	}
224 
225 	if (smbios_info_common(hdl, sp->smbstr_id, &info) != 0) {
226 		warnx("failed to get common chassis info: %s",
227 		    smbios_errmsg(smbios_errno(hdl)));
228 		return (B_FALSE);
229 	}
230 
231 	if (strcmp(info.smbi_manufacturer, smbios_proc_mfg) != 0) {
232 		warnx("processor state mismatch, found unexpected mfg: %s",
233 		    info.smbi_manufacturer);
234 		ret = B_FALSE;
235 	}
236 
237 
238 	if (strcmp(info.smbi_version, smbios_proc_vers) != 0) {
239 		warnx("processor state mismatch, found unexpected vers: %s",
240 		    info.smbi_version);
241 		ret = B_FALSE;
242 	}
243 
244 	if (strcmp(info.smbi_serial, smbios_proc_serial) != 0) {
245 		warnx("processor state mismatch, found unexpected serial: %s",
246 		    info.smbi_serial);
247 		ret = B_FALSE;
248 	}
249 
250 	if (strcmp(info.smbi_asset, smbios_proc_asset) != 0) {
251 		warnx("processor state mismatch, found unexpected asset: %s",
252 		    info.smbi_asset);
253 		ret = B_FALSE;
254 	}
255 
256 	if (strcmp(info.smbi_location, smbios_proc_sock) != 0) {
257 		warnx("processor state mismatch, found unexpected sock: %s",
258 		    info.smbi_location);
259 		ret = B_FALSE;
260 	}
261 
262 	if (strcmp(info.smbi_part, smbios_proc_pn) != 0) {
263 		warnx("processor state mismatch, found unexpected pn: %s",
264 		    info.smbi_part);
265 		ret = B_FALSE;
266 	}
267 
268 	return (ret);
269 }
270 
271 boolean_t
smbios_test_proc_verify_25(smbios_hdl_t * hdl)272 smbios_test_proc_verify_25(smbios_hdl_t *hdl)
273 {
274 	boolean_t ret = B_TRUE;
275 	smbios_struct_t sp;
276 	smbios_processor_t proc;
277 
278 	if (smbios_lookup_type(hdl, SMB_TYPE_PROCESSOR, &sp) == -1) {
279 		warnx("failed to lookup SMBIOS processor: %s",
280 		    smbios_errmsg(smbios_errno(hdl)));
281 		return (B_FALSE);
282 	}
283 
284 	if (smbios_info_processor(hdl, sp.smbstr_id, &proc) == -1) {
285 		warnx("failed to get processor: %s",
286 		    smbios_errmsg(smbios_errno(hdl)));
287 		return (B_FALSE);
288 	}
289 
290 	if (!smbios_test_proc_verify_common(hdl, &sp, &proc)) {
291 		ret = B_FALSE;
292 	}
293 
294 	if (proc.smbp_family != SMB_PRF_HOBBIT) {
295 		warnx("processor state mismatch, found unexpected family: 0x%x",
296 		    proc.smbp_family);
297 		ret = B_FALSE;
298 	}
299 
300 	if (proc.smbp_corecount != 0x77) {
301 		warnx("processor state mismatch, found unexpected core count: "
302 		    "0x%x",  proc.smbp_corecount);
303 		ret = B_FALSE;
304 	}
305 
306 	if (proc.smbp_coresenabled != 0x3) {
307 		warnx("processor state mismatch, found unexpected cores "
308 		    "enabled count: 0x%x",  proc.smbp_coresenabled);
309 		ret = B_FALSE;
310 	}
311 
312 	if (proc.smbp_threadcount != 0x19) {
313 		warnx("processor state mismatch, found unexpected thread "
314 		    "count: 0x%x",  proc.smbp_threadcount);
315 		ret = B_FALSE;
316 	}
317 
318 	return (ret);
319 }
320 
321 /*
322  * This verifies that the 3.6 based table with a 3.0+ client always sees the
323  * values from the uint16_t extension values.
324  */
325 boolean_t
smbios_test_proc_verify_36(smbios_hdl_t * hdl)326 smbios_test_proc_verify_36(smbios_hdl_t *hdl)
327 {
328 	boolean_t ret = B_TRUE;
329 	smbios_struct_t sp;
330 	smbios_processor_t proc;
331 
332 	if (smbios_lookup_type(hdl, SMB_TYPE_PROCESSOR, &sp) == -1) {
333 		warnx("failed to lookup SMBIOS processor: %s",
334 		    smbios_errmsg(smbios_errno(hdl)));
335 		return (B_FALSE);
336 	}
337 
338 	if (smbios_info_processor(hdl, sp.smbstr_id, &proc) == -1) {
339 		warnx("failed to get processor: %s",
340 		    smbios_errmsg(smbios_errno(hdl)));
341 		return (B_FALSE);
342 	}
343 
344 	if (!smbios_test_proc_verify_common(hdl, &sp, &proc)) {
345 		ret = B_FALSE;
346 	}
347 
348 	if (proc.smbp_family != SMB_PRF_RV64) {
349 		warnx("processor state mismatch, found unexpected family: 0x%x",
350 		    proc.smbp_family);
351 		ret = B_FALSE;
352 	}
353 
354 	if (proc.smbp_corecount != 0x171) {
355 		warnx("processor state mismatch, found unexpected core count: "
356 		    "0x%x",  proc.smbp_corecount);
357 		ret = B_FALSE;
358 	}
359 
360 	if (proc.smbp_coresenabled != 0x717) {
361 		warnx("processor state mismatch, found unexpected cores "
362 		    "enabled count: 0x%x",  proc.smbp_coresenabled);
363 		ret = B_FALSE;
364 	}
365 
366 	if (proc.smbp_threadcount != 0x5445) {
367 		warnx("processor state mismatch, found unexpected thread "
368 		    "count: 0x%x",  proc.smbp_threadcount);
369 		ret = B_FALSE;
370 	}
371 
372 	if (proc.smbp_threadsenabled != 0x2232) {
373 		warnx("processor state mismatch, found unexpected thread "
374 		    "enabled coun: 0x%x",  proc.smbp_threadsenabled);
375 		ret = B_FALSE;
376 	}
377 
378 	return (ret);
379 }
380 
381 /*
382  * This verifies that when a 2.5 based client uses a 3.x based table, we don't
383  * know about the second flags and instead seed data just based off of the
384  * original field with reserved and all.
385  */
386 boolean_t
smbios_test_proc_verify_36_25(smbios_hdl_t * hdl)387 smbios_test_proc_verify_36_25(smbios_hdl_t *hdl)
388 {
389 	boolean_t ret = B_TRUE;
390 	smbios_struct_t sp;
391 	smbios_processor_t proc;
392 
393 	if (smbios_lookup_type(hdl, SMB_TYPE_PROCESSOR, &sp) == -1) {
394 		warnx("failed to lookup SMBIOS processor: %s",
395 		    smbios_errmsg(smbios_errno(hdl)));
396 		return (B_FALSE);
397 	}
398 
399 	if (smbios_info_processor(hdl, sp.smbstr_id, &proc) == -1) {
400 		warnx("failed to get processor: %s",
401 		    smbios_errmsg(smbios_errno(hdl)));
402 		return (B_FALSE);
403 	}
404 
405 	if (!smbios_test_proc_verify_common(hdl, &sp, &proc)) {
406 		ret = B_FALSE;
407 	}
408 
409 	if (proc.smbp_family != 0xfe) {
410 		warnx("processor state mismatch, found unexpected family: 0x%x",
411 		    proc.smbp_family);
412 		ret = B_FALSE;
413 	}
414 
415 	if (proc.smbp_corecount != 0xff) {
416 		warnx("processor state mismatch, found unexpected core count: "
417 		    "0x%x",  proc.smbp_corecount);
418 		ret = B_FALSE;
419 	}
420 
421 	if (proc.smbp_coresenabled != 0xff) {
422 		warnx("processor state mismatch, found unexpected cores "
423 		    "enabled count: 0x%x",  proc.smbp_coresenabled);
424 		ret = B_FALSE;
425 	}
426 
427 	if (proc.smbp_threadcount != 0xff) {
428 		warnx("processor state mismatch, found unexpected thread "
429 		    "count: 0x%x",  proc.smbp_threadcount);
430 		ret = B_FALSE;
431 	}
432 
433 	return (ret);
434 }
435