2 * Boot order test cases.
4 * Copyright (c) 2013 Red Hat Inc.
7 * Michael S. Tsirkin <mst@redhat.com>,
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.
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"
21 #define MACHINE_PC "pc"
22 #define MACHINE_Q35 "q35"
24 #define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
30 AcpiRsdpDescriptor rsdp_table
;
31 AcpiRsdtDescriptorRev1 rsdt_table
;
34 AcpiFacsDescriptorRev1 facs_table
;
35 uint32_t *rsdt_tables_addr
;
38 uint32_t smbios_ep_addr
;
39 struct smbios_21_entry_point smbios_ep_table
;
40 uint8_t *required_struct_types
;
41 int required_struct_types_len
;
45 static char disk
[] = "tests/acpi-test-disk-XXXXXX";
46 static const char *data_dir
= "tests/data/acpi";
48 static const char *iasl
= stringify(CONFIG_IASL
);
50 static const char *iasl
;
53 static void free_test_data(test_data
*data
)
58 g_free(data
->rsdt_tables_addr
);
60 for (i
= 0; i
< data
->tables
->len
; ++i
) {
61 temp
= &g_array_index(data
->tables
, AcpiSdtTable
, i
);
64 !temp
->tmp_files_retain
&&
65 g_strstr_len(temp
->aml_file
, -1, "aml-")) {
66 unlink(temp
->aml_file
);
68 g_free(temp
->aml_file
);
71 !temp
->tmp_files_retain
) {
72 unlink(temp
->asl_file
);
74 g_free(temp
->asl_file
);
77 g_array_free(data
->tables
, true);
80 static void test_acpi_rsdp_address(test_data
*data
)
82 uint32_t off
= acpi_find_rsdp_address(data
->qts
);
83 g_assert_cmphex(off
, <, 0x100000);
84 data
->rsdp_addr
= off
;
87 static void test_acpi_rsdp_table(test_data
*data
)
89 AcpiRsdpDescriptor
*rsdp_table
= &data
->rsdp_table
;
90 uint32_t addr
= data
->rsdp_addr
;
92 acpi_parse_rsdp_table(data
->qts
, addr
, rsdp_table
);
94 /* rsdp checksum is not for the whole table, but for the first 20 bytes */
95 g_assert(!acpi_calc_checksum((uint8_t *)rsdp_table
, 20));
98 static void test_acpi_rsdt_table(test_data
*data
)
100 AcpiRsdtDescriptorRev1
*rsdt_table
= &data
->rsdt_table
;
101 uint32_t addr
= le32_to_cpu(data
->rsdp_table
.rsdt_physical_address
);
105 uint32_t rsdt_table_length
;
107 /* read the header */
108 ACPI_READ_TABLE_HEADER(data
->qts
, rsdt_table
, addr
);
109 ACPI_ASSERT_CMP(rsdt_table
->signature
, "RSDT");
111 rsdt_table_length
= le32_to_cpu(rsdt_table
->length
);
113 /* compute the table entries in rsdt */
114 tables_nr
= (rsdt_table_length
- sizeof(AcpiRsdtDescriptorRev1
)) /
116 g_assert(tables_nr
> 0);
118 /* get the addresses of the tables pointed by rsdt */
119 tables
= g_new0(uint32_t, tables_nr
);
120 ACPI_READ_ARRAY_PTR(data
->qts
, tables
, tables_nr
, addr
);
122 checksum
= acpi_calc_checksum((uint8_t *)rsdt_table
, rsdt_table_length
) +
123 acpi_calc_checksum((uint8_t *)tables
,
124 tables_nr
* sizeof(uint32_t));
127 /* SSDT tables after FADT */
128 data
->rsdt_tables_addr
= tables
;
129 data
->rsdt_tables_nr
= tables_nr
;
132 static void fadt_fetch_facs_and_dsdt_ptrs(test_data
*data
)
137 /* FADT table comes first */
138 addr
= le32_to_cpu(data
->rsdt_tables_addr
[0]);
139 ACPI_READ_TABLE_HEADER(data
->qts
, &hdr
, addr
);
140 ACPI_ASSERT_CMP(hdr
.signature
, "FACP");
142 ACPI_READ_FIELD(data
->qts
, data
->facs_addr
, addr
);
143 ACPI_READ_FIELD(data
->qts
, data
->dsdt_addr
, addr
);
146 static void sanitize_fadt_ptrs(test_data
*data
)
148 /* fixup pointers in FADT */
151 for (i
= 0; i
< data
->tables
->len
; i
++) {
152 AcpiSdtTable
*sdt
= &g_array_index(data
->tables
, AcpiSdtTable
, i
);
154 if (memcmp(&sdt
->header
.signature
, "FACP", 4)) {
158 /* check original FADT checksum before sanitizing table */
160 acpi_calc_checksum((uint8_t *)sdt
, sizeof(AcpiTableHeader
)) +
161 acpi_calc_checksum((uint8_t *)sdt
->aml
, sdt
->aml_len
)
164 /* sdt->aml field offset := spec offset - header size */
165 memset(sdt
->aml
+ 0, 0, 4); /* sanitize FIRMWARE_CTRL(36) ptr */
166 memset(sdt
->aml
+ 4, 0, 4); /* sanitize DSDT(40) ptr */
167 if (sdt
->header
.revision
>= 3) {
168 memset(sdt
->aml
+ 96, 0, 8); /* sanitize X_FIRMWARE_CTRL(132) ptr */
169 memset(sdt
->aml
+ 104, 0, 8); /* sanitize X_DSDT(140) ptr */
172 /* update checksum */
173 sdt
->header
.checksum
= 0;
174 sdt
->header
.checksum
-=
175 acpi_calc_checksum((uint8_t *)sdt
, sizeof(AcpiTableHeader
)) +
176 acpi_calc_checksum((uint8_t *)sdt
->aml
, sdt
->aml_len
);
181 static void test_acpi_facs_table(test_data
*data
)
183 AcpiFacsDescriptorRev1
*facs_table
= &data
->facs_table
;
184 uint32_t addr
= le32_to_cpu(data
->facs_addr
);
186 ACPI_READ_FIELD(data
->qts
, facs_table
->signature
, addr
);
187 ACPI_READ_FIELD(data
->qts
, facs_table
->length
, addr
);
188 ACPI_READ_FIELD(data
->qts
, facs_table
->hardware_signature
, addr
);
189 ACPI_READ_FIELD(data
->qts
, facs_table
->firmware_waking_vector
, addr
);
190 ACPI_READ_FIELD(data
->qts
, facs_table
->global_lock
, addr
);
191 ACPI_READ_FIELD(data
->qts
, facs_table
->flags
, addr
);
192 ACPI_READ_ARRAY(data
->qts
, facs_table
->resverved3
, addr
);
194 ACPI_ASSERT_CMP(facs_table
->signature
, "FACS");
198 * load ACPI table at @addr into table descriptor @sdt_table
199 * and check that header checksum matches actual one.
201 static void fetch_table(QTestState
*qts
, AcpiSdtTable
*sdt_table
, uint32_t addr
)
205 memset(sdt_table
, 0, sizeof(*sdt_table
));
206 ACPI_READ_TABLE_HEADER(qts
, &sdt_table
->header
, addr
);
208 sdt_table
->aml_len
= le32_to_cpu(sdt_table
->header
.length
)
209 - sizeof(AcpiTableHeader
);
210 sdt_table
->aml
= g_malloc0(sdt_table
->aml_len
);
211 ACPI_READ_ARRAY_PTR(qts
, sdt_table
->aml
, sdt_table
->aml_len
, addr
);
213 checksum
= acpi_calc_checksum((uint8_t *)sdt_table
,
214 sizeof(AcpiTableHeader
)) +
215 acpi_calc_checksum((uint8_t *)sdt_table
->aml
,
220 static void test_acpi_dsdt_table(test_data
*data
)
222 AcpiSdtTable dsdt_table
;
223 uint32_t addr
= le32_to_cpu(data
->dsdt_addr
);
225 fetch_table(data
->qts
, &dsdt_table
, addr
);
226 ACPI_ASSERT_CMP(dsdt_table
.header
.signature
, "DSDT");
228 /* Since DSDT isn't in RSDT, add DSDT to ASL test tables list manually */
229 g_array_append_val(data
->tables
, dsdt_table
);
232 /* Load all tables and add to test list directly RSDT referenced tables */
233 static void fetch_rsdt_referenced_tables(test_data
*data
)
235 int tables_nr
= data
->rsdt_tables_nr
;
238 for (i
= 0; i
< tables_nr
; i
++) {
239 AcpiSdtTable ssdt_table
;
242 addr
= le32_to_cpu(data
->rsdt_tables_addr
[i
]);
243 fetch_table(data
->qts
, &ssdt_table
, addr
);
245 /* Add table to ASL test tables list */
246 g_array_append_val(data
->tables
, ssdt_table
);
250 static void dump_aml_files(test_data
*data
, bool rebuild
)
253 GError
*error
= NULL
;
254 gchar
*aml_file
= NULL
;
259 for (i
= 0; i
< data
->tables
->len
; ++i
) {
260 const char *ext
= data
->variant
? data
->variant
: "";
261 sdt
= &g_array_index(data
->tables
, AcpiSdtTable
, i
);
265 aml_file
= g_strdup_printf("%s/%s/%.4s%s", data_dir
, data
->machine
,
266 (gchar
*)&sdt
->header
.signature
, ext
);
267 fd
= g_open(aml_file
, O_WRONLY
|O_TRUNC
|O_CREAT
,
268 S_IRUSR
|S_IWUSR
|S_IRGRP
|S_IWGRP
|S_IROTH
);
270 fd
= g_file_open_tmp("aml-XXXXXX", &sdt
->aml_file
, &error
);
271 g_assert_no_error(error
);
275 ret
= qemu_write_full(fd
, sdt
, sizeof(AcpiTableHeader
));
276 g_assert(ret
== sizeof(AcpiTableHeader
));
277 ret
= qemu_write_full(fd
, sdt
->aml
, sdt
->aml_len
);
278 g_assert(ret
== sdt
->aml_len
);
286 static bool compare_signature(AcpiSdtTable
*sdt
, const char *signature
)
288 return !memcmp(&sdt
->header
.signature
, signature
, 4);
291 static bool load_asl(GArray
*sdts
, AcpiSdtTable
*sdt
)
294 GError
*error
= NULL
;
295 GString
*command_line
= g_string_new(iasl
);
297 gchar
*out
, *out_err
;
301 fd
= g_file_open_tmp("asl-XXXXXX.dsl", &sdt
->asl_file
, &error
);
302 g_assert_no_error(error
);
305 /* build command line */
306 g_string_append_printf(command_line
, " -p %s ", sdt
->asl_file
);
307 if (compare_signature(sdt
, "DSDT") ||
308 compare_signature(sdt
, "SSDT")) {
309 for (i
= 0; i
< sdts
->len
; ++i
) {
310 temp
= &g_array_index(sdts
, AcpiSdtTable
, i
);
311 if (compare_signature(temp
, "DSDT") ||
312 compare_signature(temp
, "SSDT")) {
313 g_string_append_printf(command_line
, "-e %s ", temp
->aml_file
);
317 g_string_append_printf(command_line
, "-d %s", sdt
->aml_file
);
319 /* pass 'out' and 'out_err' in order to be redirected */
320 ret
= g_spawn_command_line_sync(command_line
->str
, &out
, &out_err
, NULL
, &error
);
321 g_assert_no_error(error
);
323 ret
= g_file_get_contents(sdt
->asl_file
, &sdt
->asl
,
324 &sdt
->asl_len
, &error
);
326 g_assert_no_error(error
);
327 ret
= (sdt
->asl_len
> 0);
332 g_string_free(command_line
, true);
337 #define COMMENT_END "*/"
338 #define DEF_BLOCK "DefinitionBlock ("
339 #define BLOCK_NAME_END ","
341 static GString
*normalize_asl(gchar
*asl_code
)
343 GString
*asl
= g_string_new(asl_code
);
344 gchar
*comment
, *block_name
;
346 /* strip comments (different generation days) */
347 comment
= g_strstr_len(asl
->str
, asl
->len
, COMMENT_END
);
349 comment
+= strlen(COMMENT_END
);
350 while (*comment
== '\n') {
353 asl
= g_string_erase(asl
, 0, comment
- asl
->str
);
356 /* strip def block name (it has file path in it) */
357 if (g_str_has_prefix(asl
->str
, DEF_BLOCK
)) {
358 block_name
= g_strstr_len(asl
->str
, asl
->len
, BLOCK_NAME_END
);
359 g_assert(block_name
);
360 asl
= g_string_erase(asl
, 0,
361 block_name
+ sizeof(BLOCK_NAME_END
) - asl
->str
);
367 static GArray
*load_expected_aml(test_data
*data
)
371 GError
*error
= NULL
;
374 GArray
*exp_tables
= g_array_new(false, true, sizeof(AcpiSdtTable
));
378 for (i
= 0; i
< data
->tables
->len
; ++i
) {
379 AcpiSdtTable exp_sdt
;
380 gchar
*aml_file
= NULL
;
381 const char *ext
= data
->variant
? data
->variant
: "";
383 sdt
= &g_array_index(data
->tables
, AcpiSdtTable
, i
);
385 memset(&exp_sdt
, 0, sizeof(exp_sdt
));
386 exp_sdt
.header
.signature
= sdt
->header
.signature
;
389 aml_file
= g_strdup_printf("%s/%s/%.4s%s", data_dir
, data
->machine
,
390 (gchar
*)&sdt
->header
.signature
, ext
);
392 fprintf(stderr
, "Looking for expected file '%s'\n", aml_file
);
394 if (g_file_test(aml_file
, G_FILE_TEST_EXISTS
)) {
395 exp_sdt
.aml_file
= aml_file
;
396 } else if (*ext
!= '\0') {
397 /* try fallback to generic (extension less) expected file */
402 g_assert(exp_sdt
.aml_file
);
404 fprintf(stderr
, "Using expected file '%s'\n", aml_file
);
406 ret
= g_file_get_contents(aml_file
, &exp_sdt
.aml
,
407 &exp_sdt
.aml_len
, &error
);
409 g_assert_no_error(error
);
410 g_assert(exp_sdt
.aml
);
411 g_assert(exp_sdt
.aml_len
);
413 g_array_append_val(exp_tables
, exp_sdt
);
419 /* test the list of tables in @data->tables against reference tables */
420 static void test_acpi_asl(test_data
*data
)
423 AcpiSdtTable
*sdt
, *exp_sdt
;
425 gboolean exp_err
, err
;
427 memset(&exp_data
, 0, sizeof(exp_data
));
428 exp_data
.tables
= load_expected_aml(data
);
429 dump_aml_files(data
, false);
430 for (i
= 0; i
< data
->tables
->len
; ++i
) {
431 GString
*asl
, *exp_asl
;
433 sdt
= &g_array_index(data
->tables
, AcpiSdtTable
, i
);
434 exp_sdt
= &g_array_index(exp_data
.tables
, AcpiSdtTable
, i
);
436 err
= load_asl(data
->tables
, sdt
);
437 asl
= normalize_asl(sdt
->asl
);
439 exp_err
= load_asl(exp_data
.tables
, exp_sdt
);
440 exp_asl
= normalize_asl(exp_sdt
->asl
);
442 /* TODO: check for warnings */
443 g_assert(!err
|| exp_err
);
445 if (g_strcmp0(asl
->str
, exp_asl
->str
)) {
448 "Warning! iasl couldn't parse the expected aml\n");
450 uint32_t signature
= cpu_to_le32(exp_sdt
->header
.signature
);
451 sdt
->tmp_files_retain
= true;
452 exp_sdt
->tmp_files_retain
= true;
454 "acpi-test: Warning! %.4s mismatch. "
455 "Actual [asl:%s, aml:%s], Expected [asl:%s, aml:%s].\n",
457 sdt
->asl_file
, sdt
->aml_file
,
458 exp_sdt
->asl_file
, exp_sdt
->aml_file
);
460 const char *diff_cmd
= getenv("DIFF");
462 int ret G_GNUC_UNUSED
;
463 char *diff
= g_strdup_printf("%s %s %s", diff_cmd
,
464 exp_sdt
->asl_file
, sdt
->asl_file
);
468 fprintf(stderr
, "acpi-test: Warning. not showing "
469 "difference since no diff utility is specified. "
470 "Set 'DIFF' environment variable to a preferred "
471 "diff utility and run 'make V=1 check' again to "
472 "see ASL difference.");
477 g_string_free(asl
, true);
478 g_string_free(exp_asl
, true);
481 free_test_data(&exp_data
);
484 static bool smbios_ep_table_ok(test_data
*data
)
486 struct smbios_21_entry_point
*ep_table
= &data
->smbios_ep_table
;
487 uint32_t addr
= data
->smbios_ep_addr
;
489 ACPI_READ_ARRAY(data
->qts
, ep_table
->anchor_string
, addr
);
490 if (memcmp(ep_table
->anchor_string
, "_SM_", 4)) {
493 ACPI_READ_FIELD(data
->qts
, ep_table
->checksum
, addr
);
494 ACPI_READ_FIELD(data
->qts
, ep_table
->length
, addr
);
495 ACPI_READ_FIELD(data
->qts
, ep_table
->smbios_major_version
, addr
);
496 ACPI_READ_FIELD(data
->qts
, ep_table
->smbios_minor_version
, addr
);
497 ACPI_READ_FIELD(data
->qts
, ep_table
->max_structure_size
, addr
);
498 ACPI_READ_FIELD(data
->qts
, ep_table
->entry_point_revision
, addr
);
499 ACPI_READ_ARRAY(data
->qts
, ep_table
->formatted_area
, addr
);
500 ACPI_READ_ARRAY(data
->qts
, ep_table
->intermediate_anchor_string
, addr
);
501 if (memcmp(ep_table
->intermediate_anchor_string
, "_DMI_", 5)) {
504 ACPI_READ_FIELD(data
->qts
, ep_table
->intermediate_checksum
, addr
);
505 ACPI_READ_FIELD(data
->qts
, ep_table
->structure_table_length
, addr
);
506 if (ep_table
->structure_table_length
== 0) {
509 ACPI_READ_FIELD(data
->qts
, ep_table
->structure_table_address
, addr
);
510 ACPI_READ_FIELD(data
->qts
, ep_table
->number_of_structures
, addr
);
511 if (ep_table
->number_of_structures
== 0) {
514 ACPI_READ_FIELD(data
->qts
, ep_table
->smbios_bcd_revision
, addr
);
515 if (acpi_calc_checksum((uint8_t *)ep_table
, sizeof *ep_table
) ||
516 acpi_calc_checksum((uint8_t *)ep_table
+ 0x10,
517 sizeof *ep_table
- 0x10)) {
523 static void test_smbios_entry_point(test_data
*data
)
527 /* find smbios entry point structure */
528 for (off
= 0xf0000; off
< 0x100000; off
+= 0x10) {
529 uint8_t sig
[] = "_SM_";
532 for (i
= 0; i
< sizeof sig
- 1; ++i
) {
533 sig
[i
] = qtest_readb(data
->qts
, off
+ i
);
536 if (!memcmp(sig
, "_SM_", sizeof sig
)) {
537 /* signature match, but is this a valid entry point? */
538 data
->smbios_ep_addr
= off
;
539 if (smbios_ep_table_ok(data
)) {
545 g_assert_cmphex(off
, <, 0x100000);
548 static inline bool smbios_single_instance(uint8_t type
)
564 static void test_smbios_structs(test_data
*data
)
566 DECLARE_BITMAP(struct_bitmap
, SMBIOS_MAX_TYPE
+1) = { 0 };
567 struct smbios_21_entry_point
*ep_table
= &data
->smbios_ep_table
;
568 uint32_t addr
= le32_to_cpu(ep_table
->structure_table_address
);
569 int i
, len
, max_len
= 0;
570 uint8_t type
, prv
, crt
;
572 /* walk the smbios tables */
573 for (i
= 0; i
< le16_to_cpu(ep_table
->number_of_structures
); i
++) {
575 /* grab type and formatted area length from struct header */
576 type
= qtest_readb(data
->qts
, addr
);
577 g_assert_cmpuint(type
, <=, SMBIOS_MAX_TYPE
);
578 len
= qtest_readb(data
->qts
, addr
+ 1);
580 /* single-instance structs must not have been encountered before */
581 if (smbios_single_instance(type
)) {
582 g_assert(!test_bit(type
, struct_bitmap
));
584 set_bit(type
, struct_bitmap
);
586 /* seek to end of unformatted string area of this struct ("\0\0") */
590 crt
= qtest_readb(data
->qts
, addr
+ len
);
594 /* keep track of max. struct size */
597 g_assert_cmpuint(max_len
, <=, ep_table
->max_structure_size
);
600 /* start of next structure */
604 /* total table length and max struct size must match entry point values */
605 g_assert_cmpuint(le16_to_cpu(ep_table
->structure_table_length
), ==,
606 addr
- le32_to_cpu(ep_table
->structure_table_address
));
607 g_assert_cmpuint(le16_to_cpu(ep_table
->max_structure_size
), ==, max_len
);
609 /* required struct types must all be present */
610 for (i
= 0; i
< data
->required_struct_types_len
; i
++) {
611 g_assert(test_bit(data
->required_struct_types
[i
], struct_bitmap
));
615 static void test_acpi_one(const char *params
, test_data
*data
)
619 /* Disable kernel irqchip to be able to override apic irq0. */
620 args
= g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
621 "-net none -display none %s "
622 "-drive id=hd0,if=none,file=%s,format=raw "
623 "-device ide-hd,drive=hd0 ",
624 data
->machine
, "kvm:tcg",
625 params
? params
: "", disk
);
627 data
->qts
= qtest_init(args
);
629 boot_sector_test(data
->qts
);
631 data
->tables
= g_array_new(false, true, sizeof(AcpiSdtTable
));
632 test_acpi_rsdp_address(data
);
633 test_acpi_rsdp_table(data
);
634 test_acpi_rsdt_table(data
);
635 fadt_fetch_facs_and_dsdt_ptrs(data
);
636 test_acpi_facs_table(data
);
637 test_acpi_dsdt_table(data
);
638 fetch_rsdt_referenced_tables(data
);
640 sanitize_fadt_ptrs(data
);
643 if (getenv(ACPI_REBUILD_EXPECTED_AML
)) {
644 dump_aml_files(data
, true);
650 test_smbios_entry_point(data
);
651 test_smbios_structs(data
);
653 assert(!global_qtest
);
654 qtest_quit(data
->qts
);
658 static uint8_t base_required_struct_types
[] = {
659 0, 1, 3, 4, 16, 17, 19, 32, 127
662 static void test_acpi_piix4_tcg(void)
666 /* Supplying -machine accel argument overrides the default (qtest).
667 * This is to make guest actually run.
669 memset(&data
, 0, sizeof(data
));
670 data
.machine
= MACHINE_PC
;
671 data
.required_struct_types
= base_required_struct_types
;
672 data
.required_struct_types_len
= ARRAY_SIZE(base_required_struct_types
);
673 test_acpi_one(NULL
, &data
);
674 free_test_data(&data
);
677 static void test_acpi_piix4_tcg_bridge(void)
681 memset(&data
, 0, sizeof(data
));
682 data
.machine
= MACHINE_PC
;
683 data
.variant
= ".bridge";
684 data
.required_struct_types
= base_required_struct_types
;
685 data
.required_struct_types_len
= ARRAY_SIZE(base_required_struct_types
);
686 test_acpi_one("-device pci-bridge,chassis_nr=1", &data
);
687 free_test_data(&data
);
690 static void test_acpi_q35_tcg(void)
694 memset(&data
, 0, sizeof(data
));
695 data
.machine
= MACHINE_Q35
;
696 data
.required_struct_types
= base_required_struct_types
;
697 data
.required_struct_types_len
= ARRAY_SIZE(base_required_struct_types
);
698 test_acpi_one(NULL
, &data
);
699 free_test_data(&data
);
702 static void test_acpi_q35_tcg_bridge(void)
706 memset(&data
, 0, sizeof(data
));
707 data
.machine
= MACHINE_Q35
;
708 data
.variant
= ".bridge";
709 data
.required_struct_types
= base_required_struct_types
;
710 data
.required_struct_types_len
= ARRAY_SIZE(base_required_struct_types
);
711 test_acpi_one("-device pci-bridge,chassis_nr=1",
713 free_test_data(&data
);
716 static void test_acpi_q35_tcg_mmio64(void)
719 .machine
= MACHINE_Q35
,
720 .variant
= ".mmio64",
721 .required_struct_types
= base_required_struct_types
,
722 .required_struct_types_len
= ARRAY_SIZE(base_required_struct_types
)
725 test_acpi_one("-m 128M,slots=1,maxmem=2G "
726 "-device pci-testdev,membar=2G",
728 free_test_data(&data
);
731 static void test_acpi_piix4_tcg_cphp(void)
735 memset(&data
, 0, sizeof(data
));
736 data
.machine
= MACHINE_PC
;
737 data
.variant
= ".cphp";
738 test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6"
739 " -numa node -numa node"
740 " -numa dist,src=0,dst=1,val=21",
742 free_test_data(&data
);
745 static void test_acpi_q35_tcg_cphp(void)
749 memset(&data
, 0, sizeof(data
));
750 data
.machine
= MACHINE_Q35
;
751 data
.variant
= ".cphp";
752 test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6"
753 " -numa node -numa node"
754 " -numa dist,src=0,dst=1,val=21",
756 free_test_data(&data
);
759 static uint8_t ipmi_required_struct_types
[] = {
760 0, 1, 3, 4, 16, 17, 19, 32, 38, 127
763 static void test_acpi_q35_tcg_ipmi(void)
767 memset(&data
, 0, sizeof(data
));
768 data
.machine
= MACHINE_Q35
;
769 data
.variant
= ".ipmibt";
770 data
.required_struct_types
= ipmi_required_struct_types
;
771 data
.required_struct_types_len
= ARRAY_SIZE(ipmi_required_struct_types
);
772 test_acpi_one("-device ipmi-bmc-sim,id=bmc0"
773 " -device isa-ipmi-bt,bmc=bmc0",
775 free_test_data(&data
);
778 static void test_acpi_piix4_tcg_ipmi(void)
782 /* Supplying -machine accel argument overrides the default (qtest).
783 * This is to make guest actually run.
785 memset(&data
, 0, sizeof(data
));
786 data
.machine
= MACHINE_PC
;
787 data
.variant
= ".ipmikcs";
788 data
.required_struct_types
= ipmi_required_struct_types
;
789 data
.required_struct_types_len
= ARRAY_SIZE(ipmi_required_struct_types
);
790 test_acpi_one("-device ipmi-bmc-sim,id=bmc0"
791 " -device isa-ipmi-kcs,irq=0,bmc=bmc0",
793 free_test_data(&data
);
796 static void test_acpi_q35_tcg_memhp(void)
800 memset(&data
, 0, sizeof(data
));
801 data
.machine
= MACHINE_Q35
;
802 data
.variant
= ".memhp";
803 test_acpi_one(" -m 128,slots=3,maxmem=1G"
804 " -numa node -numa node"
805 " -numa dist,src=0,dst=1,val=21",
807 free_test_data(&data
);
810 static void test_acpi_piix4_tcg_memhp(void)
814 memset(&data
, 0, sizeof(data
));
815 data
.machine
= MACHINE_PC
;
816 data
.variant
= ".memhp";
817 test_acpi_one(" -m 128,slots=3,maxmem=1G"
818 " -numa node -numa node"
819 " -numa dist,src=0,dst=1,val=21",
821 free_test_data(&data
);
824 static void test_acpi_q35_tcg_numamem(void)
828 memset(&data
, 0, sizeof(data
));
829 data
.machine
= MACHINE_Q35
;
830 data
.variant
= ".numamem";
831 test_acpi_one(" -numa node -numa node,mem=128", &data
);
832 free_test_data(&data
);
835 static void test_acpi_piix4_tcg_numamem(void)
839 memset(&data
, 0, sizeof(data
));
840 data
.machine
= MACHINE_PC
;
841 data
.variant
= ".numamem";
842 test_acpi_one(" -numa node -numa node,mem=128", &data
);
843 free_test_data(&data
);
846 static void test_acpi_tcg_dimm_pxm(const char *machine
)
850 memset(&data
, 0, sizeof(data
));
851 data
.machine
= machine
;
852 data
.variant
= ".dimmpxm";
853 test_acpi_one(" -machine nvdimm=on,nvdimm-persistence=cpu"
855 " -m 128M,slots=3,maxmem=1G"
856 " -numa node,mem=32M,nodeid=0"
857 " -numa node,mem=32M,nodeid=1"
858 " -numa node,mem=32M,nodeid=2"
859 " -numa node,mem=32M,nodeid=3"
860 " -numa cpu,node-id=0,socket-id=0"
861 " -numa cpu,node-id=1,socket-id=1"
862 " -numa cpu,node-id=2,socket-id=2"
863 " -numa cpu,node-id=3,socket-id=3"
864 " -object memory-backend-ram,id=ram0,size=128M"
865 " -object memory-backend-ram,id=nvm0,size=128M"
866 " -device pc-dimm,id=dimm0,memdev=ram0,node=1"
867 " -device nvdimm,id=dimm1,memdev=nvm0,node=2",
869 free_test_data(&data
);
872 static void test_acpi_q35_tcg_dimm_pxm(void)
874 test_acpi_tcg_dimm_pxm(MACHINE_Q35
);
877 static void test_acpi_piix4_tcg_dimm_pxm(void)
879 test_acpi_tcg_dimm_pxm(MACHINE_PC
);
882 int main(int argc
, char *argv
[])
884 const char *arch
= qtest_get_arch();
887 ret
= boot_sector_init(disk
);
891 g_test_init(&argc
, &argv
, NULL
);
893 if (strcmp(arch
, "i386") == 0 || strcmp(arch
, "x86_64") == 0) {
894 qtest_add_func("acpi/piix4", test_acpi_piix4_tcg
);
895 qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge
);
896 qtest_add_func("acpi/q35", test_acpi_q35_tcg
);
897 qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge
);
898 qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64
);
899 qtest_add_func("acpi/piix4/ipmi", test_acpi_piix4_tcg_ipmi
);
900 qtest_add_func("acpi/q35/ipmi", test_acpi_q35_tcg_ipmi
);
901 qtest_add_func("acpi/piix4/cpuhp", test_acpi_piix4_tcg_cphp
);
902 qtest_add_func("acpi/q35/cpuhp", test_acpi_q35_tcg_cphp
);
903 qtest_add_func("acpi/piix4/memhp", test_acpi_piix4_tcg_memhp
);
904 qtest_add_func("acpi/q35/memhp", test_acpi_q35_tcg_memhp
);
905 qtest_add_func("acpi/piix4/numamem", test_acpi_piix4_tcg_numamem
);
906 qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem
);
907 qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm
);
908 qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm
);
911 boot_sector_cleanup(disk
);