From 14cda3503dc00754bab9ce6c688ea21f791c4a33 Mon Sep 17 00:00:00 2001 From: Liran Alon Date: Fri, 13 Mar 2020 16:50:08 +0200 Subject: [PATCH] acpi: Add Windows ACPI Emulated Device Table (WAET) Microsoft introduced this ACPI table to avoid Windows guests performing various workarounds for device erratas. As the virtual device emulated by VMM may not have the errata. Currently, WAET allows hypervisor to inform guest about two specific behaviors: One for RTC and the other for ACPI PM timer. Support for WAET have been introduced since Windows Vista. This ACPI table is also exposed by other common hypervisors by default, including: VMware, GCP and AWS. This patch adds WAET ACPI Table to QEMU. We set "ACPI PM timer good" bit in "Emualted Device Flags" field to indicate that the ACPI PM timer has been enhanced to not require multiple reads to obtain a reliable value. This results in improving the performance of Windows guests that use ACPI PM timer by avoiding unnecessary VMExits caused by these multiple reads. Co-developed-by: Elad Gabay Signed-off-by: Liran Alon Message-Id: <20200313145009.144820-3-liran.alon@oracle.com> Reviewed-by: Michael S. Tsirkin Signed-off-by: Michael S. Tsirkin Reviewed-by: Igor Mammedov --- hw/i386/acpi-build.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c index 7d880bec4a..2e15f6848e 100644 --- a/hw/i386/acpi-build.c +++ b/hw/i386/acpi-build.c @@ -2512,6 +2512,34 @@ build_dmar_q35(GArray *table_data, BIOSLinker *linker) build_header(linker, table_data, (void *)(table_data->data + dmar_start), "DMAR", table_data->len - dmar_start, 1, NULL, NULL); } + +/* + * Windows ACPI Emulated Devices Table + * (Version 1.0 - April 6, 2009) + * Spec: http://download.microsoft.com/download/7/E/7/7E7662CF-CBEA-470B-A97E-CE7CE0D98DC2/WAET.docx + * + * Helpful to speedup Windows guests and ignored by others. + */ +static void +build_waet(GArray *table_data, BIOSLinker *linker) +{ + int waet_start = table_data->len; + + /* WAET header */ + acpi_data_push(table_data, sizeof(AcpiTableHeader)); + /* + * Set "ACPI PM timer good" flag. + * + * Tells Windows guests that our ACPI PM timer is reliable in the + * sense that guest can read it only once to obtain a reliable value. + * Which avoids costly VMExits caused by guest re-reading it unnecessarily. + */ + build_append_int_noprefix(table_data, 1 << 1 /* ACPI PM timer good */, 4); + + build_header(linker, table_data, (void *)(table_data->data + waet_start), + "WAET", table_data->len - waet_start, 1, NULL, NULL); +} + /* * IVRS table as specified in AMD IOMMU Specification v2.62, Section 5.2 * accessible here http://support.amd.com/TechDocs/48882_IOMMU.pdf @@ -2859,6 +2887,9 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine) machine->nvdimms_state, machine->ram_slots); } + acpi_add_table(table_offsets, tables_blob); + build_waet(tables_blob, tables->linker); + /* Add tables supplied by user (if any) */ for (u = acpi_table_first(); u; u = acpi_table_next(u)) { unsigned len = acpi_table_len(u); -- 2.11.0