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