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 #include "qemu/osdep.h" 14 #include <glib/gstdio.h> 15 #include "qemu-common.h" 16 #include "hw/smbios/smbios.h" 17 #include "qemu/bitmap.h" 18 #include "acpi-utils.h" 19 #include "boot-sector.h" 20 21 #define MACHINE_PC "pc" 22 #define MACHINE_Q35 "q35" 23 24 #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML" 25 26 typedef struct { 27 const char *machine; 28 const char *variant; 29 uint32_t rsdp_addr; 30 AcpiRsdpDescriptor rsdp_table; 31 AcpiRsdtDescriptorRev1 rsdt_table; 32 AcpiFadtDescriptorRev1 fadt_table; 33 AcpiFacsDescriptorRev1 facs_table; 34 uint32_t *rsdt_tables_addr; 35 int rsdt_tables_nr; 36 GArray *tables; 37 uint32_t smbios_ep_addr; 38 struct smbios_21_entry_point smbios_ep_table; 39 uint8_t *required_struct_types; 40 int required_struct_types_len; 41 } test_data; 42 43 static char disk[] = "tests/acpi-test-disk-XXXXXX"; 44 static const char *data_dir = "tests/acpi-test-data"; 45 #ifdef CONFIG_IASL 46 static const char *iasl = stringify(CONFIG_IASL); 47 #else 48 static const char *iasl; 49 #endif 50 51 static void free_test_data(test_data *data) 52 { 53 AcpiSdtTable *temp; 54 int i; 55 56 g_free(data->rsdt_tables_addr); 57 58 for (i = 0; i < data->tables->len; ++i) { 59 temp = &g_array_index(data->tables, AcpiSdtTable, i); 60 g_free(temp->aml); 61 if (temp->aml_file && 62 !temp->tmp_files_retain && 63 g_strstr_len(temp->aml_file, -1, "aml-")) { 64 unlink(temp->aml_file); 65 } 66 g_free(temp->aml_file); 67 g_free(temp->asl); 68 if (temp->asl_file && 69 !temp->tmp_files_retain) { 70 unlink(temp->asl_file); 71 } 72 g_free(temp->asl_file); 73 } 74 75 g_array_free(data->tables, false); 76 } 77 78 static void test_acpi_rsdp_address(test_data *data) 79 { 80 uint32_t off = acpi_find_rsdp_address(); 81 g_assert_cmphex(off, <, 0x100000); 82 data->rsdp_addr = off; 83 } 84 85 static void test_acpi_rsdp_table(test_data *data) 86 { 87 AcpiRsdpDescriptor *rsdp_table = &data->rsdp_table; 88 uint32_t addr = data->rsdp_addr; 89 90 acpi_parse_rsdp_table(addr, rsdp_table); 91 92 /* rsdp checksum is not for the whole table, but for the first 20 bytes */ 93 g_assert(!acpi_calc_checksum((uint8_t *)rsdp_table, 20)); 94 } 95 96 static void test_acpi_rsdt_table(test_data *data) 97 { 98 AcpiRsdtDescriptorRev1 *rsdt_table = &data->rsdt_table; 99 uint32_t addr = data->rsdp_table.rsdt_physical_address; 100 uint32_t *tables; 101 int tables_nr; 102 uint8_t checksum; 103 104 /* read the header */ 105 ACPI_READ_TABLE_HEADER(rsdt_table, addr); 106 ACPI_ASSERT_CMP(rsdt_table->signature, "RSDT"); 107 108 /* compute the table entries in rsdt */ 109 tables_nr = (rsdt_table->length - sizeof(AcpiRsdtDescriptorRev1)) / 110 sizeof(uint32_t); 111 g_assert_cmpint(tables_nr, >, 0); 112 113 /* get the addresses of the tables pointed by rsdt */ 114 tables = g_new0(uint32_t, tables_nr); 115 ACPI_READ_ARRAY_PTR(tables, tables_nr, addr); 116 117 checksum = acpi_calc_checksum((uint8_t *)rsdt_table, rsdt_table->length) + 118 acpi_calc_checksum((uint8_t *)tables, 119 tables_nr * sizeof(uint32_t)); 120 g_assert(!checksum); 121 122 /* SSDT tables after FADT */ 123 data->rsdt_tables_addr = tables; 124 data->rsdt_tables_nr = tables_nr; 125 } 126 127 static void test_acpi_fadt_table(test_data *data) 128 { 129 AcpiFadtDescriptorRev1 *fadt_table = &data->fadt_table; 130 uint32_t addr; 131 132 /* FADT table comes first */ 133 addr = data->rsdt_tables_addr[0]; 134 ACPI_READ_TABLE_HEADER(fadt_table, addr); 135 136 ACPI_READ_FIELD(fadt_table->firmware_ctrl, addr); 137 ACPI_READ_FIELD(fadt_table->dsdt, addr); 138 ACPI_READ_FIELD(fadt_table->model, addr); 139 ACPI_READ_FIELD(fadt_table->reserved1, addr); 140 ACPI_READ_FIELD(fadt_table->sci_int, addr); 141 ACPI_READ_FIELD(fadt_table->smi_cmd, addr); 142 ACPI_READ_FIELD(fadt_table->acpi_enable, addr); 143 ACPI_READ_FIELD(fadt_table->acpi_disable, addr); 144 ACPI_READ_FIELD(fadt_table->S4bios_req, addr); 145 ACPI_READ_FIELD(fadt_table->reserved2, addr); 146 ACPI_READ_FIELD(fadt_table->pm1a_evt_blk, addr); 147 ACPI_READ_FIELD(fadt_table->pm1b_evt_blk, addr); 148 ACPI_READ_FIELD(fadt_table->pm1a_cnt_blk, addr); 149 ACPI_READ_FIELD(fadt_table->pm1b_cnt_blk, addr); 150 ACPI_READ_FIELD(fadt_table->pm2_cnt_blk, addr); 151 ACPI_READ_FIELD(fadt_table->pm_tmr_blk, addr); 152 ACPI_READ_FIELD(fadt_table->gpe0_blk, addr); 153 ACPI_READ_FIELD(fadt_table->gpe1_blk, addr); 154 ACPI_READ_FIELD(fadt_table->pm1_evt_len, addr); 155 ACPI_READ_FIELD(fadt_table->pm1_cnt_len, addr); 156 ACPI_READ_FIELD(fadt_table->pm2_cnt_len, addr); 157 ACPI_READ_FIELD(fadt_table->pm_tmr_len, addr); 158 ACPI_READ_FIELD(fadt_table->gpe0_blk_len, addr); 159 ACPI_READ_FIELD(fadt_table->gpe1_blk_len, addr); 160 ACPI_READ_FIELD(fadt_table->gpe1_base, addr); 161 ACPI_READ_FIELD(fadt_table->reserved3, addr); 162 ACPI_READ_FIELD(fadt_table->plvl2_lat, addr); 163 ACPI_READ_FIELD(fadt_table->plvl3_lat, addr); 164 ACPI_READ_FIELD(fadt_table->flush_size, addr); 165 ACPI_READ_FIELD(fadt_table->flush_stride, addr); 166 ACPI_READ_FIELD(fadt_table->duty_offset, addr); 167 ACPI_READ_FIELD(fadt_table->duty_width, addr); 168 ACPI_READ_FIELD(fadt_table->day_alrm, addr); 169 ACPI_READ_FIELD(fadt_table->mon_alrm, addr); 170 ACPI_READ_FIELD(fadt_table->century, addr); 171 ACPI_READ_FIELD(fadt_table->reserved4, addr); 172 ACPI_READ_FIELD(fadt_table->reserved4a, addr); 173 ACPI_READ_FIELD(fadt_table->reserved4b, addr); 174 ACPI_READ_FIELD(fadt_table->flags, addr); 175 176 ACPI_ASSERT_CMP(fadt_table->signature, "FACP"); 177 g_assert(!acpi_calc_checksum((uint8_t *)fadt_table, fadt_table->length)); 178 } 179 180 static void test_acpi_facs_table(test_data *data) 181 { 182 AcpiFacsDescriptorRev1 *facs_table = &data->facs_table; 183 uint32_t addr = data->fadt_table.firmware_ctrl; 184 185 ACPI_READ_FIELD(facs_table->signature, addr); 186 ACPI_READ_FIELD(facs_table->length, addr); 187 ACPI_READ_FIELD(facs_table->hardware_signature, addr); 188 ACPI_READ_FIELD(facs_table->firmware_waking_vector, addr); 189 ACPI_READ_FIELD(facs_table->global_lock, addr); 190 ACPI_READ_FIELD(facs_table->flags, addr); 191 ACPI_READ_ARRAY(facs_table->resverved3, addr); 192 193 ACPI_ASSERT_CMP(facs_table->signature, "FACS"); 194 } 195 196 static void test_dst_table(AcpiSdtTable *sdt_table, uint32_t addr) 197 { 198 uint8_t checksum; 199 200 ACPI_READ_TABLE_HEADER(&sdt_table->header, addr); 201 202 sdt_table->aml_len = sdt_table->header.length - sizeof(AcpiTableHeader); 203 sdt_table->aml = g_malloc0(sdt_table->aml_len); 204 ACPI_READ_ARRAY_PTR(sdt_table->aml, sdt_table->aml_len, addr); 205 206 checksum = acpi_calc_checksum((uint8_t *)sdt_table, 207 sizeof(AcpiTableHeader)) + 208 acpi_calc_checksum((uint8_t *)sdt_table->aml, 209 sdt_table->aml_len); 210 g_assert(!checksum); 211 } 212 213 static void test_acpi_dsdt_table(test_data *data) 214 { 215 AcpiSdtTable dsdt_table; 216 uint32_t addr = data->fadt_table.dsdt; 217 218 memset(&dsdt_table, 0, sizeof(dsdt_table)); 219 data->tables = g_array_new(false, true, sizeof(AcpiSdtTable)); 220 221 test_dst_table(&dsdt_table, addr); 222 ACPI_ASSERT_CMP(dsdt_table.header.signature, "DSDT"); 223 224 /* Place DSDT first */ 225 g_array_append_val(data->tables, dsdt_table); 226 } 227 228 static void test_acpi_tables(test_data *data) 229 { 230 int tables_nr = data->rsdt_tables_nr - 1; /* fadt is first */ 231 int i; 232 233 for (i = 0; i < tables_nr; i++) { 234 AcpiSdtTable ssdt_table; 235 236 memset(&ssdt_table, 0, sizeof(ssdt_table)); 237 uint32_t addr = data->rsdt_tables_addr[i + 1]; /* fadt is first */ 238 test_dst_table(&ssdt_table, addr); 239 g_array_append_val(data->tables, ssdt_table); 240 } 241 } 242 243 static void dump_aml_files(test_data *data, bool rebuild) 244 { 245 AcpiSdtTable *sdt; 246 GError *error = NULL; 247 gchar *aml_file = NULL; 248 gint fd; 249 ssize_t ret; 250 int i; 251 252 for (i = 0; i < data->tables->len; ++i) { 253 const char *ext = data->variant ? data->variant : ""; 254 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 255 g_assert(sdt->aml); 256 257 if (rebuild) { 258 uint32_t signature = cpu_to_le32(sdt->header.signature); 259 aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, 260 (gchar *)&signature, ext); 261 fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT, 262 S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH); 263 } else { 264 fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error); 265 g_assert_no_error(error); 266 } 267 g_assert(fd >= 0); 268 269 ret = qemu_write_full(fd, sdt, sizeof(AcpiTableHeader)); 270 g_assert(ret == sizeof(AcpiTableHeader)); 271 ret = qemu_write_full(fd, sdt->aml, sdt->aml_len); 272 g_assert(ret == sdt->aml_len); 273 274 close(fd); 275 276 g_free(aml_file); 277 } 278 } 279 280 static bool compare_signature(AcpiSdtTable *sdt, const char *signature) 281 { 282 return !memcmp(&sdt->header.signature, signature, 4); 283 } 284 285 static bool load_asl(GArray *sdts, AcpiSdtTable *sdt) 286 { 287 AcpiSdtTable *temp; 288 GError *error = NULL; 289 GString *command_line = g_string_new(iasl); 290 gint fd; 291 gchar *out, *out_err; 292 gboolean ret; 293 int i; 294 295 fd = g_file_open_tmp("asl-XXXXXX.dsl", &sdt->asl_file, &error); 296 g_assert_no_error(error); 297 close(fd); 298 299 /* build command line */ 300 g_string_append_printf(command_line, " -p %s ", sdt->asl_file); 301 if (compare_signature(sdt, "DSDT") || 302 compare_signature(sdt, "SSDT")) { 303 for (i = 0; i < sdts->len; ++i) { 304 temp = &g_array_index(sdts, AcpiSdtTable, i); 305 if (compare_signature(temp, "DSDT") || 306 compare_signature(temp, "SSDT")) { 307 g_string_append_printf(command_line, "-e %s ", temp->aml_file); 308 } 309 } 310 } 311 g_string_append_printf(command_line, "-d %s", sdt->aml_file); 312 313 /* pass 'out' and 'out_err' in order to be redirected */ 314 ret = g_spawn_command_line_sync(command_line->str, &out, &out_err, NULL, &error); 315 g_assert_no_error(error); 316 if (ret) { 317 ret = g_file_get_contents(sdt->asl_file, (gchar **)&sdt->asl, 318 &sdt->asl_len, &error); 319 g_assert(ret); 320 g_assert_no_error(error); 321 ret = (sdt->asl_len > 0); 322 } 323 324 g_free(out); 325 g_free(out_err); 326 g_string_free(command_line, true); 327 328 return !ret; 329 } 330 331 #define COMMENT_END "*/" 332 #define DEF_BLOCK "DefinitionBlock (" 333 #define BLOCK_NAME_END "," 334 335 static GString *normalize_asl(gchar *asl_code) 336 { 337 GString *asl = g_string_new(asl_code); 338 gchar *comment, *block_name; 339 340 /* strip comments (different generation days) */ 341 comment = g_strstr_len(asl->str, asl->len, COMMENT_END); 342 if (comment) { 343 comment += strlen(COMMENT_END); 344 while (*comment == '\n') { 345 comment++; 346 } 347 asl = g_string_erase(asl, 0, comment - asl->str); 348 } 349 350 /* strip def block name (it has file path in it) */ 351 if (g_str_has_prefix(asl->str, DEF_BLOCK)) { 352 block_name = g_strstr_len(asl->str, asl->len, BLOCK_NAME_END); 353 g_assert(block_name); 354 asl = g_string_erase(asl, 0, 355 block_name + sizeof(BLOCK_NAME_END) - asl->str); 356 } 357 358 return asl; 359 } 360 361 static GArray *load_expected_aml(test_data *data) 362 { 363 int i; 364 AcpiSdtTable *sdt; 365 GError *error = NULL; 366 gboolean ret; 367 368 GArray *exp_tables = g_array_new(false, true, sizeof(AcpiSdtTable)); 369 for (i = 0; i < data->tables->len; ++i) { 370 AcpiSdtTable exp_sdt; 371 uint32_t signature; 372 gchar *aml_file = NULL; 373 const char *ext = data->variant ? data->variant : ""; 374 375 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 376 377 memset(&exp_sdt, 0, sizeof(exp_sdt)); 378 exp_sdt.header.signature = sdt->header.signature; 379 380 signature = cpu_to_le32(sdt->header.signature); 381 382 try_again: 383 aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, data->machine, 384 (gchar *)&signature, ext); 385 if (getenv("V")) { 386 fprintf(stderr, "\nLooking for expected file '%s'\n", aml_file); 387 } 388 if (g_file_test(aml_file, G_FILE_TEST_EXISTS)) { 389 exp_sdt.aml_file = aml_file; 390 } else if (*ext != '\0') { 391 /* try fallback to generic (extention less) expected file */ 392 ext = ""; 393 g_free(aml_file); 394 goto try_again; 395 } 396 g_assert(exp_sdt.aml_file); 397 if (getenv("V")) { 398 fprintf(stderr, "\nUsing expected file '%s'\n", aml_file); 399 } 400 ret = g_file_get_contents(aml_file, &exp_sdt.aml, 401 &exp_sdt.aml_len, &error); 402 g_assert(ret); 403 g_assert_no_error(error); 404 g_assert(exp_sdt.aml); 405 g_assert(exp_sdt.aml_len); 406 407 g_array_append_val(exp_tables, exp_sdt); 408 } 409 410 return exp_tables; 411 } 412 413 static void test_acpi_asl(test_data *data) 414 { 415 int i; 416 AcpiSdtTable *sdt, *exp_sdt; 417 test_data exp_data; 418 gboolean exp_err, err; 419 420 memset(&exp_data, 0, sizeof(exp_data)); 421 exp_data.tables = load_expected_aml(data); 422 dump_aml_files(data, false); 423 for (i = 0; i < data->tables->len; ++i) { 424 GString *asl, *exp_asl; 425 426 sdt = &g_array_index(data->tables, AcpiSdtTable, i); 427 exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i); 428 429 err = load_asl(data->tables, sdt); 430 asl = normalize_asl(sdt->asl); 431 432 exp_err = load_asl(exp_data.tables, exp_sdt); 433 exp_asl = normalize_asl(exp_sdt->asl); 434 435 /* TODO: check for warnings */ 436 g_assert(!err || exp_err); 437 438 if (g_strcmp0(asl->str, exp_asl->str)) { 439 if (exp_err) { 440 fprintf(stderr, 441 "Warning! iasl couldn't parse the expected aml\n"); 442 } else { 443 uint32_t signature = cpu_to_le32(exp_sdt->header.signature); 444 sdt->tmp_files_retain = true; 445 exp_sdt->tmp_files_retain = true; 446 fprintf(stderr, 447 "acpi-test: Warning! %.4s mismatch. " 448 "Actual [asl:%s, aml:%s], Expected [asl:%s, aml:%s].\n", 449 (gchar *)&signature, 450 sdt->asl_file, sdt->aml_file, 451 exp_sdt->asl_file, exp_sdt->aml_file); 452 if (getenv("V")) { 453 const char *diff_cmd = getenv("DIFF"); 454 if (diff_cmd) { 455 int ret G_GNUC_UNUSED; 456 char *diff = g_strdup_printf("%s %s %s", diff_cmd, 457 exp_sdt->asl_file, sdt->asl_file); 458 ret = system(diff) ; 459 g_free(diff); 460 } else { 461 fprintf(stderr, "acpi-test: Warning. not showing " 462 "difference since no diff utility is specified. " 463 "Set 'DIFF' environment variable to a preferred " 464 "diff utility and run 'make V=1 check' again to " 465 "see ASL difference."); 466 } 467 } 468 } 469 } 470 g_string_free(asl, true); 471 g_string_free(exp_asl, true); 472 } 473 474 free_test_data(&exp_data); 475 } 476 477 static bool smbios_ep_table_ok(test_data *data) 478 { 479 struct smbios_21_entry_point *ep_table = &data->smbios_ep_table; 480 uint32_t addr = data->smbios_ep_addr; 481 482 ACPI_READ_ARRAY(ep_table->anchor_string, addr); 483 if (memcmp(ep_table->anchor_string, "_SM_", 4)) { 484 return false; 485 } 486 ACPI_READ_FIELD(ep_table->checksum, addr); 487 ACPI_READ_FIELD(ep_table->length, addr); 488 ACPI_READ_FIELD(ep_table->smbios_major_version, addr); 489 ACPI_READ_FIELD(ep_table->smbios_minor_version, addr); 490 ACPI_READ_FIELD(ep_table->max_structure_size, addr); 491 ACPI_READ_FIELD(ep_table->entry_point_revision, addr); 492 ACPI_READ_ARRAY(ep_table->formatted_area, addr); 493 ACPI_READ_ARRAY(ep_table->intermediate_anchor_string, addr); 494 if (memcmp(ep_table->intermediate_anchor_string, "_DMI_", 5)) { 495 return false; 496 } 497 ACPI_READ_FIELD(ep_table->intermediate_checksum, addr); 498 ACPI_READ_FIELD(ep_table->structure_table_length, addr); 499 if (ep_table->structure_table_length == 0) { 500 return false; 501 } 502 ACPI_READ_FIELD(ep_table->structure_table_address, addr); 503 ACPI_READ_FIELD(ep_table->number_of_structures, addr); 504 if (ep_table->number_of_structures == 0) { 505 return false; 506 } 507 ACPI_READ_FIELD(ep_table->smbios_bcd_revision, addr); 508 if (acpi_calc_checksum((uint8_t *)ep_table, sizeof *ep_table) || 509 acpi_calc_checksum((uint8_t *)ep_table + 0x10, 510 sizeof *ep_table - 0x10)) { 511 return false; 512 } 513 return true; 514 } 515 516 static void test_smbios_entry_point(test_data *data) 517 { 518 uint32_t off; 519 520 /* find smbios entry point structure */ 521 for (off = 0xf0000; off < 0x100000; off += 0x10) { 522 uint8_t sig[] = "_SM_"; 523 int i; 524 525 for (i = 0; i < sizeof sig - 1; ++i) { 526 sig[i] = readb(off + i); 527 } 528 529 if (!memcmp(sig, "_SM_", sizeof sig)) { 530 /* signature match, but is this a valid entry point? */ 531 data->smbios_ep_addr = off; 532 if (smbios_ep_table_ok(data)) { 533 break; 534 } 535 } 536 } 537 538 g_assert_cmphex(off, <, 0x100000); 539 } 540 541 static inline bool smbios_single_instance(uint8_t type) 542 { 543 switch (type) { 544 case 0: 545 case 1: 546 case 2: 547 case 3: 548 case 16: 549 case 32: 550 case 127: 551 return true; 552 default: 553 return false; 554 } 555 } 556 557 static void test_smbios_structs(test_data *data) 558 { 559 DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 }; 560 struct smbios_21_entry_point *ep_table = &data->smbios_ep_table; 561 uint32_t addr = ep_table->structure_table_address; 562 int i, len, max_len = 0; 563 uint8_t type, prv, crt; 564 565 /* walk the smbios tables */ 566 for (i = 0; i < ep_table->number_of_structures; i++) { 567 568 /* grab type and formatted area length from struct header */ 569 type = readb(addr); 570 g_assert_cmpuint(type, <=, SMBIOS_MAX_TYPE); 571 len = readb(addr + 1); 572 573 /* single-instance structs must not have been encountered before */ 574 if (smbios_single_instance(type)) { 575 g_assert(!test_bit(type, struct_bitmap)); 576 } 577 set_bit(type, struct_bitmap); 578 579 /* seek to end of unformatted string area of this struct ("\0\0") */ 580 prv = crt = 1; 581 while (prv || crt) { 582 prv = crt; 583 crt = readb(addr + len); 584 len++; 585 } 586 587 /* keep track of max. struct size */ 588 if (max_len < len) { 589 max_len = len; 590 g_assert_cmpuint(max_len, <=, ep_table->max_structure_size); 591 } 592 593 /* start of next structure */ 594 addr += len; 595 } 596 597 /* total table length and max struct size must match entry point values */ 598 g_assert_cmpuint(ep_table->structure_table_length, ==, 599 addr - ep_table->structure_table_address); 600 g_assert_cmpuint(ep_table->max_structure_size, ==, max_len); 601 602 /* required struct types must all be present */ 603 for (i = 0; i < data->required_struct_types_len; i++) { 604 g_assert(test_bit(data->required_struct_types[i], struct_bitmap)); 605 } 606 } 607 608 static void test_acpi_one(const char *params, test_data *data) 609 { 610 char *args; 611 612 /* Disable kernel irqchip to be able to override apic irq0. */ 613 args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off " 614 "-net none -display none %s " 615 "-drive id=hd0,if=none,file=%s,format=raw " 616 "-device ide-hd,drive=hd0 ", 617 data->machine, "kvm:tcg", 618 params ? params : "", disk); 619 620 qtest_start(args); 621 622 boot_sector_test(); 623 624 test_acpi_rsdp_address(data); 625 test_acpi_rsdp_table(data); 626 test_acpi_rsdt_table(data); 627 test_acpi_fadt_table(data); 628 test_acpi_facs_table(data); 629 test_acpi_dsdt_table(data); 630 test_acpi_tables(data); 631 632 if (iasl) { 633 if (getenv(ACPI_REBUILD_EXPECTED_AML)) { 634 dump_aml_files(data, true); 635 } else { 636 test_acpi_asl(data); 637 } 638 } 639 640 test_smbios_entry_point(data); 641 test_smbios_structs(data); 642 643 qtest_quit(global_qtest); 644 g_free(args); 645 } 646 647 static uint8_t base_required_struct_types[] = { 648 0, 1, 3, 4, 16, 17, 19, 32, 127 649 }; 650 651 static void test_acpi_piix4_tcg(void) 652 { 653 test_data data; 654 655 /* Supplying -machine accel argument overrides the default (qtest). 656 * This is to make guest actually run. 657 */ 658 memset(&data, 0, sizeof(data)); 659 data.machine = MACHINE_PC; 660 data.required_struct_types = base_required_struct_types; 661 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 662 test_acpi_one(NULL, &data); 663 free_test_data(&data); 664 } 665 666 static void test_acpi_piix4_tcg_bridge(void) 667 { 668 test_data data; 669 670 memset(&data, 0, sizeof(data)); 671 data.machine = MACHINE_PC; 672 data.variant = ".bridge"; 673 data.required_struct_types = base_required_struct_types; 674 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 675 test_acpi_one("-device pci-bridge,chassis_nr=1", &data); 676 free_test_data(&data); 677 } 678 679 static void test_acpi_q35_tcg(void) 680 { 681 test_data data; 682 683 memset(&data, 0, sizeof(data)); 684 data.machine = MACHINE_Q35; 685 data.required_struct_types = base_required_struct_types; 686 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 687 test_acpi_one(NULL, &data); 688 free_test_data(&data); 689 } 690 691 static void test_acpi_q35_tcg_bridge(void) 692 { 693 test_data data; 694 695 memset(&data, 0, sizeof(data)); 696 data.machine = MACHINE_Q35; 697 data.variant = ".bridge"; 698 data.required_struct_types = base_required_struct_types; 699 data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types); 700 test_acpi_one("-device pci-bridge,chassis_nr=1", 701 &data); 702 free_test_data(&data); 703 } 704 705 static void test_acpi_piix4_tcg_cphp(void) 706 { 707 test_data data; 708 709 memset(&data, 0, sizeof(data)); 710 data.machine = MACHINE_PC; 711 data.variant = ".cphp"; 712 test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6" 713 " -numa node -numa node", 714 &data); 715 free_test_data(&data); 716 } 717 718 static void test_acpi_q35_tcg_cphp(void) 719 { 720 test_data data; 721 722 memset(&data, 0, sizeof(data)); 723 data.machine = MACHINE_Q35; 724 data.variant = ".cphp"; 725 test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6" 726 " -numa node -numa node", 727 &data); 728 free_test_data(&data); 729 } 730 731 static uint8_t ipmi_required_struct_types[] = { 732 0, 1, 3, 4, 16, 17, 19, 32, 38, 127 733 }; 734 735 static void test_acpi_q35_tcg_ipmi(void) 736 { 737 test_data data; 738 739 memset(&data, 0, sizeof(data)); 740 data.machine = MACHINE_Q35; 741 data.variant = ".ipmibt"; 742 data.required_struct_types = ipmi_required_struct_types; 743 data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); 744 test_acpi_one("-device ipmi-bmc-sim,id=bmc0" 745 " -device isa-ipmi-bt,bmc=bmc0", 746 &data); 747 free_test_data(&data); 748 } 749 750 static void test_acpi_piix4_tcg_ipmi(void) 751 { 752 test_data data; 753 754 /* Supplying -machine accel argument overrides the default (qtest). 755 * This is to make guest actually run. 756 */ 757 memset(&data, 0, sizeof(data)); 758 data.machine = MACHINE_PC; 759 data.variant = ".ipmikcs"; 760 data.required_struct_types = ipmi_required_struct_types; 761 data.required_struct_types_len = ARRAY_SIZE(ipmi_required_struct_types); 762 test_acpi_one("-device ipmi-bmc-sim,id=bmc0" 763 " -device isa-ipmi-kcs,irq=0,bmc=bmc0", 764 &data); 765 free_test_data(&data); 766 } 767 768 static void test_acpi_q35_tcg_memhp(void) 769 { 770 test_data data; 771 772 memset(&data, 0, sizeof(data)); 773 data.machine = MACHINE_Q35; 774 data.variant = ".memhp"; 775 test_acpi_one(" -m 128,slots=3,maxmem=1G -numa node", &data); 776 free_test_data(&data); 777 } 778 779 static void test_acpi_piix4_tcg_memhp(void) 780 { 781 test_data data; 782 783 memset(&data, 0, sizeof(data)); 784 data.machine = MACHINE_PC; 785 data.variant = ".memhp"; 786 test_acpi_one(" -m 128,slots=3,maxmem=1G -numa node", &data); 787 free_test_data(&data); 788 } 789 790 int main(int argc, char *argv[]) 791 { 792 const char *arch = qtest_get_arch(); 793 int ret; 794 795 ret = boot_sector_init(disk); 796 if(ret) 797 return ret; 798 799 g_test_init(&argc, &argv, NULL); 800 801 if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) { 802 qtest_add_func("acpi/piix4", test_acpi_piix4_tcg); 803 qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge); 804 qtest_add_func("acpi/q35", test_acpi_q35_tcg); 805 qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge); 806 qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi); 807 qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi); 808 qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp); 809 qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp); 810 qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp); 811 qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp); 812 } 813 ret = g_test_run(); 814 boot_sector_cleanup(disk); 815 return ret; 816 } 817