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