1 /* 2 * Boot order test cases. 3 * 4 * Copyright (c) 2013 Red Hat Inc. 5 * 6 * Authors: 7 * Michael S. Tsirkin <mst@redhat.com>, 8 * 9 * This work is licensed under the terms of the GNU GPL, version 2 or later. 10 * See the COPYING file in the top-level directory. 11 */ 12 13 /* 14 * How to add or update the tests or commit changes that affect ACPI tables: 15 * Contributor: 16 * 1. add empty files for new tables, if any, under tests/data/acpi 17 * 2. list any changed files in tests/qtest/bios-tables-test-allowed-diff.h 18 * 3. commit the above *before* making changes that affect the tables 19 * 20 * Contributor or ACPI Maintainer (steps 4-7 need to be redone to resolve conflicts 21 * in binary commit created in step 6): 22 * 23 * After 1-3 above tests will pass but ignore differences with the expected files. 24 * You will also notice that tests/qtest/bios-tables-test-allowed-diff.h lists 25 * a bunch of files. This is your hint that you need to do the below: 26 * 4. Run 27 * make check V=2 28 * this will produce a bunch of warnings about differences 29 * between actual and expected ACPI tables. If you have IASL installed, 30 * they will also be disassembled so you can look at the disassembled 31 * output. If not - disassemble them yourself in any way you like. 32 * Look at the differences - make sure they make sense and match what the 33 * changes you are merging are supposed to do. 34 * Save the changes, preferably in form of ASL diff for the commit log in 35 * step 6. 36 * 37 * 5. From build directory, run: 38 * $(SRC_PATH)/tests/data/acpi/rebuild-expected-aml.sh 39 * 6. Now commit any changes to the expected binary, include diff from step 4 40 * in commit log. 41 * Expected binary updates needs to be a separate patch from the code that 42 * introduces changes to ACPI tables. It lets the maintainer drop 43 * and regenerate binary updates in case of merge conflicts. Further, a code 44 * change is easily reviewable but a binary blob is not (without doing a 45 * disassembly). 46 * 7. Before sending patches to the list (Contributor) 47 * or before doing a pull request (Maintainer), make sure 48 * tests/qtest/bios-tables-test-allowed-diff.h is empty - this will ensure 49 * following changes to ACPI tables will be noticed. 50 * 51 * The resulting patchset/pull request then looks like this: 52 * - patch 1: list changed files in tests/qtest/bios-tables-test-allowed-diff.h. 53 * - patches 2 - n: real changes, may contain multiple patches. 54 * - patch n + 1: update golden master binaries and empty 55 * tests/qtest/bios-tables-test-allowed-diff.h 56 */ 57 58 #include "qemu/osdep.h" 59 #include <glib/gstdio.h> 60 #include "hw/firmware/smbios.h" 61 #include "qemu/bitmap.h" 62 #include "acpi-utils.h" 63 #include "boot-sector.h" 64 #include "tpm-emu.h" 65 #include "hw/acpi/tpm.h" 66 #include "qemu/cutils.h" 67 68 #define MACHINE_PC "pc" 69 #define MACHINE_Q35 "q35" 70 71 #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML" 72 73 #define OEM_ID "TEST" 74 #define OEM_TABLE_ID "OEM" 75 #define OEM_TEST_ARGS "-machine x-oem-id=" OEM_ID ",x-oem-table-id=" \ 76 OEM_TABLE_ID 77 78 typedef struct { 79 bool tcg_only; 80 const char *machine; 81 const char *machine_param; 82 const char *variant; 83 const char *uefi_fl1; 84 const char *uefi_fl2; 85 const char *blkdev; 86 const char *cd; 87 const uint64_t ram_start; 88 const uint64_t scan_len; 89 uint64_t rsdp_addr; 90 uint8_t rsdp_table[36 /* ACPI 2.0+ RSDP size */]; 91 GArray *tables; 92 uint64_t smbios_ep_addr[SMBIOS_ENTRY_POINT_TYPE__MAX]; 93 SmbiosEntryPoint smbios_ep_table; 94 uint16_t smbios_cpu_max_speed; 95 uint16_t smbios_cpu_curr_speed; 96 uint8_t smbios_core_count; 97 uint16_t smbios_core_count2; 98 uint8_t smbios_thread_count; 99 uint16_t smbios_thread_count2; 100 uint8_t *required_struct_types; 101 int required_struct_types_len; 102 int type4_count; 103 QTestState *qts; 104 } test_data; 105 106 static char disk[] = "tests/acpi-test-disk-XXXXXX"; 107 static const char *data_dir = "tests/data/acpi"; 108 #ifdef CONFIG_IASL 109 static const char *iasl = CONFIG_IASL; 110 #else 111 static const char *iasl; 112 #endif 113 114 static int verbosity_level; 115 static GArray *load_expected_aml(test_data *data); 116 117 static bool compare_signature(const AcpiSdtTable *sdt, const char *signature) 118 { 119 return !memcmp(sdt->aml, signature, 4); 120 } 121 122 static void cleanup_table_descriptor(AcpiSdtTable *table) 123 { 124 g_free(table->aml); 125 if (table->aml_file && 126 !table->tmp_files_retain && 127 g_strstr_len(table->aml_file, -1, "aml-")) { 128 unlink(table->aml_file); 129 } 130 g_free(table->aml_file); 131 g_free(table->asl); 132 if (table->asl_file && 133 !table->tmp_files_retain) { 134 unlink(table->asl_file); 135 } 136 g_free(table->asl_file); 137 } 138 139 static void free_test_data(test_data *data) 140 { 141 int i; 142 143 if (!data->tables) { 144 return; 145 } 146 for (i = 0; i < data->tables->len; ++i) { 147 cleanup_table_descriptor(&g_array_index(data->tables, AcpiSdtTable, i)); 148 } 149 150 g_array_free(data->tables, true); 151 } 152 153 static void test_acpi_rsdp_table(test_data *data) 154 { 155 uint8_t *rsdp_table = data->rsdp_table; 156 157 acpi_fetch_rsdp_table(data->qts, data->rsdp_addr, rsdp_table); 158 159 switch (rsdp_table[15 /* Revision offset */]) { 160 case 0: /* ACPI 1.0 RSDP */ 161 /* With rev 1, checksum is only for the first 20 bytes */ 162 g_assert(!acpi_calc_checksum(rsdp_table, 20)); 163 break; 164 case 2: /* ACPI 2.0+ RSDP */ 165 /* With revision 2, we have 2 checksums */ 166 g_assert(!acpi_calc_checksum(rsdp_table, 20)); 167 g_assert(!acpi_calc_checksum(rsdp_table, 36)); 168 break; 169 default: 170 g_assert_not_reached(); 171 } 172 } 173 174 static void test_acpi_rxsdt_table(test_data *data) 175 { 176 const char *sig = "RSDT"; 177 AcpiSdtTable rsdt = {}; 178 int entry_size = 4; 179 int addr_off = 16 /* RsdtAddress */; 180 uint8_t *ent; 181 182 if (data->rsdp_table[15 /* Revision offset */] != 0) { 183 addr_off = 24 /* XsdtAddress */; 184 entry_size = 8; 185 sig = "XSDT"; 186 } 187 /* read [RX]SDT table */ 188 acpi_fetch_table(data->qts, &rsdt.aml, &rsdt.aml_len, 189 &data->rsdp_table[addr_off], entry_size, sig, true); 190 191 /* Load all tables and add to test list directly RSDT referenced tables */ 192 ACPI_FOREACH_RSDT_ENTRY(rsdt.aml, rsdt.aml_len, ent, entry_size) { 193 AcpiSdtTable ssdt_table = {}; 194 195 acpi_fetch_table(data->qts, &ssdt_table.aml, &ssdt_table.aml_len, ent, 196 entry_size, NULL, true); 197 /* Add table to ASL test tables list */ 198 g_array_append_val(data->tables, ssdt_table); 199 } 200 cleanup_table_descriptor(&rsdt); 201 } 202 203 static void test_acpi_fadt_table(test_data *data) 204 { 205 /* FADT table is 1st */ 206 AcpiSdtTable table = g_array_index(data->tables, typeof(table), 0); 207 uint8_t *fadt_aml = table.aml; 208 uint32_t fadt_len = table.aml_len; 209 uint32_t val; 210 int dsdt_offset = 40 /* DSDT */; 211 int dsdt_entry_size = 4; 212 213 g_assert(compare_signature(&table, "FACP")); 214 215 /* Since DSDT/FACS isn't in RSDT, add them to ASL test list manually */ 216 memcpy(&val, fadt_aml + 112 /* Flags */, 4); 217 val = le32_to_cpu(val); 218 if (!(val & 1UL << 20 /* HW_REDUCED_ACPI */)) { 219 acpi_fetch_table(data->qts, &table.aml, &table.aml_len, 220 fadt_aml + 36 /* FIRMWARE_CTRL */, 4, "FACS", false); 221 g_array_append_val(data->tables, table); 222 } 223 224 memcpy(&val, fadt_aml + dsdt_offset, 4); 225 val = le32_to_cpu(val); 226 if (!val) { 227 dsdt_offset = 140 /* X_DSDT */; 228 dsdt_entry_size = 8; 229 } 230 acpi_fetch_table(data->qts, &table.aml, &table.aml_len, 231 fadt_aml + dsdt_offset, dsdt_entry_size, "DSDT", true); 232 g_array_append_val(data->tables, table); 233 234 memset(fadt_aml + 36, 0, 4); /* sanitize FIRMWARE_CTRL ptr */ 235 memset(fadt_aml + 40, 0, 4); /* sanitize DSDT ptr */ 236 if (fadt_aml[8 /* FADT Major Version */] >= 3) { 237 memset(fadt_aml + 132, 0, 8); /* sanitize X_FIRMWARE_CTRL ptr */ 238 memset(fadt_aml + 140, 0, 8); /* sanitize X_DSDT ptr */ 239 } 240 241 /* update checksum */ 242 fadt_aml[9 /* Checksum */] = 0; 243 fadt_aml[9 /* Checksum */] -= acpi_calc_checksum(fadt_aml, fadt_len); 244 } 245 246 static void dump_aml_files(test_data *data, bool rebuild) 247 { 248 AcpiSdtTable *sdt, *exp_sdt; 249 GError *error = NULL; 250 gchar *aml_file = NULL; 251 test_data exp_data = {}; 252 gint fd; 253 ssize_t ret; 254 int i; 255 256 exp_data.tables = load_expected_aml(data); 257 for (i = 0; i < data->tables->len; ++i) { 258 const char *ext = data->variant ? data->variant : ""; 259 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 260 exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i); 261 g_assert(sdt->aml); 262 g_assert(exp_sdt->aml); 263 264 if (rebuild) { 265 aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, 266 sdt->aml, ext); 267 if (!g_file_test(aml_file, G_FILE_TEST_EXISTS) && 268 sdt->aml_len == exp_sdt->aml_len && 269 !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) { 270 /* identical tables, no need to write new files */ 271 g_free(aml_file); 272 continue; 273 } 274 fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT, 275 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); 276 if (fd < 0) { 277 perror(aml_file); 278 } 279 g_assert(fd >= 0); 280 } else { 281 fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error); 282 g_assert_no_error(error); 283 } 284 285 ret = qemu_write_full(fd, sdt->aml, sdt->aml_len); 286 g_assert(ret == sdt->aml_len); 287 288 close(fd); 289 290 g_free(aml_file); 291 } 292 } 293 294 static bool create_tmp_asl(AcpiSdtTable *sdt) 295 { 296 GError *error = NULL; 297 gint fd; 298 299 fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error); 300 g_assert_no_error(error); 301 close(fd); 302 303 return false; 304 } 305 306 static bool load_asl(GArray *sdts, AcpiSdtTable *sdt) 307 { 308 AcpiSdtTable *temp; 309 GError *error = NULL; 310 GString *command_line = g_string_new(iasl); 311 gchar *out, *out_err; 312 gboolean ret; 313 int i; 314 315 create_tmp_asl(sdt); 316 317 /* build command line */ 318 g_string_append_printf(command_line, " -p %s ", sdt->asl_file); 319 if (compare_signature(sdt, "DSDT") || 320 compare_signature(sdt, "SSDT")) { 321 for (i = 0; i < sdts->len; ++i) { 322 temp = &g_array_index(sdts, AcpiSdtTable, i); 323 if (compare_signature(temp, "DSDT") || 324 compare_signature(temp, "SSDT")) { 325 g_string_append_printf(command_line, "-e %s ", temp->aml_file); 326 } 327 } 328 } 329 g_string_append_printf(command_line, "-d %s", sdt->aml_file); 330 331 /* pass 'out' and 'out_err' in order to be redirected */ 332 ret = g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error); 333 g_assert_no_error(error); 334 if (ret) { 335 ret = g_file_get_contents(sdt->asl_file, &sdt->asl, 336 &sdt->asl_len, &error); 337 g_assert(ret); 338 g_assert_no_error(error); 339 ret = (sdt->asl_len > 0); 340 } 341 342 g_free(out); 343 g_free(out_err); 344 g_string_free(command_line, true); 345 346 return !ret; 347 } 348 349 #define COMMENT_END "*/" 350 #define DEF_BLOCK "DefinitionBlock (" 351 #define BLOCK_NAME_END "," 352 353 static GString *normalize_asl(gchar *asl_code) 354 { 355 GString *asl = g_string_new(asl_code); 356 gchar *comment, *block_name; 357 358 /* strip comments (different generation days) */ 359 comment = g_strstr_len(asl->str, asl->len, COMMENT_END); 360 if (comment) { 361 comment += strlen(COMMENT_END); 362 while (*comment == '\n') { 363 comment++; 364 } 365 asl = g_string_erase(asl, 0, comment - asl->str); 366 } 367 368 /* strip def block name (it has file path in it) */ 369 if (g_str_has_prefix(asl->str, DEF_BLOCK)) { 370 block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END); 371 g_assert(block_name); 372 asl = g_string_erase(asl, 0, 373 block_name + sizeof(BLOCK_NAME_END) - asl->str); 374 } 375 376 return asl; 377 } 378 379 static GArray *load_expected_aml(test_data *data) 380 { 381 int i; 382 AcpiSdtTable *sdt; 383 GError *error = NULL; 384 gboolean ret; 385 gsize aml_len; 386 387 GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable)); 388 if (verbosity_level >= 2) { 389 fputc('\n', stderr); 390 } 391 for (i = 0; i < data->tables->len; ++i) { 392 AcpiSdtTable exp_sdt; 393 gchar *aml_file = NULL; 394 const char *ext = data->variant ? data->variant : ""; 395 396 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 397 398 memset(&exp_sdt, 0, sizeof(exp_sdt)); 399 400 try_again: 401 aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, 402 sdt->aml, ext); 403 if (verbosity_level >= 2) { 404 fprintf(stderr, "Looking for expected file '%s'\n", aml_file); 405 } 406 if (g_file_test(aml_file, G_FILE_TEST_EXISTS)) { 407 exp_sdt.aml_file = aml_file; 408 } else if (*ext != '\0') { 409 /* try fallback to generic (extension less) expected file */ 410 ext = ""; 411 g_free(aml_file); 412 goto try_again; 413 } 414 g_assert(exp_sdt.aml_file); 415 if (verbosity_level >= 2) { 416 fprintf(stderr, "Using expected file '%s'\n", aml_file); 417 } 418 ret = g_file_get_contents(aml_file, (gchar **)&exp_sdt.aml, 419 &aml_len, &error); 420 exp_sdt.aml_len = aml_len; 421 g_assert(ret); 422 g_assert_no_error(error); 423 g_assert(exp_sdt.aml); 424 if (!exp_sdt.aml_len) { 425 fprintf(stderr, "Warning! zero length expected file '%s'\n", 426 aml_file); 427 } 428 429 g_array_append_val(exp_tables, exp_sdt); 430 } 431 432 return exp_tables; 433 } 434 435 static bool test_acpi_find_diff_allowed(AcpiSdtTable *sdt) 436 { 437 const gchar *allowed_diff_file[] = { 438 #include "bios-tables-test-allowed-diff.h" 439 NULL 440 }; 441 const gchar **f; 442 443 for (f = allowed_diff_file; *f; ++f) { 444 if (!g_strcmp0(sdt->aml_file, *f)) { 445 return true; 446 } 447 } 448 return false; 449 } 450 451 /* test the list of tables in @data->tables against reference tables */ 452 static void test_acpi_asl(test_data *data) 453 { 454 int i; 455 AcpiSdtTable *sdt, *exp_sdt; 456 test_data exp_data = {}; 457 gboolean exp_err, err, all_tables_match = true; 458 459 exp_data.tables = load_expected_aml(data); 460 dump_aml_files(data, false); 461 for (i = 0; i < data->tables->len; ++i) { 462 GString *asl, *exp_asl; 463 464 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 465 exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i); 466 467 if (sdt->aml_len == exp_sdt->aml_len && 468 !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) { 469 /* Identical table binaries: no need to disassemble. */ 470 continue; 471 } 472 473 fprintf(stderr, 474 "acpi-test: Warning! %.4s binary file mismatch. " 475 "Actual [aml:%s], Expected [aml:%s].\n" 476 "See source file tests/qtest/bios-tables-test.c " 477 "for instructions on how to update expected files.\n", 478 exp_sdt->aml, sdt->aml_file, exp_sdt->aml_file); 479 480 all_tables_match = all_tables_match && 481 test_acpi_find_diff_allowed(exp_sdt); 482 483 /* 484 * don't try to decompile if IASL isn't present, in this case user 485 * will just 'get binary file mismatch' warnings and test failure 486 */ 487 if (!iasl) { 488 continue; 489 } 490 491 err = load_asl(data->tables, sdt); 492 asl = normalize_asl(sdt->asl); 493 494 /* 495 * If expected file is empty - it's likely that it was a stub just 496 * created for step 1 above: we do want to decompile the actual one. 497 */ 498 if (exp_sdt->aml_len) { 499 exp_err = load_asl(exp_data.tables, exp_sdt); 500 exp_asl = normalize_asl(exp_sdt->asl); 501 } else { 502 exp_err = create_tmp_asl(exp_sdt); 503 exp_asl = g_string_new(""); 504 } 505 506 /* TODO: check for warnings */ 507 g_assert(!err || exp_err || !exp_sdt->aml_len); 508 509 if (g_strcmp0(asl->str, exp_asl->str)) { 510 sdt->tmp_files_retain = true; 511 if (exp_err) { 512 fprintf(stderr, 513 "Warning! iasl couldn't parse the expected aml\n"); 514 } else { 515 exp_sdt->tmp_files_retain = true; 516 fprintf(stderr, 517 "acpi-test: Warning! %.4s mismatch. " 518 "Actual [asl:%s, aml:%s], Expected [asl:%s, aml:%s].\n", 519 exp_sdt->aml, sdt->asl_file, sdt->aml_file, 520 exp_sdt->asl_file, exp_sdt->aml_file); 521 fflush(stderr); 522 if (verbosity_level >= 1) { 523 const char *diff_env = getenv("DIFF"); 524 const char *diff_cmd = diff_env ? diff_env : "diff -U 16"; 525 char *diff = g_strdup_printf("%s %s %s", diff_cmd, 526 exp_sdt->asl_file, sdt->asl_file); 527 int out = dup(STDOUT_FILENO); 528 int ret G_GNUC_UNUSED; 529 int dupret; 530 531 g_assert(out >= 0); 532 dupret = dup2(STDERR_FILENO, STDOUT_FILENO); 533 g_assert(dupret >= 0); 534 ret = system(diff) ; 535 dupret = dup2(out, STDOUT_FILENO); 536 g_assert(dupret >= 0); 537 close(out); 538 g_free(diff); 539 } 540 } 541 } 542 g_string_free(asl, true); 543 g_string_free(exp_asl, true); 544 } 545 if (!iasl && !all_tables_match) { 546 fprintf(stderr, "to see ASL diff between mismatched files install IASL," 547 " rebuild QEMU from scratch and re-run tests with V=1" 548 " environment variable set"); 549 } 550 g_assert(all_tables_match); 551 552 free_test_data(&exp_data); 553 } 554 555 static bool smbios_ep2_table_ok(test_data *data, uint32_t addr) 556 { 557 struct smbios_21_entry_point *ep_table = &data->smbios_ep_table.ep21; 558 559 qtest_memread(data->qts, addr, ep_table, sizeof(*ep_table)); 560 if (memcmp(ep_table->anchor_string, "_SM_", 4)) { 561 return false; 562 } 563 if (memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5)) { 564 return false; 565 } 566 if (ep_table->structure_table_length == 0) { 567 return false; 568 } 569 if (ep_table->number_of_structures == 0) { 570 return false; 571 } 572 if (acpi_calc_checksum((uint8_t *)ep_table, sizeof *ep_table) || 573 acpi_calc_checksum((uint8_t *)ep_table + 0x10, 574 sizeof *ep_table - 0x10)) { 575 return false; 576 } 577 return true; 578 } 579 580 static bool smbios_ep3_table_ok(test_data *data, uint64_t addr) 581 { 582 struct smbios_30_entry_point *ep_table = &data->smbios_ep_table.ep30; 583 584 qtest_memread(data->qts, addr, ep_table, sizeof(*ep_table)); 585 if (memcmp(ep_table->anchor_string, "_SM3_", 5)) { 586 return false; 587 } 588 589 if (acpi_calc_checksum((uint8_t *)ep_table, sizeof *ep_table)) { 590 return false; 591 } 592 593 return true; 594 } 595 596 static SmbiosEntryPointType test_smbios_entry_point(test_data *data) 597 { 598 uint32_t off; 599 600 /* find smbios entry point structure */ 601 for (off = 0xf0000; off < 0x100000; off += 0x10) { 602 uint8_t sig[] = "_SM_", sig3[] = "_SM3_"; 603 int i; 604 605 for (i = 0; i < sizeof sig - 1; ++i) { 606 sig[i] = qtest_readb(data->qts, off + i); 607 } 608 609 if (!memcmp(sig, "_SM_", sizeof sig)) { 610 /* signature match, but is this a valid entry point? */ 611 if (smbios_ep2_table_ok(data, off)) { 612 data->smbios_ep_addr[SMBIOS_ENTRY_POINT_TYPE_32] = off; 613 } 614 } 615 616 for (i = 0; i < sizeof sig3 - 1; ++i) { 617 sig3[i] = qtest_readb(data->qts, off + i); 618 } 619 620 if (!memcmp(sig3, "_SM3_", sizeof sig3)) { 621 if (smbios_ep3_table_ok(data, off)) { 622 data->smbios_ep_addr[SMBIOS_ENTRY_POINT_TYPE_64] = off; 623 /* found 64-bit entry point, no need to look for 32-bit one */ 624 break; 625 } 626 } 627 } 628 629 /* found at least one entry point */ 630 g_assert_true(data->smbios_ep_addr[SMBIOS_ENTRY_POINT_TYPE_32] || 631 data->smbios_ep_addr[SMBIOS_ENTRY_POINT_TYPE_64]); 632 633 return data->smbios_ep_addr[SMBIOS_ENTRY_POINT_TYPE_64] ? 634 SMBIOS_ENTRY_POINT_TYPE_64 : SMBIOS_ENTRY_POINT_TYPE_32; 635 } 636 637 static inline bool smbios_single_instance(uint8_t type) 638 { 639 switch (type) { 640 case 0: 641 case 1: 642 case 2: 643 case 3: 644 case 16: 645 case 32: 646 case 127: 647 return true; 648 default: 649 return false; 650 } 651 } 652 653 static void smbios_cpu_test(test_data *data, uint32_t addr, 654 SmbiosEntryPointType ep_type) 655 { 656 uint8_t core_count, expected_core_count = data->smbios_core_count; 657 uint8_t thread_count, expected_thread_count = data->smbios_thread_count; 658 uint16_t speed, expected_speed[2]; 659 uint16_t core_count2, expected_core_count2 = data->smbios_core_count2; 660 uint16_t thread_count2, expected_thread_count2 = data->smbios_thread_count2; 661 int offset[2]; 662 int i; 663 664 /* Check CPU speed for backward compatibility */ 665 offset[0] = offsetof(struct smbios_type_4, max_speed); 666 offset[1] = offsetof(struct smbios_type_4, current_speed); 667 expected_speed[0] = data->smbios_cpu_max_speed ? : 2000; 668 expected_speed[1] = data->smbios_cpu_curr_speed ? : 2000; 669 670 for (i = 0; i < 2; i++) { 671 speed = qtest_readw(data->qts, addr + offset[i]); 672 g_assert_cmpuint(speed, ==, expected_speed[i]); 673 } 674 675 core_count = qtest_readb(data->qts, 676 addr + offsetof(struct smbios_type_4, core_count)); 677 678 if (expected_core_count) { 679 g_assert_cmpuint(core_count, ==, expected_core_count); 680 } 681 682 thread_count = qtest_readb(data->qts, 683 addr + offsetof(struct smbios_type_4, thread_count)); 684 685 if (expected_thread_count) { 686 g_assert_cmpuint(thread_count, ==, expected_thread_count); 687 } 688 689 if (ep_type == SMBIOS_ENTRY_POINT_TYPE_64) { 690 core_count2 = qtest_readw(data->qts, 691 addr + offsetof(struct smbios_type_4, core_count2)); 692 693 /* Core Count has reached its limit, checking Core Count 2 */ 694 if (expected_core_count == 0xFF && expected_core_count2) { 695 g_assert_cmpuint(core_count2, ==, expected_core_count2); 696 } 697 698 thread_count2 = qtest_readw(data->qts, 699 addr + offsetof(struct smbios_type_4, 700 thread_count2)); 701 702 /* Thread Count has reached its limit, checking Thread Count 2 */ 703 if (expected_thread_count == 0xFF && expected_thread_count2) { 704 g_assert_cmpuint(thread_count2, ==, expected_thread_count2); 705 } 706 } 707 } 708 709 static void smbios_type4_count_test(test_data *data, int type4_count) 710 { 711 int expected_type4_count = data->type4_count; 712 713 if (expected_type4_count) { 714 g_assert_cmpuint(type4_count, ==, expected_type4_count); 715 } 716 } 717 718 static void test_smbios_structs(test_data *data, SmbiosEntryPointType ep_type) 719 { 720 DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 }; 721 722 SmbiosEntryPoint *ep_table = &data->smbios_ep_table; 723 int i = 0, len, max_len = 0, type4_count = 0; 724 uint8_t type, prv, crt; 725 uint64_t addr; 726 727 if (ep_type == SMBIOS_ENTRY_POINT_TYPE_32) { 728 addr = le32_to_cpu(ep_table->ep21.structure_table_address); 729 } else { 730 addr = le64_to_cpu(ep_table->ep30.structure_table_address); 731 } 732 733 /* walk the smbios tables */ 734 do { 735 736 /* grab type and formatted area length from struct header */ 737 type = qtest_readb(data->qts, addr); 738 g_assert_cmpuint(type, <=, SMBIOS_MAX_TYPE); 739 len = qtest_readb(data->qts, addr + 1); 740 741 /* single-instance structs must not have been encountered before */ 742 if (smbios_single_instance(type)) { 743 g_assert(!test_bit(type, struct_bitmap)); 744 } 745 set_bit(type, struct_bitmap); 746 747 if (type == 4) { 748 smbios_cpu_test(data, addr, ep_type); 749 type4_count++; 750 } 751 752 /* seek to end of unformatted string area of this struct ("\0\0") */ 753 prv = crt = 1; 754 while (prv || crt) { 755 prv = crt; 756 crt = qtest_readb(data->qts, addr + len); 757 len++; 758 } 759 760 /* keep track of max. struct size */ 761 if (ep_type == SMBIOS_ENTRY_POINT_TYPE_32 && max_len < len) { 762 max_len = len; 763 g_assert_cmpuint(max_len, <=, ep_table->ep21.max_structure_size); 764 } 765 766 /* start of next structure */ 767 addr += len; 768 769 /* 770 * Until all structures have been scanned (ep21) 771 * or an EOF structure is found (ep30) 772 */ 773 } while (ep_type == SMBIOS_ENTRY_POINT_TYPE_32 ? 774 ++i < le16_to_cpu(ep_table->ep21.number_of_structures) : 775 type != 127); 776 777 if (ep_type == SMBIOS_ENTRY_POINT_TYPE_32) { 778 /* 779 * Total table length and max struct size 780 * must match entry point values 781 */ 782 g_assert_cmpuint(le16_to_cpu(ep_table->ep21.structure_table_length), ==, 783 addr - le32_to_cpu(ep_table->ep21.structure_table_address)); 784 785 g_assert_cmpuint(le16_to_cpu(ep_table->ep21.max_structure_size), ==, 786 max_len); 787 } 788 789 /* required struct types must all be present */ 790 for (i = 0; i < data->required_struct_types_len; i++) { 791 g_assert(test_bit(data->required_struct_types[i], struct_bitmap)); 792 } 793 794 smbios_type4_count_test(data, type4_count); 795 } 796 797 static void test_acpi_load_tables(test_data *data) 798 { 799 if (data->uefi_fl1 && data->uefi_fl2) { /* use UEFI */ 800 g_assert(data->scan_len); 801 data->rsdp_addr = acpi_find_rsdp_address_uefi(data->qts, 802 data->ram_start, data->scan_len); 803 } else { 804 boot_sector_test(data->qts); 805 data->rsdp_addr = acpi_find_rsdp_address(data->qts); 806 g_assert_cmphex(data->rsdp_addr, <, 0x100000); 807 } 808 809 data->tables = g_array_new(false, true, sizeof(AcpiSdtTable)); 810 test_acpi_rsdp_table(data); 811 test_acpi_rxsdt_table(data); 812 test_acpi_fadt_table(data); 813 } 814 815 static char *test_acpi_create_args(test_data *data, const char *params) 816 { 817 char *args; 818 819 if (data->uefi_fl1 && data->uefi_fl2) { /* use UEFI */ 820 /* 821 * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3) 822 * when arm/virt boad starts to support it. 823 */ 824 if (data->cd) { 825 args = g_strdup_printf("-machine %s%s %s -accel tcg " 826 "-nodefaults -nographic " 827 "-drive if=pflash,format=raw,file=%s,readonly=on " 828 "-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s", 829 data->machine, data->machine_param ?: "", 830 data->tcg_only ? "" : "-accel kvm", 831 data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : ""); 832 } else { 833 args = g_strdup_printf("-machine %s%s %s -accel tcg " 834 "-nodefaults -nographic " 835 "-drive if=pflash,format=raw,file=%s,readonly=on " 836 "-drive if=pflash,format=raw,file=%s,snapshot=on %s", 837 data->machine, data->machine_param ?: "", 838 data->tcg_only ? "" : "-accel kvm", 839 data->uefi_fl1, data->uefi_fl2, params ? params : ""); 840 } 841 } else { 842 args = g_strdup_printf("-machine %s%s %s -accel tcg " 843 "-net none %s " 844 "-drive id=hd0,if=none,file=%s,format=raw " 845 "-device %s,drive=hd0 ", 846 data->machine, data->machine_param ?: "", 847 data->tcg_only ? "" : "-accel kvm", 848 params ? params : "", disk, 849 data->blkdev ?: "ide-hd"); 850 } 851 return args; 852 } 853 854 static void test_vm_prepare(const char *params, test_data *data) 855 { 856 char *args = test_acpi_create_args(data, params); 857 data->qts = qtest_init(args); 858 g_free(args); 859 } 860 861 static void process_acpi_tables_noexit(test_data *data) 862 { 863 test_acpi_load_tables(data); 864 865 if (getenv(ACPI_REBUILD_EXPECTED_AML)) { 866 dump_aml_files(data, true); 867 } else { 868 test_acpi_asl(data); 869 } 870 871 /* 872 * TODO: make SMBIOS tests work with UEFI firmware, 873 * Bug on uefi-test-tools to provide entry point: 874 * https://bugs.launchpad.net/qemu/+bug/1821884 875 */ 876 if (!(data->uefi_fl1 && data->uefi_fl2)) { 877 SmbiosEntryPointType ep_type = test_smbios_entry_point(data); 878 test_smbios_structs(data, ep_type); 879 } 880 } 881 882 static void process_acpi_tables(test_data *data) 883 { 884 process_acpi_tables_noexit(data); 885 qtest_quit(data->qts); 886 } 887 888 static void test_acpi_one(const char *params, test_data *data) 889 { 890 test_vm_prepare(params, data); 891 process_acpi_tables(data); 892 } 893 894 static uint8_t base_required_struct_types[] = { 895 0, 1, 3, 4, 16, 17, 19, 32, 127 896 }; 897 898 static void test_acpi_piix4_tcg(void) 899 { 900 test_data data = {}; 901 902 /* Supplying -machine accel argument overrides the default (qtest). 903 * This is to make guest actually run. 904 */ 905 data.machine = MACHINE_PC; 906 data.required_struct_types = base_required_struct_types; 907 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 908 test_acpi_one(NULL, &data); 909 free_test_data(&data); 910 } 911 912 static void test_acpi_piix4_tcg_bridge(void) 913 { 914 test_data data = {}; 915 916 data.machine = MACHINE_PC; 917 data.variant = ".bridge"; 918 data.required_struct_types = base_required_struct_types; 919 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 920 test_vm_prepare("-S" 921 " -device pci-bridge,chassis_nr=1" 922 " -device pci-bridge,bus=pci.1,addr=1.0,chassis_nr=2" 923 " -device pci-testdev,bus=pci.0,addr=5.0" 924 " -device pci-testdev,bus=pci.1", &data); 925 926 /* hotplugged bridges section */ 927 qtest_qmp_device_add(data.qts, "pci-bridge", "hpbr", 928 "{'bus': 'pci.1', 'addr': '2.0', 'chassis_nr': 3 }"); 929 qtest_qmp_device_add(data.qts, "pci-bridge", "hpbr_multifunc", 930 "{'bus': 'pci.1', 'addr': '0xf.1', 'chassis_nr': 4 }"); 931 qtest_qmp_device_add(data.qts, "pci-bridge", "hpbrhost", 932 "{'bus': 'pci.0', 'addr': '4.0', 'chassis_nr': 5 }"); 933 qtest_qmp_device_add(data.qts, "pci-testdev", "d1", "{'bus': 'pci.0' }"); 934 qtest_qmp_device_add(data.qts, "pci-testdev", "d2", "{'bus': 'pci.1' }"); 935 qtest_qmp_device_add(data.qts, "pci-testdev", "d3", "{'bus': 'hpbr', " 936 "'addr': '1.0' }"); 937 qtest_qmp_send(data.qts, "{'execute':'cont' }"); 938 qtest_qmp_eventwait(data.qts, "RESUME"); 939 940 process_acpi_tables_noexit(&data); 941 free_test_data(&data); 942 943 /* check that reboot/reset doesn't change any ACPI tables */ 944 qtest_qmp_send(data.qts, "{'execute':'system_reset' }"); 945 process_acpi_tables(&data); 946 free_test_data(&data); 947 } 948 949 static void test_acpi_piix4_no_root_hotplug(void) 950 { 951 test_data data = {}; 952 953 data.machine = MACHINE_PC; 954 data.variant = ".roothp"; 955 data.required_struct_types = base_required_struct_types; 956 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 957 test_acpi_one("-global PIIX4_PM.acpi-root-pci-hotplug=off " 958 "-device pci-bridge,chassis_nr=1 " 959 "-device pci-bridge,bus=pci.1,addr=1.0,chassis_nr=2 " 960 "-device pci-testdev,bus=pci.0 " 961 "-device pci-testdev,bus=pci.1", &data); 962 free_test_data(&data); 963 } 964 965 static void test_acpi_piix4_no_bridge_hotplug(void) 966 { 967 test_data data = {}; 968 969 data.machine = MACHINE_PC; 970 data.variant = ".hpbridge"; 971 data.required_struct_types = base_required_struct_types; 972 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 973 test_acpi_one("-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off " 974 "-device pci-bridge,chassis_nr=1 " 975 "-device pci-bridge,bus=pci.1,addr=1.0,chassis_nr=2 " 976 "-device pci-testdev,bus=pci.0 " 977 "-device pci-testdev,bus=pci.1,addr=2.0", &data); 978 free_test_data(&data); 979 } 980 981 static void test_acpi_piix4_no_acpi_pci_hotplug(void) 982 { 983 test_data data = {}; 984 985 data.machine = MACHINE_PC; 986 data.variant = ".hpbrroot"; 987 data.required_struct_types = base_required_struct_types; 988 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 989 test_acpi_one("-global PIIX4_PM.acpi-root-pci-hotplug=off " 990 "-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off " 991 "-device pci-bridge,chassis_nr=1,addr=4.0 " 992 "-device pci-testdev,bus=pci.0,addr=5.0 " 993 "-device pci-testdev,bus=pci.0,addr=6.0,acpi-index=101 " 994 "-device pci-testdev,bus=pci.1,addr=1.0 " 995 "-device pci-testdev,bus=pci.1,addr=2.0,acpi-index=201 " 996 "-device pci-bridge,id=nhpbr,chassis_nr=2,shpc=off,addr=7.0 " 997 "-device pci-testdev,bus=nhpbr,addr=1.0,acpi-index=301 " 998 , &data); 999 free_test_data(&data); 1000 } 1001 1002 static void test_acpi_q35_tcg(void) 1003 { 1004 test_data data = {}; 1005 1006 data.machine = MACHINE_Q35; 1007 data.required_struct_types = base_required_struct_types; 1008 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 1009 test_acpi_one(NULL, &data); 1010 free_test_data(&data); 1011 1012 data.smbios_cpu_max_speed = 3000; 1013 data.smbios_cpu_curr_speed = 2600; 1014 test_acpi_one("-smbios type=4,max-speed=3000,current-speed=2600", &data); 1015 free_test_data(&data); 1016 } 1017 1018 static void test_acpi_q35_tcg_type4_count(void) 1019 { 1020 test_data data = { 1021 .machine = MACHINE_Q35, 1022 .variant = ".type4-count", 1023 .required_struct_types = base_required_struct_types, 1024 .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), 1025 .type4_count = 5, 1026 }; 1027 1028 test_acpi_one("-machine smbios-entry-point-type=64 " 1029 "-smp cpus=100,maxcpus=120,sockets=5," 1030 "dies=2,cores=4,threads=3", &data); 1031 free_test_data(&data); 1032 } 1033 1034 static void test_acpi_q35_tcg_core_count(void) 1035 { 1036 test_data data = { 1037 .machine = MACHINE_Q35, 1038 .variant = ".core-count", 1039 .required_struct_types = base_required_struct_types, 1040 .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), 1041 .smbios_core_count = 9, 1042 .smbios_core_count2 = 9, 1043 }; 1044 1045 test_acpi_one("-machine smbios-entry-point-type=64 " 1046 "-smp 54,sockets=2,dies=3,cores=3,threads=3", 1047 &data); 1048 free_test_data(&data); 1049 } 1050 1051 static void test_acpi_q35_tcg_core_count2(void) 1052 { 1053 test_data data = { 1054 .machine = MACHINE_Q35, 1055 .variant = ".core-count2", 1056 .required_struct_types = base_required_struct_types, 1057 .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), 1058 .smbios_core_count = 0xFF, 1059 .smbios_core_count2 = 260, 1060 }; 1061 1062 test_acpi_one("-machine smbios-entry-point-type=64 " 1063 "-smp 260,dies=2,cores=130,threads=1", 1064 &data); 1065 free_test_data(&data); 1066 } 1067 1068 static void test_acpi_q35_tcg_thread_count(void) 1069 { 1070 test_data data = { 1071 .machine = MACHINE_Q35, 1072 .variant = ".thread-count", 1073 .required_struct_types = base_required_struct_types, 1074 .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), 1075 .smbios_thread_count = 27, 1076 .smbios_thread_count2 = 27, 1077 }; 1078 1079 test_acpi_one("-machine smbios-entry-point-type=64 " 1080 "-smp cpus=15,maxcpus=54,sockets=2,dies=3,cores=3,threads=3", 1081 &data); 1082 free_test_data(&data); 1083 } 1084 1085 static void test_acpi_q35_tcg_thread_count2(void) 1086 { 1087 test_data data = { 1088 .machine = MACHINE_Q35, 1089 .variant = ".thread-count2", 1090 .required_struct_types = base_required_struct_types, 1091 .required_struct_types_len = ARRAY_SIZE(base_required_struct_types), 1092 .smbios_thread_count = 0xFF, 1093 .smbios_thread_count2 = 260, 1094 }; 1095 1096 test_acpi_one("-machine smbios-entry-point-type=64 " 1097 "-smp cpus=210,maxcpus=260,dies=2,cores=65,threads=2", 1098 &data); 1099 free_test_data(&data); 1100 } 1101 1102 static void test_acpi_q35_tcg_bridge(void) 1103 { 1104 test_data data = {}; 1105 1106 data.machine = MACHINE_Q35; 1107 data.variant = ".bridge"; 1108 data.required_struct_types = base_required_struct_types; 1109 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 1110 test_acpi_one("-device pci-bridge,chassis_nr=1,id=br1" 1111 " -device pci-testdev,bus=pcie.0" 1112 " -device pci-testdev,bus=br1", &data); 1113 free_test_data(&data); 1114 } 1115 1116 static void test_acpi_q35_tcg_no_acpi_hotplug(void) 1117 { 1118 test_data data = {}; 1119 1120 data.machine = MACHINE_Q35; 1121 data.variant = ".noacpihp"; 1122 data.required_struct_types = base_required_struct_types; 1123 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 1124 test_acpi_one("-global ICH9-LPC.acpi-pci-hotplug-with-bridge-support=off" 1125 " -device pci-testdev,bus=pcie.0,acpi-index=101,addr=3.0" 1126 " -device pci-bridge,chassis_nr=1,id=shpcbr,addr=4.0" 1127 " -device pci-testdev,bus=shpcbr,addr=1.0,acpi-index=201" 1128 " -device pci-bridge,chassis_nr=2,shpc=off,id=noshpcbr,addr=5.0" 1129 " -device pci-testdev,bus=noshpcbr,addr=1.0,acpi-index=301" 1130 " -device pcie-root-port,id=hprp,port=0x0,chassis=1,addr=6.0" 1131 " -device pci-testdev,bus=hprp,acpi-index=401" 1132 " -device pcie-root-port,id=nohprp,port=0x0,chassis=2,hotplug=off," 1133 "addr=7.0" 1134 " -device pci-testdev,bus=nohprp,acpi-index=501" 1135 " -device pcie-root-port,id=nohprpint,port=0x0,chassis=3,hotplug=off," 1136 "multifunction=on,addr=8.0" 1137 " -device pci-testdev,bus=nohprpint,acpi-index=601,addr=0.1" 1138 " -device pcie-root-port,id=hprp2,port=0x0,chassis=4,bus=nohprpint," 1139 "addr=0.2" 1140 " -device pci-testdev,bus=hprp2,acpi-index=602" 1141 , &data); 1142 free_test_data(&data); 1143 } 1144 1145 static void test_acpi_q35_multif_bridge(void) 1146 { 1147 test_data data = { 1148 .machine = MACHINE_Q35, 1149 .variant = ".multi-bridge", 1150 }; 1151 test_vm_prepare("-S" 1152 " -device virtio-balloon,id=balloon0,addr=0x4.0x2" 1153 " -device pcie-root-port,id=rp0,multifunction=on," 1154 "port=0x0,chassis=1,addr=0x2" 1155 " -device pcie-root-port,id=rp1,port=0x1,chassis=2,addr=0x3.0x1" 1156 " -device pcie-root-port,id=rp2,port=0x0,chassis=3,bus=rp1,addr=0.0" 1157 " -device pci-bridge,bus=rp2,chassis_nr=4,id=br1" 1158 " -device pcie-root-port,id=rphptgt1,port=0x0,chassis=5,addr=2.1" 1159 " -device pcie-root-port,id=rphptgt2,port=0x0,chassis=6,addr=2.2" 1160 " -device pcie-root-port,id=rphptgt3,port=0x0,chassis=7,addr=2.3" 1161 " -device pci-testdev,bus=pcie.0,addr=2.4" 1162 " -device pci-testdev,bus=pcie.0,addr=2.5,acpi-index=102" 1163 " -device pci-testdev,bus=pcie.0,addr=5.0" 1164 " -device pci-testdev,bus=pcie.0,addr=0xf.0,acpi-index=101" 1165 " -device pci-testdev,bus=rp0,addr=0.0" 1166 " -device pci-testdev,bus=br1" 1167 " -device pcie-root-port,id=rpnohp,chassis=8,addr=0xA.0,hotplug=off" 1168 " -device pcie-root-port,id=rp3,chassis=9,bus=rpnohp" 1169 , &data); 1170 1171 /* hotplugged bridges section */ 1172 qtest_qmp_device_add(data.qts, "pci-bridge", "hpbr1", 1173 "{'bus': 'br1', 'addr': '6.0', 'chassis_nr': 128 }"); 1174 qtest_qmp_device_add(data.qts, "pci-bridge", "hpbr2-multiif", 1175 "{ 'bus': 'br1', 'addr': '2.2', 'chassis_nr': 129 }"); 1176 qtest_qmp_device_add(data.qts, "pcie-pci-bridge", "hpbr3", 1177 "{'bus': 'rphptgt1', 'addr': '0.0' }"); 1178 qtest_qmp_device_add(data.qts, "pcie-root-port", "hprp", 1179 "{'bus': 'rphptgt2', 'addr': '0.0' }"); 1180 qtest_qmp_device_add(data.qts, "pci-testdev", "hpnic", 1181 "{'bus': 'rphptgt3', 'addr': '0.0' }"); 1182 qtest_qmp_send(data.qts, "{'execute':'cont' }"); 1183 qtest_qmp_eventwait(data.qts, "RESUME"); 1184 1185 process_acpi_tables_noexit(&data); 1186 free_test_data(&data); 1187 1188 /* check that reboot/reset doesn't change any ACPI tables */ 1189 qtest_qmp_send(data.qts, "{'execute':'system_reset' }"); 1190 process_acpi_tables(&data); 1191 free_test_data(&data); 1192 } 1193 1194 static void test_acpi_q35_tcg_mmio64(void) 1195 { 1196 test_data data = { 1197 .machine = MACHINE_Q35, 1198 .variant = ".mmio64", 1199 .tcg_only = true, 1200 .required_struct_types = base_required_struct_types, 1201 .required_struct_types_len = ARRAY_SIZE(base_required_struct_types) 1202 }; 1203 1204 test_acpi_one("-m 128M,slots=1,maxmem=2G " 1205 "-cpu Opteron_G1 " 1206 "-object memory-backend-ram,id=ram0,size=128M " 1207 "-numa node,memdev=ram0 " 1208 "-device pci-testdev,membar=2G", 1209 &data); 1210 free_test_data(&data); 1211 } 1212 1213 static void test_acpi_piix4_tcg_cphp(void) 1214 { 1215 test_data data = {}; 1216 1217 data.machine = MACHINE_PC; 1218 data.variant = ".cphp"; 1219 test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6" 1220 " -object memory-backend-ram,id=ram0,size=64M" 1221 " -object memory-backend-ram,id=ram1,size=64M" 1222 " -numa node,memdev=ram0 -numa node,memdev=ram1" 1223 " -numa dist,src=0,dst=1,val=21", 1224 &data); 1225 free_test_data(&data); 1226 } 1227 1228 static void test_acpi_q35_tcg_cphp(void) 1229 { 1230 test_data data = {}; 1231 1232 data.machine = MACHINE_Q35; 1233 data.variant = ".cphp"; 1234 test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6" 1235 " -object memory-backend-ram,id=ram0,size=64M" 1236 " -object memory-backend-ram,id=ram1,size=64M" 1237 " -numa node,memdev=ram0 -numa node,memdev=ram1" 1238 " -numa dist,src=0,dst=1,val=21", 1239 &data); 1240 free_test_data(&data); 1241 } 1242 1243 static uint8_t ipmi_required_struct_types[] = { 1244 0, 1, 3, 4, 16, 17, 19, 32, 38, 127 1245 }; 1246 1247 static void test_acpi_q35_tcg_ipmi(void) 1248 { 1249 test_data data = {}; 1250 1251 data.machine = MACHINE_Q35; 1252 data.variant = ".ipmibt"; 1253 data.required_struct_types = ipmi_required_struct_types; 1254 data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); 1255 test_acpi_one("-device ipmi-bmc-sim,id=bmc0" 1256 " -device isa-ipmi-bt,bmc=bmc0", 1257 &data); 1258 free_test_data(&data); 1259 } 1260 1261 static void test_acpi_q35_tcg_smbus_ipmi(void) 1262 { 1263 test_data data = {}; 1264 1265 data.machine = MACHINE_Q35; 1266 data.variant = ".ipmismbus"; 1267 data.required_struct_types = ipmi_required_struct_types; 1268 data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); 1269 test_acpi_one("-device ipmi-bmc-sim,id=bmc0" 1270 " -device smbus-ipmi,bmc=bmc0", 1271 &data); 1272 free_test_data(&data); 1273 } 1274 1275 static void test_acpi_piix4_tcg_ipmi(void) 1276 { 1277 test_data data = {}; 1278 1279 /* Supplying -machine accel argument overrides the default (qtest). 1280 * This is to make guest actually run. 1281 */ 1282 data.machine = MACHINE_PC; 1283 data.variant = ".ipmikcs"; 1284 data.required_struct_types = ipmi_required_struct_types; 1285 data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); 1286 test_acpi_one("-device ipmi-bmc-sim,id=bmc0" 1287 " -device isa-ipmi-kcs,irq=0,bmc=bmc0", 1288 &data); 1289 free_test_data(&data); 1290 } 1291 1292 static void test_acpi_q35_tcg_memhp(void) 1293 { 1294 test_data data = {}; 1295 1296 data.machine = MACHINE_Q35; 1297 data.variant = ".memhp"; 1298 test_acpi_one(" -m 128,slots=3,maxmem=1G" 1299 " -object memory-backend-ram,id=ram0,size=64M" 1300 " -object memory-backend-ram,id=ram1,size=64M" 1301 " -numa node,memdev=ram0 -numa node,memdev=ram1" 1302 " -numa dist,src=0,dst=1,val=21", 1303 &data); 1304 free_test_data(&data); 1305 } 1306 1307 static void test_acpi_piix4_tcg_memhp(void) 1308 { 1309 test_data data = {}; 1310 1311 data.machine = MACHINE_PC; 1312 data.variant = ".memhp"; 1313 test_acpi_one(" -m 128,slots=3,maxmem=1G" 1314 " -object memory-backend-ram,id=ram0,size=64M" 1315 " -object memory-backend-ram,id=ram1,size=64M" 1316 " -numa node,memdev=ram0 -numa node,memdev=ram1" 1317 " -numa dist,src=0,dst=1,val=21", 1318 &data); 1319 free_test_data(&data); 1320 } 1321 1322 static void test_acpi_piix4_tcg_nosmm(void) 1323 { 1324 test_data data = {}; 1325 1326 data.machine = MACHINE_PC; 1327 data.variant = ".nosmm"; 1328 test_acpi_one("-machine smm=off", &data); 1329 free_test_data(&data); 1330 } 1331 1332 static void test_acpi_piix4_tcg_smm_compat(void) 1333 { 1334 test_data data = {}; 1335 1336 data.machine = MACHINE_PC; 1337 data.variant = ".smm-compat"; 1338 test_acpi_one("-global PIIX4_PM.smm-compat=on", &data); 1339 free_test_data(&data); 1340 } 1341 1342 static void test_acpi_piix4_tcg_smm_compat_nosmm(void) 1343 { 1344 test_data data = {}; 1345 1346 data.machine = MACHINE_PC; 1347 data.variant = ".smm-compat-nosmm"; 1348 test_acpi_one("-global PIIX4_PM.smm-compat=on -machine smm=off", &data); 1349 free_test_data(&data); 1350 } 1351 1352 static void test_acpi_piix4_tcg_nohpet(void) 1353 { 1354 test_data data = {}; 1355 1356 data.machine = MACHINE_PC; 1357 data.machine_param = ",hpet=off"; 1358 data.variant = ".nohpet"; 1359 test_acpi_one(NULL, &data); 1360 free_test_data(&data); 1361 } 1362 1363 static void test_acpi_q35_tcg_numamem(void) 1364 { 1365 test_data data = {}; 1366 1367 data.machine = MACHINE_Q35; 1368 data.variant = ".numamem"; 1369 test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M" 1370 " -numa node -numa node,memdev=ram0", &data); 1371 free_test_data(&data); 1372 } 1373 1374 static void test_acpi_q35_kvm_xapic(void) 1375 { 1376 test_data data = {}; 1377 1378 data.machine = MACHINE_Q35; 1379 data.variant = ".xapic"; 1380 test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M" 1381 " -numa node -numa node,memdev=ram0" 1382 " -machine kernel-irqchip=on -smp 1,maxcpus=288", &data); 1383 free_test_data(&data); 1384 } 1385 1386 static void test_acpi_q35_tcg_nosmm(void) 1387 { 1388 test_data data = {}; 1389 1390 data.machine = MACHINE_Q35; 1391 data.variant = ".nosmm"; 1392 test_acpi_one("-machine smm=off", &data); 1393 free_test_data(&data); 1394 } 1395 1396 static void test_acpi_q35_tcg_smm_compat(void) 1397 { 1398 test_data data = {}; 1399 1400 data.machine = MACHINE_Q35; 1401 data.variant = ".smm-compat"; 1402 test_acpi_one("-global ICH9-LPC.smm-compat=on", &data); 1403 free_test_data(&data); 1404 } 1405 1406 static void test_acpi_q35_tcg_smm_compat_nosmm(void) 1407 { 1408 test_data data = {}; 1409 1410 data.machine = MACHINE_Q35; 1411 data.variant = ".smm-compat-nosmm"; 1412 test_acpi_one("-global ICH9-LPC.smm-compat=on -machine smm=off", &data); 1413 free_test_data(&data); 1414 } 1415 1416 static void test_acpi_q35_tcg_nohpet(void) 1417 { 1418 test_data data = {}; 1419 1420 data.machine = MACHINE_Q35; 1421 data.machine_param = ",hpet=off"; 1422 data.variant = ".nohpet"; 1423 test_acpi_one(NULL, &data); 1424 free_test_data(&data); 1425 } 1426 1427 static void test_acpi_q35_kvm_dmar(void) 1428 { 1429 test_data data = {}; 1430 1431 data.machine = MACHINE_Q35; 1432 data.variant = ".dmar"; 1433 test_acpi_one("-machine kernel-irqchip=split -accel kvm" 1434 " -device intel-iommu,intremap=on,device-iotlb=on", &data); 1435 free_test_data(&data); 1436 } 1437 1438 static void test_acpi_q35_tcg_ivrs(void) 1439 { 1440 test_data data = {}; 1441 1442 data.machine = MACHINE_Q35; 1443 data.variant = ".ivrs"; 1444 data.tcg_only = true, 1445 test_acpi_one(" -device amd-iommu", &data); 1446 free_test_data(&data); 1447 } 1448 1449 static void test_acpi_piix4_tcg_numamem(void) 1450 { 1451 test_data data = {}; 1452 1453 data.machine = MACHINE_PC; 1454 data.variant = ".numamem"; 1455 test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M" 1456 " -numa node -numa node,memdev=ram0", &data); 1457 free_test_data(&data); 1458 } 1459 1460 uint64_t tpm_tis_base_addr; 1461 1462 static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if, 1463 uint64_t base, enum TPMVersion tpm_version) 1464 { 1465 gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XXXXXX", 1466 machine, tpm_if); 1467 char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL); 1468 TPMTestState test; 1469 test_data data = {}; 1470 GThread *thread; 1471 const char *suffix = tpm_version == TPM_VERSION_2_0 ? "tpm2" : "tpm12"; 1472 char *args, *variant = g_strdup_printf(".%s.%s", tpm_if, suffix); 1473 1474 tpm_tis_base_addr = base; 1475 1476 module_call_init(MODULE_INIT_QOM); 1477 1478 test.addr = g_new0(SocketAddress, 1); 1479 test.addr->type = SOCKET_ADDRESS_TYPE_UNIX; 1480 test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL); 1481 g_mutex_init(&test.data_mutex); 1482 g_cond_init(&test.data_cond); 1483 test.data_cond_signal = false; 1484 test.tpm_version = tpm_version; 1485 1486 thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test); 1487 tpm_emu_test_wait_cond(&test); 1488 1489 data.machine = machine; 1490 data.variant = variant; 1491 1492 args = g_strdup_printf( 1493 " -chardev socket,id=chr,path=%s" 1494 " -tpmdev emulator,id=dev,chardev=chr" 1495 " -device tpm-%s,tpmdev=dev", 1496 test.addr->u.q_unix.path, tpm_if); 1497 1498 test_acpi_one(args, &data); 1499 1500 g_thread_join(thread); 1501 g_unlink(test.addr->u.q_unix.path); 1502 qapi_free_SocketAddress(test.addr); 1503 g_rmdir(tmp_path); 1504 g_free(variant); 1505 g_free(tmp_path); 1506 g_free(tmp_dir_name); 1507 g_free(args); 1508 free_test_data(&data); 1509 } 1510 1511 static void test_acpi_q35_tcg_tpm2_tis(void) 1512 { 1513 test_acpi_tcg_tpm("q35", "tis", 0xFED40000, TPM_VERSION_2_0); 1514 } 1515 1516 static void test_acpi_q35_tcg_tpm12_tis(void) 1517 { 1518 test_acpi_tcg_tpm("q35", "tis", 0xFED40000, TPM_VERSION_1_2); 1519 } 1520 1521 static void test_acpi_tcg_dimm_pxm(const char *machine) 1522 { 1523 test_data data = {}; 1524 1525 data.machine = machine; 1526 data.variant = ".dimmpxm"; 1527 test_acpi_one(" -machine nvdimm=on,nvdimm-persistence=cpu" 1528 " -smp 4,sockets=4" 1529 " -m 128M,slots=3,maxmem=1G" 1530 " -object memory-backend-ram,id=ram0,size=32M" 1531 " -object memory-backend-ram,id=ram1,size=32M" 1532 " -object memory-backend-ram,id=ram2,size=32M" 1533 " -object memory-backend-ram,id=ram3,size=32M" 1534 " -numa node,memdev=ram0,nodeid=0" 1535 " -numa node,memdev=ram1,nodeid=1" 1536 " -numa node,memdev=ram2,nodeid=2" 1537 " -numa node,memdev=ram3,nodeid=3" 1538 " -numa cpu,node-id=0,socket-id=0" 1539 " -numa cpu,node-id=1,socket-id=1" 1540 " -numa cpu,node-id=2,socket-id=2" 1541 " -numa cpu,node-id=3,socket-id=3" 1542 " -object memory-backend-ram,id=ram4,size=128M" 1543 " -object memory-backend-ram,id=nvm0,size=128M" 1544 " -device pc-dimm,id=dimm0,memdev=ram4,node=1" 1545 " -device nvdimm,id=dimm1,memdev=nvm0,node=2", 1546 &data); 1547 free_test_data(&data); 1548 } 1549 1550 static void test_acpi_q35_tcg_dimm_pxm(void) 1551 { 1552 test_acpi_tcg_dimm_pxm(MACHINE_Q35); 1553 } 1554 1555 static void test_acpi_piix4_tcg_dimm_pxm(void) 1556 { 1557 test_acpi_tcg_dimm_pxm(MACHINE_PC); 1558 } 1559 1560 static void test_acpi_virt_tcg_memhp(void) 1561 { 1562 test_data data = { 1563 .machine = "virt", 1564 .tcg_only = true, 1565 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 1566 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 1567 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 1568 .ram_start = 0x40000000ULL, 1569 .scan_len = 256ULL * 1024 * 1024, 1570 }; 1571 1572 data.variant = ".memhp"; 1573 test_acpi_one(" -machine nvdimm=on" 1574 " -cpu cortex-a57" 1575 " -m 256M,slots=3,maxmem=1G" 1576 " -object memory-backend-ram,id=ram0,size=128M" 1577 " -object memory-backend-ram,id=ram1,size=128M" 1578 " -numa node,memdev=ram0 -numa node,memdev=ram1" 1579 " -numa dist,src=0,dst=1,val=21" 1580 " -object memory-backend-ram,id=ram2,size=128M" 1581 " -object memory-backend-ram,id=nvm0,size=128M" 1582 " -device pc-dimm,id=dimm0,memdev=ram2,node=0" 1583 " -device nvdimm,id=dimm1,memdev=nvm0,node=1", 1584 &data); 1585 1586 free_test_data(&data); 1587 1588 } 1589 1590 static void test_acpi_microvm_prepare(test_data *data) 1591 { 1592 data->machine = "microvm"; 1593 data->required_struct_types = NULL; /* no smbios */ 1594 data->required_struct_types_len = 0; 1595 data->blkdev = "virtio-blk-device"; 1596 } 1597 1598 static void test_acpi_microvm_tcg(void) 1599 { 1600 test_data data = {}; 1601 1602 test_acpi_microvm_prepare(&data); 1603 test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,rtc=off", 1604 &data); 1605 free_test_data(&data); 1606 } 1607 1608 static void test_acpi_microvm_usb_tcg(void) 1609 { 1610 test_data data = {}; 1611 1612 test_acpi_microvm_prepare(&data); 1613 data.variant = ".usb"; 1614 test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,usb=on,rtc=off", 1615 &data); 1616 free_test_data(&data); 1617 } 1618 1619 static void test_acpi_microvm_rtc_tcg(void) 1620 { 1621 test_data data = {}; 1622 1623 test_acpi_microvm_prepare(&data); 1624 data.variant = ".rtc"; 1625 test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,rtc=on", 1626 &data); 1627 free_test_data(&data); 1628 } 1629 1630 static void test_acpi_microvm_pcie_tcg(void) 1631 { 1632 test_data data = {}; 1633 1634 test_acpi_microvm_prepare(&data); 1635 data.variant = ".pcie"; 1636 data.tcg_only = true; /* need constant host-phys-bits */ 1637 test_acpi_one(" -machine microvm,acpi=on,ioapic2=off,rtc=off,pcie=on", 1638 &data); 1639 free_test_data(&data); 1640 } 1641 1642 static void test_acpi_microvm_ioapic2_tcg(void) 1643 { 1644 test_data data = {}; 1645 1646 test_acpi_microvm_prepare(&data); 1647 data.variant = ".ioapic2"; 1648 test_acpi_one(" -machine microvm,acpi=on,ioapic2=on,rtc=off", 1649 &data); 1650 free_test_data(&data); 1651 } 1652 1653 static void test_acpi_virt_tcg_numamem(void) 1654 { 1655 test_data data = { 1656 .machine = "virt", 1657 .tcg_only = true, 1658 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 1659 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 1660 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 1661 .ram_start = 0x40000000ULL, 1662 .scan_len = 128ULL * 1024 * 1024, 1663 }; 1664 1665 data.variant = ".numamem"; 1666 test_acpi_one(" -cpu cortex-a57" 1667 " -object memory-backend-ram,id=ram0,size=128M" 1668 " -numa node,memdev=ram0", 1669 &data); 1670 1671 free_test_data(&data); 1672 1673 } 1674 1675 static void test_acpi_virt_tcg_pxb(void) 1676 { 1677 test_data data = { 1678 .machine = "virt", 1679 .tcg_only = true, 1680 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 1681 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 1682 .ram_start = 0x40000000ULL, 1683 .scan_len = 128ULL * 1024 * 1024, 1684 }; 1685 /* 1686 * While using -cdrom, the cdrom would auto plugged into pxb-pcie, 1687 * the reason is the bus of pxb-pcie is also root bus, it would lead 1688 * to the error only PCI/PCIE bridge could plug onto pxb. 1689 * Therefore,thr cdrom is defined and plugged onto the scsi controller 1690 * to solve the conflicts. 1691 */ 1692 data.variant = ".pxb"; 1693 test_acpi_one(" -device pcie-root-port,chassis=1,id=pci.1" 1694 " -device virtio-scsi-pci,id=scsi0,bus=pci.1" 1695 " -drive file=" 1696 "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2," 1697 "if=none,media=cdrom,id=drive-scsi0-0-0-1,readonly=on" 1698 " -device scsi-cd,bus=scsi0.0,scsi-id=0," 1699 "drive=drive-scsi0-0-0-1,id=scsi0-0-0-1,bootindex=1" 1700 " -cpu cortex-a57" 1701 " -device pxb-pcie,bus_nr=128", 1702 &data); 1703 1704 free_test_data(&data); 1705 } 1706 1707 static void test_acpi_tcg_acpi_hmat(const char *machine) 1708 { 1709 test_data data = {}; 1710 1711 data.machine = machine; 1712 data.variant = ".acpihmat"; 1713 test_acpi_one(" -machine hmat=on" 1714 " -smp 2,sockets=2" 1715 " -m 128M,slots=2,maxmem=1G" 1716 " -object memory-backend-ram,size=64M,id=m0" 1717 " -object memory-backend-ram,size=64M,id=m1" 1718 " -numa node,nodeid=0,memdev=m0" 1719 " -numa node,nodeid=1,memdev=m1,initiator=0" 1720 " -numa cpu,node-id=0,socket-id=0" 1721 " -numa cpu,node-id=0,socket-id=1" 1722 " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," 1723 "data-type=access-latency,latency=1" 1724 " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," 1725 "data-type=access-bandwidth,bandwidth=65534M" 1726 " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," 1727 "data-type=access-latency,latency=65534" 1728 " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," 1729 "data-type=access-bandwidth,bandwidth=32767M" 1730 " -numa hmat-cache,node-id=0,size=10K,level=1," 1731 "associativity=direct,policy=write-back,line=8" 1732 " -numa hmat-cache,node-id=1,size=10K,level=1," 1733 "associativity=direct,policy=write-back,line=8", 1734 &data); 1735 free_test_data(&data); 1736 } 1737 1738 static void test_acpi_q35_tcg_acpi_hmat(void) 1739 { 1740 test_acpi_tcg_acpi_hmat(MACHINE_Q35); 1741 } 1742 1743 static void test_acpi_piix4_tcg_acpi_hmat(void) 1744 { 1745 test_acpi_tcg_acpi_hmat(MACHINE_PC); 1746 } 1747 1748 static void test_acpi_virt_tcg_acpi_hmat(void) 1749 { 1750 test_data data = { 1751 .machine = "virt", 1752 .tcg_only = true, 1753 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 1754 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 1755 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 1756 .ram_start = 0x40000000ULL, 1757 .scan_len = 128ULL * 1024 * 1024, 1758 }; 1759 1760 data.variant = ".acpihmatvirt"; 1761 1762 test_acpi_one(" -machine hmat=on" 1763 " -cpu cortex-a57" 1764 " -smp 4,sockets=2" 1765 " -m 384M" 1766 " -object memory-backend-ram,size=128M,id=ram0" 1767 " -object memory-backend-ram,size=128M,id=ram1" 1768 " -object memory-backend-ram,size=128M,id=ram2" 1769 " -numa node,nodeid=0,memdev=ram0" 1770 " -numa node,nodeid=1,memdev=ram1" 1771 " -numa node,nodeid=2,memdev=ram2" 1772 " -numa cpu,node-id=0,socket-id=0" 1773 " -numa cpu,node-id=0,socket-id=0" 1774 " -numa cpu,node-id=1,socket-id=1" 1775 " -numa cpu,node-id=1,socket-id=1" 1776 " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," 1777 "data-type=access-latency,latency=10" 1778 " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," 1779 "data-type=access-bandwidth,bandwidth=10485760" 1780 " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," 1781 "data-type=access-latency,latency=20" 1782 " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," 1783 "data-type=access-bandwidth,bandwidth=5242880" 1784 " -numa hmat-lb,initiator=0,target=2,hierarchy=memory," 1785 "data-type=access-latency,latency=30" 1786 " -numa hmat-lb,initiator=0,target=2,hierarchy=memory," 1787 "data-type=access-bandwidth,bandwidth=1048576" 1788 " -numa hmat-lb,initiator=1,target=0,hierarchy=memory," 1789 "data-type=access-latency,latency=20" 1790 " -numa hmat-lb,initiator=1,target=0,hierarchy=memory," 1791 "data-type=access-bandwidth,bandwidth=5242880" 1792 " -numa hmat-lb,initiator=1,target=1,hierarchy=memory," 1793 "data-type=access-latency,latency=10" 1794 " -numa hmat-lb,initiator=1,target=1,hierarchy=memory," 1795 "data-type=access-bandwidth,bandwidth=10485760" 1796 " -numa hmat-lb,initiator=1,target=2,hierarchy=memory," 1797 "data-type=access-latency,latency=30" 1798 " -numa hmat-lb,initiator=1,target=2,hierarchy=memory," 1799 "data-type=access-bandwidth,bandwidth=1048576", 1800 &data); 1801 1802 free_test_data(&data); 1803 } 1804 1805 static void test_acpi_q35_tcg_acpi_hmat_noinitiator(void) 1806 { 1807 test_data data = {}; 1808 1809 data.machine = MACHINE_Q35; 1810 data.variant = ".acpihmat-noinitiator"; 1811 test_acpi_one(" -machine hmat=on" 1812 " -smp 4,sockets=2" 1813 " -m 128M" 1814 " -object memory-backend-ram,size=32M,id=ram0" 1815 " -object memory-backend-ram,size=32M,id=ram1" 1816 " -object memory-backend-ram,size=64M,id=ram2" 1817 " -numa node,nodeid=0,memdev=ram0" 1818 " -numa node,nodeid=1,memdev=ram1" 1819 " -numa node,nodeid=2,memdev=ram2" 1820 " -numa cpu,node-id=0,socket-id=0" 1821 " -numa cpu,node-id=0,socket-id=0" 1822 " -numa cpu,node-id=1,socket-id=1" 1823 " -numa cpu,node-id=1,socket-id=1" 1824 " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," 1825 "data-type=access-latency,latency=10" 1826 " -numa hmat-lb,initiator=0,target=0,hierarchy=memory," 1827 "data-type=access-bandwidth,bandwidth=10485760" 1828 " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," 1829 "data-type=access-latency,latency=20" 1830 " -numa hmat-lb,initiator=0,target=1,hierarchy=memory," 1831 "data-type=access-bandwidth,bandwidth=5242880" 1832 " -numa hmat-lb,initiator=0,target=2,hierarchy=memory," 1833 "data-type=access-latency,latency=30" 1834 " -numa hmat-lb,initiator=0,target=2,hierarchy=memory," 1835 "data-type=access-bandwidth,bandwidth=1048576" 1836 " -numa hmat-lb,initiator=1,target=0,hierarchy=memory," 1837 "data-type=access-latency,latency=20" 1838 " -numa hmat-lb,initiator=1,target=0,hierarchy=memory," 1839 "data-type=access-bandwidth,bandwidth=5242880" 1840 " -numa hmat-lb,initiator=1,target=1,hierarchy=memory," 1841 "data-type=access-latency,latency=10" 1842 " -numa hmat-lb,initiator=1,target=1,hierarchy=memory," 1843 "data-type=access-bandwidth,bandwidth=10485760" 1844 " -numa hmat-lb,initiator=1,target=2,hierarchy=memory," 1845 "data-type=access-latency,latency=30" 1846 " -numa hmat-lb,initiator=1,target=2,hierarchy=memory," 1847 "data-type=access-bandwidth,bandwidth=1048576", 1848 &data); 1849 free_test_data(&data); 1850 } 1851 1852 #ifdef CONFIG_POSIX 1853 static void test_acpi_erst(const char *machine) 1854 { 1855 gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL); 1856 gchar *params; 1857 test_data data = {}; 1858 1859 data.machine = machine; 1860 data.variant = ".acpierst"; 1861 params = g_strdup_printf( 1862 " -object memory-backend-file,id=erstnvram," 1863 "mem-path=%s,size=0x10000,share=on" 1864 " -device acpi-erst,memdev=erstnvram", tmp_path); 1865 test_acpi_one(params, &data); 1866 free_test_data(&data); 1867 g_free(params); 1868 g_assert(g_rmdir(tmp_path) == 0); 1869 g_free(tmp_path); 1870 } 1871 1872 static void test_acpi_piix4_acpi_erst(void) 1873 { 1874 test_acpi_erst(MACHINE_PC); 1875 } 1876 1877 static void test_acpi_q35_acpi_erst(void) 1878 { 1879 test_acpi_erst(MACHINE_Q35); 1880 } 1881 1882 static void test_acpi_microvm_acpi_erst(void) 1883 { 1884 gchar *tmp_path = g_dir_make_tmp("qemu-test-erst.XXXXXX", NULL); 1885 gchar *params; 1886 test_data data = {}; 1887 1888 test_acpi_microvm_prepare(&data); 1889 data.variant = ".pcie"; 1890 data.tcg_only = true; /* need constant host-phys-bits */ 1891 params = g_strdup_printf(" -machine microvm," 1892 "acpi=on,ioapic2=off,rtc=off,pcie=on" 1893 " -object memory-backend-file,id=erstnvram," 1894 "mem-path=%s,size=0x10000,share=on" 1895 " -device acpi-erst,memdev=erstnvram", tmp_path); 1896 test_acpi_one(params, &data); 1897 g_free(params); 1898 g_assert(g_rmdir(tmp_path) == 0); 1899 g_free(tmp_path); 1900 free_test_data(&data); 1901 } 1902 #endif /* CONFIG_POSIX */ 1903 1904 static void test_acpi_virt_tcg(void) 1905 { 1906 test_data data = { 1907 .machine = "virt", 1908 .tcg_only = true, 1909 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 1910 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 1911 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 1912 .ram_start = 0x40000000ULL, 1913 .scan_len = 128ULL * 1024 * 1024, 1914 }; 1915 1916 data.smbios_cpu_max_speed = 2900; 1917 data.smbios_cpu_curr_speed = 2700; 1918 test_acpi_one("-cpu cortex-a57 " 1919 "-smbios type=4,max-speed=2900,current-speed=2700", &data); 1920 free_test_data(&data); 1921 } 1922 1923 static void test_acpi_virt_tcg_topology(void) 1924 { 1925 test_data data = { 1926 .machine = "virt", 1927 .variant = ".topology", 1928 .tcg_only = true, 1929 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 1930 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 1931 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 1932 .ram_start = 0x40000000ULL, 1933 .scan_len = 128ULL * 1024 * 1024, 1934 }; 1935 1936 test_acpi_one("-cpu cortex-a57 " 1937 "-smp sockets=1,clusters=2,cores=2,threads=2", &data); 1938 free_test_data(&data); 1939 } 1940 1941 static void test_acpi_q35_viot(void) 1942 { 1943 test_data data = { 1944 .machine = MACHINE_Q35, 1945 .variant = ".viot", 1946 }; 1947 1948 /* 1949 * To keep things interesting, two buses bypass the IOMMU. 1950 * VIOT should only describes the other two buses. 1951 */ 1952 test_acpi_one("-machine default_bus_bypass_iommu=on " 1953 "-device virtio-iommu-pci " 1954 "-device pxb-pcie,bus_nr=0x10,id=pcie.100,bus=pcie.0 " 1955 "-device pxb-pcie,bus_nr=0x20,id=pcie.200,bus=pcie.0,bypass_iommu=on " 1956 "-device pxb-pcie,bus_nr=0x30,id=pcie.300,bus=pcie.0", 1957 &data); 1958 free_test_data(&data); 1959 } 1960 1961 #ifdef CONFIG_POSIX 1962 static void test_acpi_q35_cxl(void) 1963 { 1964 gchar *tmp_path = g_dir_make_tmp("qemu-test-cxl.XXXXXX", NULL); 1965 gchar *params; 1966 1967 test_data data = { 1968 .machine = MACHINE_Q35, 1969 .variant = ".cxl", 1970 }; 1971 /* 1972 * A complex CXL setup. 1973 */ 1974 params = g_strdup_printf(" -machine cxl=on" 1975 " -object memory-backend-file,id=cxl-mem1,mem-path=%s,size=256M" 1976 " -object memory-backend-file,id=cxl-mem2,mem-path=%s,size=256M" 1977 " -object memory-backend-file,id=cxl-mem3,mem-path=%s,size=256M" 1978 " -object memory-backend-file,id=cxl-mem4,mem-path=%s,size=256M" 1979 " -object memory-backend-file,id=lsa1,mem-path=%s,size=256M" 1980 " -object memory-backend-file,id=lsa2,mem-path=%s,size=256M" 1981 " -object memory-backend-file,id=lsa3,mem-path=%s,size=256M" 1982 " -object memory-backend-file,id=lsa4,mem-path=%s,size=256M" 1983 " -device pxb-cxl,bus_nr=12,bus=pcie.0,id=cxl.1" 1984 " -device pxb-cxl,bus_nr=222,bus=pcie.0,id=cxl.2" 1985 " -device cxl-rp,port=0,bus=cxl.1,id=rp1,chassis=0,slot=2" 1986 " -device cxl-type3,bus=rp1,persistent-memdev=cxl-mem1,lsa=lsa1" 1987 " -device cxl-rp,port=1,bus=cxl.1,id=rp2,chassis=0,slot=3" 1988 " -device cxl-type3,bus=rp2,persistent-memdev=cxl-mem2,lsa=lsa2" 1989 " -device cxl-rp,port=0,bus=cxl.2,id=rp3,chassis=0,slot=5" 1990 " -device cxl-type3,bus=rp3,persistent-memdev=cxl-mem3,lsa=lsa3" 1991 " -device cxl-rp,port=1,bus=cxl.2,id=rp4,chassis=0,slot=6" 1992 " -device cxl-type3,bus=rp4,persistent-memdev=cxl-mem4,lsa=lsa4" 1993 " -M cxl-fmw.0.targets.0=cxl.1,cxl-fmw.0.size=4G,cxl-fmw.0.interleave-granularity=8k," 1994 "cxl-fmw.1.targets.0=cxl.1,cxl-fmw.1.targets.1=cxl.2,cxl-fmw.1.size=4G,cxl-fmw.1.interleave-granularity=8k", 1995 tmp_path, tmp_path, tmp_path, tmp_path, 1996 tmp_path, tmp_path, tmp_path, tmp_path); 1997 test_acpi_one(params, &data); 1998 1999 g_free(params); 2000 g_assert(g_rmdir(tmp_path) == 0); 2001 g_free(tmp_path); 2002 free_test_data(&data); 2003 } 2004 #endif /* CONFIG_POSIX */ 2005 2006 static void test_acpi_virt_viot(void) 2007 { 2008 test_data data = { 2009 .machine = "virt", 2010 .tcg_only = true, 2011 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 2012 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 2013 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 2014 .ram_start = 0x40000000ULL, 2015 .scan_len = 128ULL * 1024 * 1024, 2016 }; 2017 2018 test_acpi_one("-cpu cortex-a57 " 2019 "-device virtio-iommu-pci", &data); 2020 free_test_data(&data); 2021 } 2022 2023 #ifndef _WIN32 2024 # define DEV_NULL "/dev/null" 2025 #else 2026 # define DEV_NULL "nul" 2027 #endif 2028 2029 static void test_acpi_q35_slic(void) 2030 { 2031 test_data data = { 2032 .machine = MACHINE_Q35, 2033 .variant = ".slic", 2034 }; 2035 2036 test_acpi_one("-acpitable sig=SLIC,oem_id=\"CRASH \",oem_table_id=ME," 2037 "oem_rev=00002210,asl_compiler_id=qemu," 2038 "asl_compiler_rev=00000000,data=" DEV_NULL, 2039 &data); 2040 free_test_data(&data); 2041 } 2042 2043 static void test_acpi_q35_applesmc(void) 2044 { 2045 test_data data = { 2046 .machine = MACHINE_Q35, 2047 .variant = ".applesmc", 2048 }; 2049 2050 /* supply fake 64-byte OSK to silence missing key warning */ 2051 test_acpi_one("-device isa-applesmc,osk=any64characterfakeoskisenough" 2052 "topreventinvalidkeywarningsonstderr", &data); 2053 free_test_data(&data); 2054 } 2055 2056 static void test_acpi_q35_pvpanic_isa(void) 2057 { 2058 test_data data = { 2059 .machine = MACHINE_Q35, 2060 .variant = ".pvpanic-isa", 2061 }; 2062 2063 test_acpi_one("-device pvpanic", &data); 2064 free_test_data(&data); 2065 } 2066 2067 static void test_oem_fields(test_data *data) 2068 { 2069 int i; 2070 2071 for (i = 0; i < data->tables->len; ++i) { 2072 AcpiSdtTable *sdt; 2073 2074 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 2075 /* FACS doesn't have OEMID and OEMTABLEID fields */ 2076 if (compare_signature(sdt, "FACS")) { 2077 continue; 2078 } 2079 2080 g_assert(strncmp((char *)sdt->aml + 10, OEM_ID, 6) == 0); 2081 g_assert(strncmp((char *)sdt->aml + 16, OEM_TABLE_ID, 8) == 0); 2082 } 2083 } 2084 2085 static void test_acpi_piix4_oem_fields(void) 2086 { 2087 char *args; 2088 test_data data = {}; 2089 2090 data.machine = MACHINE_PC; 2091 data.required_struct_types = base_required_struct_types; 2092 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 2093 2094 args = test_acpi_create_args(&data, OEM_TEST_ARGS); 2095 data.qts = qtest_init(args); 2096 test_acpi_load_tables(&data); 2097 test_oem_fields(&data); 2098 qtest_quit(data.qts); 2099 free_test_data(&data); 2100 g_free(args); 2101 } 2102 2103 static void test_acpi_q35_oem_fields(void) 2104 { 2105 char *args; 2106 test_data data = {}; 2107 2108 data.machine = MACHINE_Q35; 2109 data.required_struct_types = base_required_struct_types; 2110 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 2111 2112 args = test_acpi_create_args(&data, OEM_TEST_ARGS); 2113 data.qts = qtest_init(args); 2114 test_acpi_load_tables(&data); 2115 test_oem_fields(&data); 2116 qtest_quit(data.qts); 2117 free_test_data(&data); 2118 g_free(args); 2119 } 2120 2121 static void test_acpi_microvm_oem_fields(void) 2122 { 2123 test_data data = {}; 2124 char *args; 2125 2126 test_acpi_microvm_prepare(&data); 2127 2128 args = test_acpi_create_args(&data, 2129 OEM_TEST_ARGS",acpi=on"); 2130 data.qts = qtest_init(args); 2131 test_acpi_load_tables(&data); 2132 test_oem_fields(&data); 2133 qtest_quit(data.qts); 2134 free_test_data(&data); 2135 g_free(args); 2136 } 2137 2138 static void test_acpi_virt_oem_fields(void) 2139 { 2140 test_data data = { 2141 .machine = "virt", 2142 .tcg_only = true, 2143 .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd", 2144 .uefi_fl2 = "pc-bios/edk2-arm-vars.fd", 2145 .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2", 2146 .ram_start = 0x40000000ULL, 2147 .scan_len = 128ULL * 1024 * 1024, 2148 }; 2149 char *args; 2150 2151 args = test_acpi_create_args(&data, "-cpu cortex-a57 "OEM_TEST_ARGS); 2152 data.qts = qtest_init(args); 2153 test_acpi_load_tables(&data); 2154 test_oem_fields(&data); 2155 qtest_quit(data.qts); 2156 free_test_data(&data); 2157 g_free(args); 2158 } 2159 2160 2161 int main(int argc, char *argv[]) 2162 { 2163 const char *arch = qtest_get_arch(); 2164 bool has_kvm, has_tcg; 2165 char *v_env = getenv("V"); 2166 int ret; 2167 2168 if (v_env) { 2169 verbosity_level = atoi(v_env); 2170 } 2171 2172 g_test_init(&argc, &argv, NULL); 2173 2174 has_kvm = qtest_has_accel("kvm"); 2175 has_tcg = qtest_has_accel("tcg"); 2176 2177 if (!has_tcg && !has_kvm) { 2178 g_test_skip("No KVM or TCG accelerator available"); 2179 return 0; 2180 } 2181 2182 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 2183 ret = boot_sector_init(disk); 2184 if (ret) { 2185 return ret; 2186 } 2187 if (qtest_has_machine(MACHINE_PC)) { 2188 qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); 2189 qtest_add_func("acpi/piix4/oem-fields", test_acpi_piix4_oem_fields); 2190 qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); 2191 qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug", 2192 test_acpi_piix4_no_root_hotplug); 2193 qtest_add_func("acpi/piix4/pci-hotplug/no_bridge_hotplug", 2194 test_acpi_piix4_no_bridge_hotplug); 2195 qtest_add_func("acpi/piix4/pci-hotplug/off", 2196 test_acpi_piix4_no_acpi_pci_hotplug); 2197 qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi); 2198 qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp); 2199 qtest_add_func("acpi/piix4/numamem", test_acpi_piix4_tcg_numamem); 2200 qtest_add_func("acpi/piix4/nosmm", test_acpi_piix4_tcg_nosmm); 2201 qtest_add_func("acpi/piix4/smm-compat", 2202 test_acpi_piix4_tcg_smm_compat); 2203 qtest_add_func("acpi/piix4/smm-compat-nosmm", 2204 test_acpi_piix4_tcg_smm_compat_nosmm); 2205 qtest_add_func("acpi/piix4/nohpet", test_acpi_piix4_tcg_nohpet); 2206 2207 /* i386 does not support memory hotplug */ 2208 if (strcmp(arch, "i386")) { 2209 qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp); 2210 qtest_add_func("acpi/piix4/dimmpxm", 2211 test_acpi_piix4_tcg_dimm_pxm); 2212 qtest_add_func("acpi/piix4/acpihmat", 2213 test_acpi_piix4_tcg_acpi_hmat); 2214 } 2215 #ifdef CONFIG_POSIX 2216 qtest_add_func("acpi/piix4/acpierst", test_acpi_piix4_acpi_erst); 2217 #endif 2218 } 2219 if (qtest_has_machine(MACHINE_Q35)) { 2220 qtest_add_func("acpi/q35", test_acpi_q35_tcg); 2221 qtest_add_func("acpi/q35/oem-fields", test_acpi_q35_oem_fields); 2222 if (tpm_model_is_available("-machine q35", "tpm-tis")) { 2223 qtest_add_func("acpi/q35/tpm2-tis", test_acpi_q35_tcg_tpm2_tis); 2224 qtest_add_func("acpi/q35/tpm12-tis", 2225 test_acpi_q35_tcg_tpm12_tis); 2226 } 2227 qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); 2228 qtest_add_func("acpi/q35/no-acpi-hotplug", 2229 test_acpi_q35_tcg_no_acpi_hotplug); 2230 qtest_add_func("acpi/q35/multif-bridge", 2231 test_acpi_q35_multif_bridge); 2232 qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); 2233 qtest_add_func("acpi/q35/smbus/ipmi", test_acpi_q35_tcg_smbus_ipmi); 2234 qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); 2235 qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem); 2236 qtest_add_func("acpi/q35/nosmm", test_acpi_q35_tcg_nosmm); 2237 qtest_add_func("acpi/q35/smm-compat", 2238 test_acpi_q35_tcg_smm_compat); 2239 qtest_add_func("acpi/q35/smm-compat-nosmm", 2240 test_acpi_q35_tcg_smm_compat_nosmm); 2241 qtest_add_func("acpi/q35/nohpet", test_acpi_q35_tcg_nohpet); 2242 qtest_add_func("acpi/q35/acpihmat-noinitiator", 2243 test_acpi_q35_tcg_acpi_hmat_noinitiator); 2244 2245 /* i386 does not support memory hotplug */ 2246 if (strcmp(arch, "i386")) { 2247 qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp); 2248 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm); 2249 qtest_add_func("acpi/q35/acpihmat", 2250 test_acpi_q35_tcg_acpi_hmat); 2251 qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64); 2252 } 2253 #ifdef CONFIG_POSIX 2254 qtest_add_func("acpi/q35/acpierst", test_acpi_q35_acpi_erst); 2255 #endif 2256 qtest_add_func("acpi/q35/applesmc", test_acpi_q35_applesmc); 2257 qtest_add_func("acpi/q35/pvpanic-isa", test_acpi_q35_pvpanic_isa); 2258 if (has_tcg) { 2259 qtest_add_func("acpi/q35/ivrs", test_acpi_q35_tcg_ivrs); 2260 } 2261 if (has_kvm) { 2262 qtest_add_func("acpi/q35/kvm/xapic", test_acpi_q35_kvm_xapic); 2263 qtest_add_func("acpi/q35/kvm/dmar", test_acpi_q35_kvm_dmar); 2264 qtest_add_func("acpi/q35/type4-count", 2265 test_acpi_q35_tcg_type4_count); 2266 qtest_add_func("acpi/q35/core-count", 2267 test_acpi_q35_tcg_core_count); 2268 qtest_add_func("acpi/q35/core-count2", 2269 test_acpi_q35_tcg_core_count2); 2270 qtest_add_func("acpi/q35/thread-count", 2271 test_acpi_q35_tcg_thread_count); 2272 qtest_add_func("acpi/q35/thread-count2", 2273 test_acpi_q35_tcg_thread_count2); 2274 } 2275 if (qtest_has_device("virtio-iommu-pci")) { 2276 qtest_add_func("acpi/q35/viot", test_acpi_q35_viot); 2277 } 2278 #ifdef CONFIG_POSIX 2279 qtest_add_func("acpi/q35/cxl", test_acpi_q35_cxl); 2280 #endif 2281 qtest_add_func("acpi/q35/slic", test_acpi_q35_slic); 2282 } 2283 if (qtest_has_machine("microvm")) { 2284 qtest_add_func("acpi/microvm", test_acpi_microvm_tcg); 2285 qtest_add_func("acpi/microvm/usb", test_acpi_microvm_usb_tcg); 2286 qtest_add_func("acpi/microvm/rtc", test_acpi_microvm_rtc_tcg); 2287 qtest_add_func("acpi/microvm/ioapic2", 2288 test_acpi_microvm_ioapic2_tcg); 2289 qtest_add_func("acpi/microvm/oem-fields", 2290 test_acpi_microvm_oem_fields); 2291 if (has_tcg) { 2292 if (strcmp(arch, "x86_64") == 0) { 2293 qtest_add_func("acpi/microvm/pcie", 2294 test_acpi_microvm_pcie_tcg); 2295 #ifdef CONFIG_POSIX 2296 qtest_add_func("acpi/microvm/acpierst", 2297 test_acpi_microvm_acpi_erst); 2298 #endif 2299 } 2300 } 2301 } 2302 } else if (strcmp(arch, "aarch64") == 0) { 2303 if (has_tcg && qtest_has_device("virtio-blk-pci")) { 2304 qtest_add_func("acpi/virt", test_acpi_virt_tcg); 2305 qtest_add_func("acpi/virt/acpihmatvirt", 2306 test_acpi_virt_tcg_acpi_hmat); 2307 qtest_add_func("acpi/virt/topology", test_acpi_virt_tcg_topology); 2308 qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem); 2309 qtest_add_func("acpi/virt/memhp", test_acpi_virt_tcg_memhp); 2310 qtest_add_func("acpi/virt/pxb", test_acpi_virt_tcg_pxb); 2311 qtest_add_func("acpi/virt/oem-fields", test_acpi_virt_oem_fields); 2312 if (qtest_has_device("virtio-iommu-pci")) { 2313 qtest_add_func("acpi/virt/viot", test_acpi_virt_viot); 2314 } 2315 } 2316 } 2317 ret = g_test_run(); 2318 boot_sector_cleanup(disk); 2319 return ret; 2320 } 2321