#include "qemu/bitmap.h"
#include "acpi-utils.h"
#include "boot-sector.h"
+#include "tpm-emu.h"
+#include "hw/acpi/tpm.h"
+
#define MACHINE_PC "pc"
#define MACHINE_Q35 "q35"
const char *variant;
const char *uefi_fl1;
const char *uefi_fl2;
+ const char *blkdev;
const char *cd;
const uint64_t ram_start;
const uint64_t scan_len;
GArray *tables;
uint32_t smbios_ep_addr;
struct smbios_21_entry_point smbios_ep_table;
+ uint16_t smbios_cpu_max_speed;
+ uint16_t smbios_cpu_curr_speed;
uint8_t *required_struct_types;
int required_struct_types_len;
QTestState *qts;
static char disk[] = "tests/acpi-test-disk-XXXXXX";
static const char *data_dir = "tests/data/acpi";
#ifdef CONFIG_IASL
-static const char *iasl = stringify(CONFIG_IASL);
+static const char *iasl = CONFIG_IASL;
#else
static const char *iasl;
#endif
fflush(stderr);
if (getenv("V")) {
const char *diff_env = getenv("DIFF");
- const char *diff_cmd = diff_env ? diff_env : "diff -u";
+ const char *diff_cmd = diff_env ? diff_env : "diff -U 16";
char *diff = g_strdup_printf("%s %s %s", diff_cmd,
exp_sdt->asl_file, sdt->asl_file);
int out = dup(STDOUT_FILENO);
}
}
+static bool smbios_cpu_test(test_data *data, uint32_t addr)
+{
+ uint16_t expect_speed[2];
+ uint16_t real;
+ int offset[2];
+ int i;
+
+ /* Check CPU speed for backward compatibility */
+ offset[0] = offsetof(struct smbios_type_4, max_speed);
+ offset[1] = offsetof(struct smbios_type_4, current_speed);
+ expect_speed[0] = data->smbios_cpu_max_speed ? : 2000;
+ expect_speed[1] = data->smbios_cpu_curr_speed ? : 2000;
+
+ for (i = 0; i < 2; i++) {
+ real = qtest_readw(data->qts, addr + offset[i]);
+ if (real != expect_speed[i]) {
+ fprintf(stderr, "Unexpected SMBIOS CPU speed: real %u expect %u\n",
+ real, expect_speed[i]);
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void test_smbios_structs(test_data *data)
{
DECLARE_BITMAP(struct_bitmap, SMBIOS_MAX_TYPE+1) = { 0 };
}
set_bit(type, struct_bitmap);
+ if (type == 4) {
+ g_assert(smbios_cpu_test(data, addr));
+ }
+
/* seek to end of unformatted string area of this struct ("\0\0") */
prv = crt = 1;
while (prv || crt) {
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,kernel-irqchip=off %s -accel tcg "
+ args = g_strdup_printf("-machine %s %s -accel tcg "
"-net none -display none %s "
"-drive id=hd0,if=none,file=%s,format=raw "
- "-device ide-hd,drive=hd0 ",
+ "-device %s,drive=hd0 ",
data->machine, data->tcg_only ? "" : "-accel kvm",
- params ? params : "", disk);
+ params ? params : "", disk,
+ data->blkdev ?: "ide-hd");
}
data->qts = qtest_init(args);
free_test_data(&data);
}
+static void test_acpi_piix4_no_root_hotplug(void)
+{
+ test_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_PC;
+ data.variant = ".roothp";
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
+ test_acpi_one("-global PIIX4_PM.acpi-root-pci-hotplug=off "
+ "-device pci-bridge,chassis_nr=1", &data);
+ free_test_data(&data);
+}
+
+static void test_acpi_piix4_no_bridge_hotplug(void)
+{
+ test_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_PC;
+ data.variant = ".hpbridge";
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
+ test_acpi_one("-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off "
+ "-device pci-bridge,chassis_nr=1", &data);
+ free_test_data(&data);
+}
+
+static void test_acpi_piix4_no_acpi_pci_hotplug(void)
+{
+ test_data data;
+
+ memset(&data, 0, sizeof(data));
+ data.machine = MACHINE_PC;
+ data.variant = ".hpbrroot";
+ data.required_struct_types = base_required_struct_types;
+ data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
+ test_acpi_one("-global PIIX4_PM.acpi-root-pci-hotplug=off "
+ "-global PIIX4_PM.acpi-pci-hotplug-with-bridge-support=off "
+ "-device pci-bridge,chassis_nr=1", &data);
+ free_test_data(&data);
+}
+
static void test_acpi_q35_tcg(void)
{
test_data data;
data.required_struct_types_len = ARRAY_SIZE(base_required_struct_types);
test_acpi_one(NULL, &data);
free_test_data(&data);
+
+ data.smbios_cpu_max_speed = 3000;
+ data.smbios_cpu_curr_speed = 2600;
+ test_acpi_one("-smbios type=4,max-speed=3000,current-speed=2600", &data);
+ free_test_data(&data);
}
static void test_acpi_q35_tcg_bridge(void)
free_test_data(&data);
}
+uint64_t tpm_tis_base_addr;
+
+static void test_acpi_tcg_tpm(const char *machine, const char *tpm_if,
+ uint64_t base)
+{
+#ifdef CONFIG_TPM
+ gchar *tmp_dir_name = g_strdup_printf("qemu-test_acpi_%s_tcg_%s.XXXXXX",
+ machine, tpm_if);
+ char *tmp_path = g_dir_make_tmp(tmp_dir_name, NULL);
+ TestState test;
+ test_data data;
+ GThread *thread;
+ char *args, *variant = g_strdup_printf(".%s", tpm_if);
+
+ tpm_tis_base_addr = base;
+
+ module_call_init(MODULE_INIT_QOM);
+
+ test.addr = g_new0(SocketAddress, 1);
+ test.addr->type = SOCKET_ADDRESS_TYPE_UNIX;
+ test.addr->u.q_unix.path = g_build_filename(tmp_path, "sock", NULL);
+ g_mutex_init(&test.data_mutex);
+ g_cond_init(&test.data_cond);
+ test.data_cond_signal = false;
+
+ thread = g_thread_new(NULL, tpm_emu_ctrl_thread, &test);
+ tpm_emu_test_wait_cond(&test);
+
+ memset(&data, 0, sizeof(data));
+ data.machine = machine;
+ data.variant = variant;
+
+ args = g_strdup_printf(
+ " -chardev socket,id=chr,path=%s"
+ " -tpmdev emulator,id=dev,chardev=chr"
+ " -device tpm-%s,tpmdev=dev",
+ test.addr->u.q_unix.path, tpm_if);
+
+ test_acpi_one(args, &data);
+
+ g_thread_join(thread);
+ g_unlink(test.addr->u.q_unix.path);
+ qapi_free_SocketAddress(test.addr);
+ g_rmdir(tmp_path);
+ g_free(variant);
+ g_free(tmp_path);
+ g_free(tmp_dir_name);
+ g_free(args);
+ free_test_data(&data);
+#else
+ g_test_skip("TPM disabled");
+#endif
+}
+
+static void test_acpi_q35_tcg_tpm_tis(void)
+{
+ test_acpi_tcg_tpm("q35", "tis", 0xFED40000);
+}
+
static void test_acpi_tcg_dimm_pxm(const char *machine)
{
test_data data;
}
+static void test_acpi_microvm_prepare(test_data *data)
+{
+ memset(data, 0, sizeof(*data));
+ data->machine = "microvm";
+ data->required_struct_types = NULL; /* no smbios */
+ data->required_struct_types_len = 0;
+ data->blkdev = "virtio-blk-device";
+}
+
+static void test_acpi_microvm_tcg(void)
+{
+ test_data data;
+
+ test_acpi_microvm_prepare(&data);
+ test_acpi_one(" -machine microvm,acpi=on,rtc=off",
+ &data);
+ free_test_data(&data);
+}
+
+static void test_acpi_microvm_pcie_tcg(void)
+{
+ test_data data;
+
+ test_acpi_microvm_prepare(&data);
+ data.variant = ".pcie";
+ data.tcg_only = true; /* need constant host-phys-bits */
+ test_acpi_one(" -machine microvm,acpi=on,rtc=off,pcie=on",
+ &data);
+ free_test_data(&data);
+}
+
static void test_acpi_virt_tcg_numamem(void)
{
test_data data = {
test_acpi_one("-cpu cortex-a57", &data);
free_test_data(&data);
+
+ data.smbios_cpu_max_speed = 2900;
+ data.smbios_cpu_curr_speed = 2700;
+ test_acpi_one("-cpu cortex-a57 "
+ "-smbios type=4,max-speed=2900,current-speed=2700", &data);
+ free_test_data(&data);
}
int main(int argc, char *argv[])
return ret;
}
+ qtest_add_func("acpi/q35/tpm-tis", test_acpi_q35_tcg_tpm_tis);
qtest_add_func("acpi/piix4", test_acpi_piix4_tcg);
qtest_add_func("acpi/piix4/bridge", test_acpi_piix4_tcg_bridge);
+ qtest_add_func("acpi/piix4/pci-hotplug/no_root_hotplug",
+ test_acpi_piix4_no_root_hotplug);
+ qtest_add_func("acpi/piix4/pci-hotplug/no_bridge_hotplug",
+ test_acpi_piix4_no_bridge_hotplug);
+ qtest_add_func("acpi/piix4/pci-hotplug/off",
+ test_acpi_piix4_no_acpi_pci_hotplug);
qtest_add_func("acpi/q35", test_acpi_q35_tcg);
qtest_add_func("acpi/q35/bridge", test_acpi_q35_tcg_bridge);
qtest_add_func("acpi/q35/mmio64", test_acpi_q35_tcg_mmio64);
qtest_add_func("acpi/q35/dimmpxm", test_acpi_q35_tcg_dimm_pxm);
qtest_add_func("acpi/piix4/acpihmat", test_acpi_piix4_tcg_acpi_hmat);
qtest_add_func("acpi/q35/acpihmat", test_acpi_q35_tcg_acpi_hmat);
+ qtest_add_func("acpi/microvm", test_acpi_microvm_tcg);
+ if (strcmp(arch, "x86_64") == 0) {
+ qtest_add_func("acpi/microvm/pcie", test_acpi_microvm_pcie_tcg);
+ }
} else if (strcmp(arch, "aarch64") == 0) {
qtest_add_func("acpi/virt", test_acpi_virt_tcg);
qtest_add_func("acpi/virt/numamem", test_acpi_virt_tcg_numamem);