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 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 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 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 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 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 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 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 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 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