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