#define ACPI_REBUILD_EXPECTED_AML "TEST_ACPI_REBUILD_AML"
typedef struct {
+ const char *accel;
const char *machine;
const char *variant;
+ const char *uefi_fl1;
+ const char *uefi_fl2;
+ const char *cd;
+ const uint64_t ram_start;
+ const uint64_t scan_len;
uint64_t rsdp_addr;
uint8_t rsdp_table[36 /* ACPI 2.0+ RSDP size */];
GArray *tables;
g_array_free(data->tables, true);
}
-static void test_acpi_rsdp_address(test_data *data)
-{
- uint32_t off = acpi_find_rsdp_address(data->qts);
- g_assert_cmphex(off, <, 0x100000);
- data->rsdp_addr = off;
-}
-
static void test_acpi_rsdp_table(test_data *data)
{
uint8_t *rsdp_table = data->rsdp_table;
AcpiSdtTable table = g_array_index(data->tables, typeof(table), 0);
uint8_t *fadt_aml = table.aml;
uint32_t fadt_len = table.aml_len;
+ uint32_t val;
+ int dsdt_offset = 40 /* DSDT */;
+ int dsdt_entry_size = 4;
g_assert(compare_signature(&table, "FACP"));
/* Since DSDT/FACS isn't in RSDT, add them to ASL test list manually */
- acpi_fetch_table(data->qts, &table.aml, &table.aml_len,
- fadt_aml + 36 /* FIRMWARE_CTRL */, 4, "FACS", false);
- g_array_append_val(data->tables, table);
+ memcpy(&val, fadt_aml + 112 /* Flags */, 4);
+ val = le32_to_cpu(val);
+ if (!(val & 1UL << 20 /* HW_REDUCED_ACPI */)) {
+ acpi_fetch_table(data->qts, &table.aml, &table.aml_len,
+ fadt_aml + 36 /* FIRMWARE_CTRL */, 4, "FACS", false);
+ g_array_append_val(data->tables, table);
+ }
+ memcpy(&val, fadt_aml + dsdt_offset, 4);
+ val = le32_to_cpu(val);
+ if (!val) {
+ dsdt_offset = 140 /* X_DSDT */;
+ dsdt_entry_size = 8;
+ }
acpi_fetch_table(data->qts, &table.aml, &table.aml_len,
- fadt_aml + 40 /* DSDT */, 4, "DSDT", true);
+ fadt_aml + dsdt_offset, dsdt_entry_size, "DSDT", true);
g_array_append_val(data->tables, table);
memset(fadt_aml + 36, 0, 4); /* sanitize FIRMWARE_CTRL ptr */
sdt->aml, ext);
fd = g_open(aml_file, O_WRONLY|O_TRUNC|O_CREAT,
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
+ if (fd < 0) {
+ perror(aml_file);
+ }
+ g_assert(fd >= 0);
} else {
fd = g_file_open_tmp("aml-XXXXXX", &sdt->aml_file, &error);
g_assert_no_error(error);
}
- g_assert(fd >= 0);
ret = qemu_write_full(fd, sdt->aml, sdt->aml_len);
g_assert(ret == sdt->aml_len);
return exp_tables;
}
+static bool test_acpi_find_diff_allowed(AcpiSdtTable *sdt)
+{
+ const gchar *allowed_diff_file[] = {
+#include "bios-tables-test-allowed-diff.h"
+ NULL
+ };
+ const gchar **f;
+
+ for (f = allowed_diff_file; *f; ++f) {
+ if (!g_strcmp0(sdt->aml_file, *f)) {
+ return true;
+ }
+ }
+ return false;
+}
+
/* test the list of tables in @data->tables against reference tables */
static void test_acpi_asl(test_data *data)
{
int i;
AcpiSdtTable *sdt, *exp_sdt;
test_data exp_data;
- gboolean exp_err, err;
+ gboolean exp_err, err, all_tables_match = true;
memset(&exp_data, 0, sizeof(exp_data));
exp_data.tables = load_expected_aml(data);
sdt = &g_array_index(data->tables, AcpiSdtTable, i);
exp_sdt = &g_array_index(exp_data.tables, AcpiSdtTable, i);
+ if (sdt->aml_len == exp_sdt->aml_len &&
+ !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) {
+ /* Identical table binaries: no need to disassemble. */
+ continue;
+ }
+
+ fprintf(stderr,
+ "acpi-test: Warning! %.4s binary file mismatch. "
+ "Actual [aml:%s], Expected [aml:%s].\n",
+ exp_sdt->aml, sdt->aml_file, exp_sdt->aml_file);
+
+ all_tables_match = all_tables_match &&
+ test_acpi_find_diff_allowed(exp_sdt);
+
err = load_asl(data->tables, sdt);
asl = normalize_asl(sdt->asl);
"see ASL difference.");
}
}
- }
+ }
}
g_string_free(asl, true);
g_string_free(exp_asl, true);
}
+ g_assert(all_tables_match);
free_test_data(&exp_data);
}
static void test_acpi_one(const char *params, test_data *data)
{
char *args;
-
- /* Disable kernel irqchip to be able to override apic irq0. */
- args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
- "-net none -display none %s "
- "-drive id=hd0,if=none,file=%s,format=raw "
- "-device ide-hd,drive=hd0 ",
- data->machine, "kvm:tcg",
- params ? params : "", disk);
+ bool use_uefi = data->uefi_fl1 && data->uefi_fl2;
+
+ if (use_uefi) {
+ /*
+ * TODO: convert '-drive if=pflash' to new syntax (see e33763be7cd3)
+ * when arm/virt boad starts to support it.
+ */
+ args = g_strdup_printf("-machine %s,accel=%s -nodefaults -nographic "
+ "-drive if=pflash,format=raw,file=%s,readonly "
+ "-drive if=pflash,format=raw,file=%s,snapshot=on -cdrom %s %s",
+ data->machine, data->accel ? data->accel : "kvm:tcg",
+ data->uefi_fl1, data->uefi_fl2, data->cd, params ? params : "");
+
+ } else {
+ /* Disable kernel irqchip to be able to override apic irq0. */
+ args = g_strdup_printf("-machine %s,accel=%s,kernel-irqchip=off "
+ "-net none -display none %s "
+ "-drive id=hd0,if=none,file=%s,format=raw "
+ "-device ide-hd,drive=hd0 ",
+ data->machine, data->accel ? data->accel : "kvm:tcg",
+ params ? params : "", disk);
+ }
data->qts = qtest_init(args);
- boot_sector_test(data->qts);
+ if (use_uefi) {
+ g_assert(data->scan_len);
+ data->rsdp_addr = acpi_find_rsdp_address_uefi(data->qts,
+ data->ram_start, data->scan_len);
+ } else {
+ boot_sector_test(data->qts);
+ data->rsdp_addr = acpi_find_rsdp_address(data->qts);
+ g_assert_cmphex(data->rsdp_addr, <, 0x100000);
+ }
data->tables = g_array_new(false, true, sizeof(AcpiSdtTable));
- test_acpi_rsdp_address(data);
test_acpi_rsdp_table(data);
test_acpi_rxsdt_table(data);
test_acpi_fadt_table(data);
}
}
- test_smbios_entry_point(data);
- test_smbios_structs(data);
+ /*
+ * TODO: make SMBIOS tests work with UEFI firmware,
+ * Bug on uefi-test-tools to provide entry point:
+ * https://bugs.launchpad.net/qemu/+bug/1821884
+ */
+ if (!use_uefi) {
+ test_smbios_entry_point(data);
+ test_smbios_structs(data);
+ }
assert(!global_qtest);
qtest_quit(data->qts);
};
test_acpi_one("-m 128M,slots=1,maxmem=2G "
+ "-object memory-backend-ram,id=ram0,size=128M "
+ "-numa node,memdev=ram0 "
"-device pci-testdev,membar=2G",
&data);
free_test_data(&data);
data.machine = MACHINE_PC;
data.variant = ".cphp";
test_acpi_one("-smp 2,cores=3,sockets=2,maxcpus=6"
- " -numa node -numa node"
+ " -object memory-backend-ram,id=ram0,size=64M"
+ " -object memory-backend-ram,id=ram1,size=64M"
+ " -numa node,memdev=ram0 -numa node,memdev=ram1"
" -numa dist,src=0,dst=1,val=21",
&data);
free_test_data(&data);
data.machine = MACHINE_Q35;
data.variant = ".cphp";
test_acpi_one(" -smp 2,cores=3,sockets=2,maxcpus=6"
- " -numa node -numa node"
+ " -object memory-backend-ram,id=ram0,size=64M"
+ " -object memory-backend-ram,id=ram1,size=64M"
+ " -numa node,memdev=ram0 -numa node,memdev=ram1"
" -numa dist,src=0,dst=1,val=21",
&data);
free_test_data(&data);
data.machine = MACHINE_Q35;
data.variant = ".memhp";
test_acpi_one(" -m 128,slots=3,maxmem=1G"
- " -numa node -numa node"
+ " -object memory-backend-ram,id=ram0,size=64M"
+ " -object memory-backend-ram,id=ram1,size=64M"
+ " -numa node,memdev=ram0 -numa node,memdev=ram1"
" -numa dist,src=0,dst=1,val=21",
&data);
free_test_data(&data);
data.machine = MACHINE_PC;
data.variant = ".memhp";
test_acpi_one(" -m 128,slots=3,maxmem=1G"
- " -numa node -numa node"
+ " -object memory-backend-ram,id=ram0,size=64M"
+ " -object memory-backend-ram,id=ram1,size=64M"
+ " -numa node,memdev=ram0 -numa node,memdev=ram1"
" -numa dist,src=0,dst=1,val=21",
&data);
free_test_data(&data);
memset(&data, 0, sizeof(data));
data.machine = MACHINE_Q35;
data.variant = ".numamem";
- test_acpi_one(" -numa node -numa node,mem=128", &data);
+ test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M"
+ " -numa node -numa node,memdev=ram0", &data);
free_test_data(&data);
}
memset(&data, 0, sizeof(data));
data.machine = MACHINE_PC;
data.variant = ".numamem";
- test_acpi_one(" -numa node -numa node,mem=128", &data);
+ test_acpi_one(" -object memory-backend-ram,id=ram0,size=128M"
+ " -numa node -numa node,memdev=ram0", &data);
free_test_data(&data);
}
test_acpi_one(" -machine nvdimm=on,nvdimm-persistence=cpu"
" -smp 4,sockets=4"
" -m 128M,slots=3,maxmem=1G"
- " -numa node,mem=32M,nodeid=0"
- " -numa node,mem=32M,nodeid=1"
- " -numa node,mem=32M,nodeid=2"
- " -numa node,mem=32M,nodeid=3"
+ " -object memory-backend-ram,id=ram0,size=32M"
+ " -object memory-backend-ram,id=ram1,size=32M"
+ " -object memory-backend-ram,id=ram2,size=32M"
+ " -object memory-backend-ram,id=ram3,size=32M"
+ " -numa node,memdev=ram0,nodeid=0"
+ " -numa node,memdev=ram1,nodeid=1"
+ " -numa node,memdev=ram2,nodeid=2"
+ " -numa node,memdev=ram3,nodeid=3"
" -numa cpu,node-id=0,socket-id=0"
" -numa cpu,node-id=1,socket-id=1"
" -numa cpu,node-id=2,socket-id=2"
" -numa cpu,node-id=3,socket-id=3"
- " -object memory-backend-ram,id=ram0,size=128M"
+ " -object memory-backend-ram,id=ram4,size=128M"
" -object memory-backend-ram,id=nvm0,size=128M"
- " -device pc-dimm,id=dimm0,memdev=ram0,node=1"
+ " -device pc-dimm,id=dimm0,memdev=ram4,node=1"
" -device nvdimm,id=dimm1,memdev=nvm0,node=2",
&data);
free_test_data(&data);
test_acpi_tcg_dimm_pxm(MACHINE_PC);
}
+static void test_acpi_virt_tcg(void)
+{
+ test_data data = {
+ .machine = "virt",
+ .accel = "tcg",
+ .uefi_fl1 = "pc-bios/edk2-aarch64-code.fd",
+ .uefi_fl2 = "pc-bios/edk2-arm-vars.fd",
+ .cd = "tests/data/uefi-boot-images/bios-tables-test.aarch64.iso.qcow2",
+ .ram_start = 0x40000000ULL,
+ .scan_len = 128ULL * 1024 * 1024,
+ };
+
+ test_acpi_one("-cpu cortex-a57", &data);
+ free_test_data(&data);
+}
+
int main(int argc, char *argv[])
{
const char *arch = qtest_get_arch();
int ret;
- ret = boot_sector_init(disk);
- if(ret)
- return ret;
-
g_test_init(&argc, &argv, NULL);
if (strcmp(arch, "i386") == 0 || strcmp(arch, "x86_64") == 0) {
+ ret = boot_sector_init(disk);
+ if (ret) {
+ return ret;
+ }
+
qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
qtest_add_func("acpi/q35", test_acpi_q35_tcg);
qtest_add_func("acpi/q35/numamem", test_acpi_q35_tcg_numamem);
qtest_add_func("acpi/piix4/dimmpxm", test_acpi_piix4_tcg_dimm_pxm);
qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
+ } else if (strcmp(arch, "aarch64") == 0) {
+ qtest_add_func("acpi/virt", test_acpi_virt_tcg);
}
ret = g_test_run();
boot_sector_cleanup(disk);