qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables
@ 2017-07-26  9:42 Paolo Bonzini
  2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT Paolo Bonzini
                   ` (2 more replies)
  0 siblings, 3 replies; 6+ messages in thread
From: Paolo Bonzini @ 2017-07-26  9:42 UTC (permalink / raw)
  To: seabios
  Cc: Kevin O'Connor, qemu-devel, lersek, lists, imammedo, mst,
	phil, programmingkidx, kraxel

Old operating systems would like to have a rev1 (ACPI 1.0) FADT, but
new operating systems would like to have rev3 (ACPI 2.0).
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
rev3 FADT.


Paolo Bonzini (2):
  seabios: build RSDT from XSDT
  seabios: create rev1 FADT in compatibility RSDT

 src/fw/paravirt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/std/acpi.h    | 11 +++++++++
 2 files changed, 78 insertions(+), 1 deletion(-)

-- 
2.13.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT
  2017-07-26  9:42 [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Paolo Bonzini
@ 2017-07-26  9:42 ` Paolo Bonzini
  2017-07-26 20:05   ` Michael S. Tsirkin
  2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 2/2] seabios: create rev1 FADT in compatibility RSDT Paolo Bonzini
  2017-08-01 17:32 ` [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Michael S. Tsirkin
  2 siblings, 1 reply; 6+ messages in thread
From: Paolo Bonzini @ 2017-07-26  9:42 UTC (permalink / raw)
  To: seabios
  Cc: Kevin O'Connor, qemu-devel, lersek, lists, imammedo, mst,
	phil, programmingkidx, kraxel

Old operating systems would like to have a rev1 (ACPI 1.0) FADT, but
new operating systems would like to have rev3 (ACPI 2.0).

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

But, edk2 is not able to handle QEMU providing two FADTs and barfs when
it sees the second; edk2 subscribes to the view that the platform code
(meaning not only OVMF, but transitively QEMU's ACPI table builder)
should not handle such hacks; it's common edk2 code that should handle
FADT rev1 vs. rev3 and RSDT vs. XSDT.

These patches make SeaBIOS follow the same model as edk2, the only
difference being how the two identify ACPI tables from the BIOS
linker/loader script.  For SeaBIOS, this task is actually much
simpler since it can just look into the RSDP: if QEMU only
provides an XSDT, SeaBIOS takes care of building the RSDT and
rev1 FADT to satisfy ACPI 1.0-compliant operating systems.

This part makes SeaBIOS build an RSDT out of an existing XSDT,
patching the RSDP to point to the RSDT.

Reviewed-by: Phil Dennis-Jordan <phil@philjordan.eu>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
 src/fw/paravirt.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/std/acpi.h    | 11 +++++++++++
 2 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 5b23d78..927fd75 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,50 @@ 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;
+    RsdpAddr->checksum -= checksum(RsdpAddr,
+				   offsetof(struct rsdp_descriptor, length));
+    RsdpAddr->extended_checksum -= checksum(RsdpAddr,
+					    sizeof(struct rsdp_descriptor));
+
+    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 +231,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..a77b53c 100644
--- a/src/std/acpi.h
+++ b/src/std/acpi.h
@@ -133,6 +133,17 @@ struct rsdt_descriptor_rev1
 } PACKED;
 
 /*
+ * ACPI 2.0 Extended System Description Table (XSDT)
+ */
+#define XSDT_SIGNATURE 0x54445358 // XSDT
+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

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* [Qemu-devel] [seabios PATCH 2/2] seabios: create rev1 FADT in compatibility RSDT
  2017-07-26  9:42 [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Paolo Bonzini
  2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT Paolo Bonzini
@ 2017-07-26  9:42 ` Paolo Bonzini
  2017-08-01 17:32 ` [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Michael S. Tsirkin
  2 siblings, 0 replies; 6+ messages in thread
From: Paolo Bonzini @ 2017-07-26  9:42 UTC (permalink / raw)
  To: seabios
  Cc: Kevin O'Connor, qemu-devel, lersek, lists, imammedo, mst,
	phil, programmingkidx, kraxel

This patch completes the job, presenting a rev1 FADT inside the
compatibility RSDT, so that ACPI 1.0 operating systems such as
Windows 2000 are not broken.

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

diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
index 927fd75..97e2fe3 100644
--- a/src/fw/paravirt.c
+++ b/src/fw/paravirt.c
@@ -148,6 +148,20 @@ 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;
+    // the upper 23 bits are reserved in the rev1 FADT
+    fadt_v1->flags &= 0x1ff;
+    fadt_v1->checksum -= checksum(fadt_v1, fadt_v1->length);
+    return fadt_v1;
+}
+
 static void
 build_compatibility_rsdt(void)
 {
@@ -186,6 +200,11 @@ 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;
+        // for compatibility with Windows 2000, the RSDT should contain
+        // an ACPI 1.0 FADT (table revision 1)
+        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

^ permalink raw reply related	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT
  2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT Paolo Bonzini
@ 2017-07-26 20:05   ` Michael S. Tsirkin
  2017-07-26 20:22     ` Paolo Bonzini
  0 siblings, 1 reply; 6+ messages in thread
From: Michael S. Tsirkin @ 2017-07-26 20:05 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: seabios, Kevin O'Connor, qemu-devel, lersek, lists, imammedo,
	phil, programmingkidx, kraxel

On Wed, Jul 26, 2017 at 11:42:34AM +0200, Paolo Bonzini wrote:
> Old operating systems would like to have a rev1 (ACPI 1.0) FADT, but
> new operating systems would like to have rev3 (ACPI 2.0).
> 
> Since old operating systems do not know about XSDTs, the
> solution is to point the RSDT to a rev1 FADT and the XSDT to a
> rev3 FADT.
> 
> But, edk2 is not able to handle QEMU providing two FADTs and barfs when
> it sees the second; edk2 subscribes to the view that the platform code
> (meaning not only OVMF, but transitively QEMU's ACPI table builder)
> should not handle such hacks; it's common edk2 code that should handle
> FADT rev1 vs. rev3 and RSDT vs. XSDT.

What exactly does it do wrt RSDT?


> These patches make SeaBIOS follow the same model as edk2, the only
> difference being how the two identify ACPI tables from the BIOS
> linker/loader script.  For SeaBIOS, this task is actually much
> simpler since it can just look into the RSDP: if QEMU only
> provides an XSDT, SeaBIOS takes care of building the RSDT and
> rev1 FADT to satisfy ACPI 1.0-compliant operating systems.
> 
> This part makes SeaBIOS build an RSDT out of an existing XSDT,
> patching the RSDP to point to the RSDT.
> 
> Reviewed-by: Phil Dennis-Jordan <phil@philjordan.eu>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  src/fw/paravirt.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/std/acpi.h    | 11 +++++++++++
>  2 files changed, 59 insertions(+), 1 deletion(-)
> 
> diff --git a/src/fw/paravirt.c b/src/fw/paravirt.c
> index 5b23d78..927fd75 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,50 @@ 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;
> +    RsdpAddr->checksum -= checksum(RsdpAddr,
> +				   offsetof(struct rsdp_descriptor, length));
> +    RsdpAddr->extended_checksum -= checksum(RsdpAddr,
> +					    sizeof(struct rsdp_descriptor));
> +
> +    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 +231,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..a77b53c 100644
> --- a/src/std/acpi.h
> +++ b/src/std/acpi.h
> @@ -133,6 +133,17 @@ struct rsdt_descriptor_rev1
>  } PACKED;
>  
>  /*
> + * ACPI 2.0 Extended System Description Table (XSDT)
> + */
> +#define XSDT_SIGNATURE 0x54445358 // XSDT
> +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
> 

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT
  2017-07-26 20:05   ` Michael S. Tsirkin
@ 2017-07-26 20:22     ` Paolo Bonzini
  0 siblings, 0 replies; 6+ messages in thread
From: Paolo Bonzini @ 2017-07-26 20:22 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: seabios, Kevin O'Connor, qemu-devel, lersek, lists, imammedo,
	phil, programmingkidx, kraxel



----- Original Message -----
> From: "Michael S. Tsirkin" <mst@redhat.com>
> To: "Paolo Bonzini" <pbonzini@redhat.com>
> Cc: seabios@seabios.org, "Kevin O'Connor" <kevin@koconnor.net>, qemu-devel@nongnu.org, lersek@redhat.com,
> lists@philjordan.eu, imammedo@redhat.com, phil@philjordan.eu, programmingkidx@gmail.com, kraxel@redhat.com
> Sent: Wednesday, July 26, 2017 10:05:03 PM
> Subject: Re: [seabios PATCH 1/2] seabios: build RSDT from XSDT
> 
> On Wed, Jul 26, 2017 at 11:42:34AM +0200, Paolo Bonzini wrote:
> > Old operating systems would like to have a rev1 (ACPI 1.0) FADT, but
> > new operating systems would like to have rev3 (ACPI 2.0).
> > 
> > Since old operating systems do not know about XSDTs, the
> > solution is to point the RSDT to a rev1 FADT and the XSDT to a
> > rev3 FADT.
> > 
> > But, edk2 is not able to handle QEMU providing two FADTs and barfs when
> > it sees the second; edk2 subscribes to the view that the platform code
> > (meaning not only OVMF, but transitively QEMU's ACPI table builder)
> > should not handle such hacks; it's common edk2 code that should handle
> > FADT rev1 vs. rev3 and RSDT vs. XSDT.
> 
> What exactly does it do wrt RSDT?

It ignores the one produced by QEMU and builds it from scratch.  Same
for RSDP and XSDT.

Paolo

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables
  2017-07-26  9:42 [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Paolo Bonzini
  2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT Paolo Bonzini
  2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 2/2] seabios: create rev1 FADT in compatibility RSDT Paolo Bonzini
@ 2017-08-01 17:32 ` Michael S. Tsirkin
  2 siblings, 0 replies; 6+ messages in thread
From: Michael S. Tsirkin @ 2017-08-01 17:32 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: seabios, Kevin O'Connor, qemu-devel, lersek, lists, imammedo,
	phil, programmingkidx, kraxel

On Wed, Jul 26, 2017 at 11:42:33AM +0200, Paolo Bonzini wrote:
> Old operating systems would like to have a rev1 (ACPI 1.0) FADT, but
> new operating systems would like to have rev3 (ACPI 2.0).
> 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
> rev3 FADT.

So I think for 2.10 Igor's patch is much smaller and only
touches QEMU, I'm inclined to merge just that one.
Let's discuss this after 2.10 is out.

> 
> Paolo Bonzini (2):
>   seabios: build RSDT from XSDT
>   seabios: create rev1 FADT in compatibility RSDT
> 
>  src/fw/paravirt.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>  src/std/acpi.h    | 11 +++++++++
>  2 files changed, 78 insertions(+), 1 deletion(-)
> 
> -- 
> 2.13.3

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2017-08-01 17:32 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-07-26  9:42 [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Paolo Bonzini
2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 1/2] seabios: build RSDT from XSDT Paolo Bonzini
2017-07-26 20:05   ` Michael S. Tsirkin
2017-07-26 20:22     ` Paolo Bonzini
2017-07-26  9:42 ` [Qemu-devel] [seabios PATCH 2/2] seabios: create rev1 FADT in compatibility RSDT Paolo Bonzini
2017-08-01 17:32 ` [Qemu-devel] [seabios PATCH for qemu 2.10 0/2] seabios: build ACPI 1.0-compatible ACPI tables Michael S. Tsirkin

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).