On Fri, 13 Mar 2020 16:50:08 +0200 Liran Alon <liran.a...@oracle.com> wrote:
> 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 <elad.ga...@oracle.com> > Signed-off-by: Liran Alon <liran.a...@oracle.com> Reviewed-by: Igor Mammedov <imamm...@redhat.com> > --- > 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 9c4e46fa7466..1c3a2e8fcb3c 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); this should work but, I'd use (1UL << 1) if you'll need to respin > + > + 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);