All of lore.kernel.org
 help / color / mirror / Atom feed
From: Paolo Bonzini <pbonzini@redhat.com>
To: Laszlo Ersek <lersek@redhat.com>,
	Phil Dennis-Jordan <lists@philjordan.eu>,
	Igor Mammedov <imammedo@redhat.com>
Cc: Phil Dennis-Jordan <phil@philjordan.eu>,
	ehabkost@redhat.com,
	"qemu-devel@nongnu.org qemu-devel" <qemu-devel@nongnu.org>,
	Programmingkid <programmingkidx@gmail.com>,
	Richard Henderson <rth@twiddle.net>,
	Gerd Hoffmann <kraxel@redhat.com>,
	"seabios@seabios.org" <seabios@seabios.org>
Subject: Re: [Qemu-devel] Commit 77af8a2b95b79699de650965d5228772743efe84 breaks Windows 2000 support
Date: Tue, 25 Jul 2017 19:10:21 +0200	[thread overview]
Message-ID: <a92581c5-87b8-26d0-15d3-33ea6e87d442@redhat.com> (raw)
In-Reply-To: <165445ef-c2fb-f49e-8185-2a8af0e27bf2@redhat.com>

On 25/07/2017 18:23, Paolo Bonzini wrote:
> On 25/07/2017 18:14, Laszlo Ersek wrote:
>>   "No regressions became apparent in tests with a range of Windows
>>    (XP-10)"
>>
>> In theory, w2k falls within that range.
> 
> Nope, Windows 2000 is like NT 5.0, XP is like NT 5.1. :(
> 
> One possibility is to fix it in SeaBIOS instead: if you get a 2.0 FADT
> and an XSDT and no RSDT, it can build an RSDT and a 1.0 FADT itself,
> patching the RSDT to point to it.
> 
> It's a hack, but it's the only place I see to make it "just work".  And
> it could be extended nicely in the future.
> 
> All QEMU would have to do is to provide an XSDT _instead_ of an RSDT.

Completely untested code follows.  Machine type compatibility code 
should not be necessary because new QEMU always starts with a new BIOS.

Not sure I'll have much time for this in the next few days, so help
is appreciated.

Paolo

QEMU:

diff --git a/hw/acpi/aml-build.c b/hw/acpi/aml-build.c
index 36a6cc450e..ea750d54d9 100644
--- a/hw/acpi/aml-build.c
+++ b/hw/acpi/aml-build.c
@@ -1573,33 +1573,6 @@ void acpi_build_tables_cleanup(AcpiBuildTables *tables, bool mfre)
     g_array_free(tables->vmgenid, mfre);
 }
 
-/* Build rsdt table */
-void
-build_rsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
-           const char *oem_id, const char *oem_table_id)
-{
-    int i;
-    unsigned rsdt_entries_offset;
-    AcpiRsdtDescriptorRev1 *rsdt;
-    const unsigned table_data_len = (sizeof(uint32_t) * table_offsets->len);
-    const unsigned rsdt_entry_size = sizeof(rsdt->table_offset_entry[0]);
-    const size_t rsdt_len = sizeof(*rsdt) + table_data_len;
-
-    rsdt = acpi_data_push(table_data, rsdt_len);
-    rsdt_entries_offset = (char *)rsdt->table_offset_entry - table_data->data;
-    for (i = 0; i < table_offsets->len; ++i) {
-        uint32_t ref_tbl_offset = g_array_index(table_offsets, uint32_t, i);
-        uint32_t rsdt_entry_offset = rsdt_entries_offset + rsdt_entry_size * i;
-
-        /* rsdt->table_offset_entry to be filled by Guest linker */
-        bios_linker_loader_add_pointer(linker,
-            ACPI_BUILD_TABLE_FILE, rsdt_entry_offset, rsdt_entry_size,
-            ACPI_BUILD_TABLE_FILE, ref_tbl_offset);
-    }
-    build_header(linker, table_data,
-                 (void *)rsdt, "RSDT", rsdt_len, 1, oem_id, oem_table_id);
-}
-
 /* Build xsdt table */
 void
 build_xsdt(GArray *table_data, BIOSLinker *linker, GArray *table_offsets,
diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 6b7bade183..ad00f6affd 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -2557,12 +2557,12 @@ build_amd_iommu(GArray *table_data, BIOSLinker *linker)
 }
 
 static GArray *
-build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
+build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned xsdt_tbl_offset)
 {
     AcpiRsdpDescriptor *rsdp = acpi_data_push(rsdp_table, sizeof *rsdp);
-    unsigned rsdt_pa_size = sizeof(rsdp->rsdt_physical_address);
-    unsigned rsdt_pa_offset =
-        (char *)&rsdp->rsdt_physical_address - rsdp_table->data;
+    unsigned xsdt_pa_size = sizeof(rsdp->xsdt_physical_address);
+    unsigned xsdt_pa_offset =
+        (char *)&rsdp->xsdt_physical_address - rsdp_table->data;
 
     bios_linker_loader_alloc(linker, ACPI_BUILD_RSDP_FILE, rsdp_table, 16,
                              true /* fseg memory */);
@@ -2571,8 +2571,8 @@ build_rsdp(GArray *rsdp_table, BIOSLinker *linker, unsigned rsdt_tbl_offset)
     memcpy(rsdp->oem_id, ACPI_BUILD_APPNAME6, 6);
     /* Address to be filled by Guest linker */
     bios_linker_loader_add_pointer(linker,
-        ACPI_BUILD_RSDP_FILE, rsdt_pa_offset, rsdt_pa_size,
-        ACPI_BUILD_TABLE_FILE, rsdt_tbl_offset);
+        ACPI_BUILD_RSDP_FILE, xsdt_pa_offset, xsdt_pa_size,
+        ACPI_BUILD_TABLE_FILE, xsdt_tbl_offset);
 
     /* Checksum to be filled by Guest linker */
     bios_linker_loader_add_checksum(linker, ACPI_BUILD_RSDP_FILE,
@@ -2621,7 +2621,7 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     PCMachineState *pcms = PC_MACHINE(machine);
     PCMachineClass *pcmc = PC_MACHINE_GET_CLASS(pcms);
     GArray *table_offsets;
-    unsigned facs, dsdt, rsdt, fadt;
+    unsigned facs, dsdt, xsdt, fadt;
     AcpiPmInfo pm;
     AcpiMiscInfo misc;
     AcpiMcfgInfo mcfg;
@@ -2730,12 +2730,12 @@ void acpi_build(AcpiBuildTables *tables, MachineState *machine)
     }
 
     /* RSDT is pointed to by RSDP */
-    rsdt = tables_blob->len;
-    build_rsdt(tables_blob, tables->linker, table_offsets,
+    xsdt = tables_blob->len;
+    build_xsdt(tables_blob, tables->linker, table_offsets,
                slic_oem.id, slic_oem.table_id);
 
     /* RSDP is in FSEG memory, so allocate it separately */
-    build_rsdp(tables->rsdp, tables->linker, rsdt);
+    build_rsdp(tables->rsdp, tables->linker, xsdt);
 
     /* We'll expose it all to Guest so we want to reduce
      * chance of size changes.


SeaBIOS:

>From 73b0facdb7349f5dbf24dc675647b68eeeec0ff4 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 25 Jul 2017 18:50:19 +0200
Subject: [PATCH 1/2] seabios: build RSDT from XSDT

Old operating systems would like to have a v1 FADT, but new
operating systems would like to have v3.

Since old operating systems do not know about XSDTs, the
solution is to point the RSDT to a v1 FADT and the XSDT to a
v3 FADT.

But, OVMF is not able to do that and barfs when it sees the
second FADT---plus really it's only BIOS operating systems
such as win2k that complain.  So instead: 1) make QEMU provide
an XSDT only; 2) build the RSDT and v1 FADT in SeaBIOS.

This patch makes SeaBIOS build an RSDT out of an existing XSDT.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 src/fw/paravirt.c | 45 ++++++++++++++++++++++++++++++++++++++++++++-
 src/std/acpi.h    | 11 +++++++++++
 2 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 5b23d78..19a4abe 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -25,6 +25,7 @@
 #include "x86.h" // cpuid
 #include "xen.h" // xen_biostable_setup
 #include "stacks.h" // yield
+#include "std/acpi.h"
 
 // Amount of continuous ram under 4Gig
 u32 RamSize;
@@ -147,6 +148,46 @@ static void msr_feature_control_setup(void)
         wrmsr_smp(MSR_IA32_FEATURE_CONTROL, feature_control_bits);
 }
 
+static void
+build_compatibility_rsdt(void)
+{
+    if (RsdpAddr->rsdt_physical_address)
+        return;
+
+    u64 xsdt_addr = RsdpAddr->xsdt_physical_address;
+    if (xsdt_addr & ~0xffffffffULL)
+        return;
+
+    struct xsdt_descriptor_rev1 *xsdt = (void*)(u32)xsdt_addr;
+    void *end = (void*)xsdt + xsdt->length;
+    struct rsdt_descriptor_rev1 *rsdt;
+    int rsdt_size = offsetof(struct rsdt_descriptor_rev1, table_offset_entry[0]);
+    int i;
+    for (i=0; (void*)&xsdt->table_offset_entry[i] < end; i++) {
+        u64 tbl_addr = xsdt->table_offset_entry[i];
+        if (!tbl_addr || (tbl_addr & ~0xffffffffULL))
+            continue;
+        rsdt_size += 4;
+    }
+
+    rsdt = malloc_high(rsdt_size);
+    RsdpAddr->rsdt_physical_address = (u32)rsdt;
+
+    memcpy(rsdt, xsdt, sizeof(struct acpi_table_header));
+    rsdt->signature = RSDT_SIGNATURE;
+    rsdt->length = rsdt_size;
+    rsdt->revision = 1;
+    int j;
+    for (i=j=0; (void*)&xsdt->table_offset_entry[i] < end; i++) {
+        u64 tbl_addr = xsdt->table_offset_entry[i];
+        if (!tbl_addr || (tbl_addr & ~0xffffffffULL))
+            continue;
+        rsdt->table_offset_entry[j++] = (u32)tbl_addr;
+    }
+
+    rsdt->checksum -= checksum(rsdt, rsdt_size);
+}
+
 void
 qemu_platform_setup(void)
 {
@@ -186,8 +227,10 @@ qemu_platform_setup(void)
 
         RsdpAddr = find_acpi_rsdp();
 
-        if (RsdpAddr)
+        if (RsdpAddr) {
+            build_compatibility_rsdt();
             return;
+        }
 
         /* If present, loader should have installed an RSDP.
          * Not installed? We might still be able to continue
diff --git a/src/std/acpi.h b/src/std/acpi.h
index c2ea707..caf5e7e 100644
--- a/src/std/acpi.h
+++ b/src/std/acpi.h
@@ -133,6 +133,17 @@ struct rsdt_descriptor_rev1
 } PACKED;
 
 /*
+ * ACPI 2.0 Root System Description Table (RSDT)
+ */
+#define XSDT_SIGNATURE 0x54445358 // RSDT
+struct xsdt_descriptor_rev1
+{
+    ACPI_TABLE_HEADER_DEF       /* ACPI common table header */
+    u64 table_offset_entry[0];  /* Array of pointers to other */
+    /* ACPI tables */
+} PACKED;
+
+/*
  * ACPI 1.0 Firmware ACPI Control Structure (FACS)
  */
 #define FACS_SIGNATURE 0x53434146 // FACS
-- 
2.13.3


>From 46c7a296d27bd487cfd89a40973b1e61426dfbd0 Mon Sep 17 00:00:00 2001
From: Paolo Bonzini <pbonzini@redhat.com>
Date: Tue, 25 Jul 2017 18:59:20 +0200
Subject: [PATCH 2/2] seabios: create v1 FADT in compatibility RSDT

This patch presents a v1 FADT inside the compatibility RSDT, so
that old operating systems are not broken.

Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 src/fw/paravirt.c | 18 +++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 19a4abe..a9b9e80 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -148,6 +148,18 @@ static void msr_feature_control_setup(void)
         wrmsr_smp(MSR_IA32_FEATURE_CONTROL, feature_control_bits);
 }
 
+static void*
+build_rev1_fadt(struct fadt_descriptor_rev1 *fadt_v3)
+{
+    struct fadt_descriptor_rev1 *fadt_v1 = malloc_high(sizeof *fadt_v1);
+
+    memcpy(fadt_v1, fadt_v3, sizeof *fadt_v1);
+    fadt_v1->length = sizeof *fadt_v1;
+    fadt_v1->revision = 1;
+    fadt_v1->checksum -= checksum(fadt_v1, fadt_v1->length);
+    return fadt_v1;
+}
+
 static void
 build_compatibility_rsdt(void)
 {
@@ -182,6 +194,12 @@ build_compatibility_rsdt(void)
         u64 tbl_addr = xsdt->table_offset_entry[i];
         if (!tbl_addr || (tbl_addr & ~0xffffffffULL))
             continue;
+        struct acpi_table_header *tbl = (void*)(u32)tbl_addr;
+        /* The RSDT should only have an ACPI 1.0 FADT according to
+         * the spec.
+         */
+        if (tbl->signature == FACP_SIGNATURE && tbl->revision > 1)
+            tbl_addr = (u32)build_rev1_fadt((void *)tbl);
         rsdt->table_offset_entry[j++] = (u32)tbl_addr;
     }
 
-- 
2.13.3

  reply	other threads:[~2017-07-25 17:10 UTC|newest]

Thread overview: 44+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-20 16:40 [Qemu-devel] Commit 77af8a2b95b79699de650965d5228772743efe84 breaks Windows 2000 support Programmingkid
2017-07-20 19:29 ` Phil Dennis-Jordan
2017-07-21  0:00   ` Programmingkid
2017-07-21  9:06   ` Igor Mammedov
2017-07-21  9:11     ` Phil Dennis-Jordan
2017-07-21  9:23     ` Daniel P. Berrange
2017-07-21 12:34       ` Igor Mammedov
2017-07-21 18:29         ` Phil Dennis-Jordan
2017-07-25 16:14           ` Laszlo Ersek
2017-07-25 16:23             ` Paolo Bonzini
2017-07-25 17:10               ` Paolo Bonzini [this message]
2017-07-25 21:25                 ` Phil Dennis-Jordan
2017-07-26  8:53                   ` Paolo Bonzini
2017-07-26 11:42                     ` Laszlo Ersek
2017-07-26 12:06                       ` Paolo Bonzini
2017-07-25 22:01                 ` [Qemu-devel] [SeaBIOS] " Kevin O'Connor
2017-07-26  7:20                   ` Paolo Bonzini
2017-07-26 19:12                     ` Kevin O'Connor
2017-07-26 20:21                       ` Paolo Bonzini
2017-07-27  8:39                         ` Gerd Hoffmann
2017-07-27 12:26                           ` Paolo Bonzini
2017-07-27 14:59                         ` Kevin O'Connor
2017-07-27 17:46                           ` Laszlo Ersek
2017-07-28  6:57                             ` Gerd Hoffmann
2017-07-26 13:08               ` [Qemu-devel] " Igor Mammedov
2017-07-26 13:10                 ` Paolo Bonzini
2017-07-26 13:30                   ` Igor Mammedov
2017-07-26 13:33                     ` Paolo Bonzini
2017-07-26 13:43                       ` Igor Mammedov
2017-07-26 14:04                         ` Daniel P. Berrange
2017-07-26 16:13                           ` Michael S. Tsirkin
2017-07-26 13:57                     ` Michael S. Tsirkin
2017-07-24 12:45     ` Gerd Hoffmann
2017-07-24 16:43     ` John Snow
2017-07-24 17:30       ` Programmingkid
2017-07-21  9:20   ` Daniel P. Berrange
2017-07-21  9:46     ` Igor Mammedov
2017-07-21 10:39       ` Phil Dennis-Jordan
2017-07-21 10:50       ` BALATON Zoltan
2017-07-21 11:46         ` Phil Dennis-Jordan
2017-07-21 17:17           ` BALATON Zoltan
     [not found] <mailman.85963.1500629384.22737.qemu-devel@nongnu.org>
2017-07-21 16:00 ` Programmingkid
     [not found] <mailman.86860.1501079288.22738.qemu-devel@nongnu.org>
2017-07-27  2:38 ` Programmingkid
2017-07-27  3:23 Programmingkid

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=a92581c5-87b8-26d0-15d3-33ea6e87d442@redhat.com \
    --to=pbonzini@redhat.com \
    --cc=ehabkost@redhat.com \
    --cc=imammedo@redhat.com \
    --cc=kraxel@redhat.com \
    --cc=lersek@redhat.com \
    --cc=lists@philjordan.eu \
    --cc=phil@philjordan.eu \
    --cc=programmingkidx@gmail.com \
    --cc=qemu-devel@nongnu.org \
    --cc=rth@twiddle.net \
    --cc=seabios@seabios.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.