Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Alex Bennée

Shannon Zhao zhaoshengl...@huawei.com writes:

 From: Shannon Zhao shannon.z...@linaro.org

 RSDT points to other tables FADT, MADT, GTDT.

 Signed-off-by: Shannon Zhao zhaoshengl...@huawei.com
 Signed-off-by: Shannon Zhao shannon.z...@linaro.org
 ---
  hw/arm/virt-acpi-build.c | 27 +++
  1 file changed, 27 insertions(+)

 diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
 index a7aba75..85e84b1 100644
 --- a/hw/arm/virt-acpi-build.c
 +++ b/hw/arm/virt-acpi-build.c
 @@ -176,6 +176,30 @@ static void acpi_dsdt_add_virtio(Aml *scope, const 
 hwaddr *mmio_addrs,
  }
  }
  
 +/* RSDT */
 +static void
 +build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
 +{
 +AcpiRsdtDescriptorRev1 *rsdt;
 +size_t rsdt_len;
 +int i;
 +
 +rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets-len;

You should use explicit brackets to be unambiguous:

   rsdt_len = sizeof(*rsdt) + (sizeof(uint32_t) * table_offsets-len);

 +rsdt = acpi_data_push(table_data, rsdt_len);
 +memcpy(rsdt-table_offset_entry, table_offsets-data,
 +   sizeof(uint32_t) * table_offsets-len);

Or perhaps split the sizes:

   const int table_data_len = (sizeof(uint32_t) * table_offsets-len);

   rsdt_len = sizeof(*rsdt) + table_data_len;
   rsdt = acpi_data_push(table_data, rsdt_len);
   memcpy(rsdt-table_offset_entry, table_offsets-data, table_data_len)

Maybe?

 +for (i = 0; i  table_offsets-len; ++i) {
 +/* rsdt-table_offset_entry to be filled by Guest linker */
 +bios_linker_loader_add_pointer(linker,
 +   ACPI_BUILD_TABLE_FILE,
 +   ACPI_BUILD_TABLE_FILE,
 +   table_data, 
 rsdt-table_offset_entry[i],
 +   sizeof(uint32_t));

Why are these pointers always 32 bit? Can they ever be 64 bit?

 +}
 +build_header(linker, table_data,
 + (void *)rsdt, RSDT, rsdt_len, 1);
 +}
 +
  /* GTDT */
  static void
  build_gtdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
 @@ -348,6 +372,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
 AcpiBuildTables *tables)
  acpi_add_table(table_offsets, tables_blob);
  build_gtdt(tables_blob, tables-linker, guest_info);
  
 +/* RSDT is pointed to by RSDP */
 +build_rsdt(tables_blob, tables-linker, table_offsets);
 +
  /* Cleanup memory that's no longer used. */
  g_array_free(table_offsets, true);
  }

-- 
Alex Bennée



Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Igor Mammedov
On Thu, 09 Apr 2015 13:50:52 +0100
Alex Bennée alex.ben...@linaro.org wrote:

 
 Shannon Zhao zhaoshengl...@huawei.com writes:
 
  From: Shannon Zhao shannon.z...@linaro.org
 
  RSDT points to other tables FADT, MADT, GTDT.
 
  Signed-off-by: Shannon Zhao zhaoshengl...@huawei.com
  Signed-off-by: Shannon Zhao shannon.z...@linaro.org
  ---
   hw/arm/virt-acpi-build.c | 27 +++
   1 file changed, 27 insertions(+)
 
  diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
  index a7aba75..85e84b1 100644
  --- a/hw/arm/virt-acpi-build.c
  +++ b/hw/arm/virt-acpi-build.c
  @@ -176,6 +176,30 @@ static void acpi_dsdt_add_virtio(Aml *scope, const 
  hwaddr *mmio_addrs,
   }
   }
   
  +/* RSDT */
  +static void
  +build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
this function looks like exact copy of x86 impl.,
could you reuse that?

  +{
  +AcpiRsdtDescriptorRev1 *rsdt;
  +size_t rsdt_len;
  +int i;
  +
  +rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets-len;
 
 You should use explicit brackets to be unambiguous:
 
rsdt_len = sizeof(*rsdt) + (sizeof(uint32_t) * table_offsets-len);
 
  +rsdt = acpi_data_push(table_data, rsdt_len);
  +memcpy(rsdt-table_offset_entry, table_offsets-data,
  +   sizeof(uint32_t) * table_offsets-len);
 
 Or perhaps split the sizes:
 
const int table_data_len = (sizeof(uint32_t) * table_offsets-len);
 
rsdt_len = sizeof(*rsdt) + table_data_len;
rsdt = acpi_data_push(table_data, rsdt_len);
memcpy(rsdt-table_offset_entry, table_offsets-data, table_data_len)
 
 Maybe?
 
  +for (i = 0; i  table_offsets-len; ++i) {
  +/* rsdt-table_offset_entry to be filled by Guest linker */
  +bios_linker_loader_add_pointer(linker,
  +   ACPI_BUILD_TABLE_FILE,
  +   ACPI_BUILD_TABLE_FILE,
  +   table_data, 
  rsdt-table_offset_entry[i],
  +   sizeof(uint32_t));
 
 Why are these pointers always 32 bit? Can they ever be 64 bit?
Laszlo, can you confirm that UEFI puts APCI tables below 4G address space?


 
  +}
  +build_header(linker, table_data,
  + (void *)rsdt, RSDT, rsdt_len, 1);
  +}
  +
   /* GTDT */
   static void
   build_gtdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
  @@ -348,6 +372,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
  AcpiBuildTables *tables)
   acpi_add_table(table_offsets, tables_blob);
   build_gtdt(tables_blob, tables-linker, guest_info);
   
  +/* RSDT is pointed to by RSDP */
  +build_rsdt(tables_blob, tables-linker, table_offsets);
  +
   /* Cleanup memory that's no longer used. */
   g_array_free(table_offsets, true);
   }
 




Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Laszlo Ersek
On 04/09/15 18:03, Peter Maydell wrote:
 On 9 April 2015 at 17:00, Laszlo Ersek ler...@redhat.com wrote:
 On 04/09/15 15:59, Peter Maydell wrote:
 On 9 April 2015 at 14:51, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 9 Apr 2015 14:27:58 +0100
 Peter Maydell peter.mayd...@linaro.org wrote:

 On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 09 Apr 2015 13:50:52 +0100
 Alex Bennée alex.ben...@linaro.org wrote:


 Shannon Zhao zhaoshengl...@huawei.com writes:
 +for (i = 0; i  table_offsets-len; ++i) {
 +/* rsdt-table_offset_entry to be filled by Guest linker */
 +bios_linker_loader_add_pointer(linker,
 +   ACPI_BUILD_TABLE_FILE,
 +   ACPI_BUILD_TABLE_FILE,
 +   table_data, 
 rsdt-table_offset_entry[i],
 +   sizeof(uint32_t));

 Why are these pointers always 32 bit? Can they ever be 64 bit?
 Laszlo, can you confirm that UEFI puts APCI tables below 4G address
 space?

 I confirmed that before, in the v2 discussion:

 http://thread.gmane.org/gmane.comp.emulators.qemu/316670/focus=317560

 But in fact the RSDT / XSDT that QEMU exports for UEFI doesn't matter.
 
 If this table is never used, presumably we should just
 not generate it at all, then?

Unfortunately, this is not the case. In order to identify ACPI tables *at all* 
in UEFI, I need relocate pointer commands for pointers that point to those 
tables. And those pointers must *reside* somewhere, in some blob.

Here's how the relocate pointer command is defined in edk2 
(OvmfPkg/AcpiPlatformDxe/QemuLoader.h):

//
// QemuLoaderCmdAddPointer: the bytes at
// [PointerOffset..PointerOffset+PointerSize) in the file PointerFile contain a
// relative pointer (an offset) into PointeeFile. Increment the relative
// pointer's value by the base address of where PointeeFile's contents have
// been placed (when QemuLoaderCmdAllocate has been executed for PointeeFile).
//
typedef struct {
  UINT8  PointerFile[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
  UINT8  PointeeFile[QEMU_LOADER_FNAME_SIZE]; // NUL-terminated
  UINT32 PointerOffset;
  UINT8  PointerSize; // one of 1, 2, 4, 8
} QEMU_LOADER_ADD_POINTER;

In the qemu tree, see COMMAND_ADD_POINTER in hw/acpi/bios-linker-loader.c, 
for the same. (I rewrote the types and the comments in edk2 from scratch, both 
for coding style reasons and for clearer documentation.)

... To be clear: the top-level pointers must exist somewhere (in some blob), 
because that helps edk2 find the tables (in some other blobs). However, the 
top-level pointers themselves don't need to reside in any ACPI table (RSDT, 
XSDT); they can just live in an otherwise unreferenced portion of one of the 
blobs.

But, IMO, implementing that wouldn't be much easier (and it would certainly be 
uglier) than composing a correct RSDT or XSDT. The latter would also keep the 
similarity with the x86 SeaBIOS case (where the RSDT is a hard requirement).

Thanks
Laszlo



Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Laszlo Ersek
On 04/09/15 15:59, Peter Maydell wrote:
 On 9 April 2015 at 14:51, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 9 Apr 2015 14:27:58 +0100
 Peter Maydell peter.mayd...@linaro.org wrote:

 On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 09 Apr 2015 13:50:52 +0100
 Alex Bennée alex.ben...@linaro.org wrote:


 Shannon Zhao zhaoshengl...@huawei.com writes:
 +for (i = 0; i  table_offsets-len; ++i) {
 +/* rsdt-table_offset_entry to be filled by Guest linker */
 +bios_linker_loader_add_pointer(linker,
 +   ACPI_BUILD_TABLE_FILE,
 +   ACPI_BUILD_TABLE_FILE,
 +   table_data, 
 rsdt-table_offset_entry[i],
 +   sizeof(uint32_t));

 Why are these pointers always 32 bit? Can they ever be 64 bit?
 Laszlo, can you confirm that UEFI puts APCI tables below 4G address
 space?

I confirmed that before, in the v2 discussion:

http://thread.gmane.org/gmane.comp.emulators.qemu/316670/focus=317560

But in fact the RSDT / XSDT that QEMU exports for UEFI doesn't matter.
See below.

 In the general case you can't guarantee that there will
 be any RAM at all below the 4G point. (The virt board
 isn't like that, obviously, but I believe there's real
 hardware out there that's designed that way.) I don't
 think we should have any 32 bit assumptions in the
 code at all -- pointer values should always be 64 bits
 everywhere.

 then that forces us to use xsdt instead of 32-bit rsdt

 Does that matter much?

I can mention two points here.


(1) See this kernel patch:

http://thread.gmane.org/gmane.linux.acpi.devel/74369/focus=1915858

 +The ACPI core will ignore any provided RSDT (Root System Description Table).
 +RSDTs have been deprecated and are ignored on arm64 since they only allow
 +for 32-bit addresses.

So you could argue that providing an XSDT instead of an RSDT is
justified by this alone.


(2) the ACPI linker/loader client in edk2 (used for both OVMF and AAVMF)
*does* restrict initial allocations to under 4GB. This is a super hairy
subject, but I'll try to summarize it quickly.

The ACPI linker/loader interface was originally designed for SeaBIOS.
The central structure of the interface is a command table, which
contains three kinds of commands:
(a) allocate blob (which includes download blob as well),
(b) relocate pointer (also known as update pointer), and
(c) checksum blob segment.

Importantly, the allocate command comes with allocation hints; it can
instruct the firmware to allocate the blob in some specific zone.

So, the general process (as designed) is something like this:
- The firmware allocates and downloads the blobs -- the allocate
  commands always come first in the table. Each blob can contain several
  ACPI tables, in any kind of arrangement.

- Then the relocate pointer commands are processed (simply because
  they come later in the command table, that's guaranteed), which update
  pointers in some tables (residing in some blobs) to some other tables
  (residing in some other, or the same, blob(s)). In more detail, the
  pointers in the tables in the blobs are pre-initialized with relative
  offsets (into other blobs), and the relocation means that these
  relative offsets are made absolute -- they are incremented with the
  actual allocation base addresses that are the results of the
  allocation command processing (see previous step).

- Finally (in fact, intermixed with relocate pointer commands),
  checksums are updated.

The idea is that after the initial allocations, everything is processed
*in place*. (This is what SeaBIOS does.) Because pointer fields, updated
by the relocate pointer commands (which basically mean increments by
actual blob base addresses) can come in various sizes (1, 2, 4, 8
bytes), the allocation commands must take care to instruct the firmware
to allocate the target blobs low enough so that the referring
pointers can accommodate these actual base addresses.

All fine; again, SeaBIOS does exactly this; the important thing to note
is that everything is processed, and then left for the runtime OS, *in
place*.

And then UEFI / edk2 came along. :)

The problem with UEFI is that you are not supposed to just throw a bunch
of binary stuff into RAM. Instead, the RSD PTR table needs to be linked
into the UEFI system config table, plus each table needs to be installed
*individually*, by passing it to EFI_ACPI_TABLE_PROTOCOL.InstallTable().

The first requirement is actually a relaxation -- the RSD PTR can be
anywhere in memory, it doesn't need to be low. However, the second
requirement is a huge pain, because it doesn't match the design of the
ACPI linker/loader interface. EFI_ACPI_TABLE_PROTOCOL is smart about
the specification, and knows what to allocate where -- it copies tables,
links the copies together, checksums them, handles the RSD PTR
internally, and so on; but it does need to *receive* 

Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Igor Mammedov
On Thu, 9 Apr 2015 14:59:09 +0100
Peter Maydell peter.mayd...@linaro.org wrote:

 On 9 April 2015 at 14:51, Igor Mammedov imamm...@redhat.com wrote:
  On Thu, 9 Apr 2015 14:27:58 +0100
  Peter Maydell peter.mayd...@linaro.org wrote:
 
  On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
   On Thu, 09 Apr 2015 13:50:52 +0100
   Alex Bennée alex.ben...@linaro.org wrote:
  
  
   Shannon Zhao zhaoshengl...@huawei.com writes:
+for (i = 0; i  table_offsets-len; ++i) {
+/* rsdt-table_offset_entry to be filled by Guest linker */
+bios_linker_loader_add_pointer(linker,
+   ACPI_BUILD_TABLE_FILE,
+   ACPI_BUILD_TABLE_FILE,
+   table_data, 
rsdt-table_offset_entry[i],
+   sizeof(uint32_t));
  
   Why are these pointers always 32 bit? Can they ever be 64 bit?
   Laszlo, can you confirm that UEFI puts APCI tables below 4G address 
   space?
 
  In the general case you can't guarantee that there will
  be any RAM at all below the 4G point. (The virt board
  isn't like that, obviously, but I believe there's real
  hardware out there that's designed that way.) I don't
  think we should have any 32 bit assumptions in the
  code at all -- pointer values should always be 64 bits
  everywhere.
 
  then that forces us to use xsdt instead of 32-bit rsdt
 
 Does that matter much?
not much, using rsdt would allow to share this code with x86.

also having tables below 4Gb in rsdt would make life of
32 bit guests easier, not that there are such guests now and may be
there wouldn't be any.

 
 -- PMM
 




Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Peter Maydell
On 9 April 2015 at 17:00, Laszlo Ersek ler...@redhat.com wrote:
 On 04/09/15 15:59, Peter Maydell wrote:
 On 9 April 2015 at 14:51, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 9 Apr 2015 14:27:58 +0100
 Peter Maydell peter.mayd...@linaro.org wrote:

 On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 09 Apr 2015 13:50:52 +0100
 Alex Bennée alex.ben...@linaro.org wrote:


 Shannon Zhao zhaoshengl...@huawei.com writes:
 +for (i = 0; i  table_offsets-len; ++i) {
 +/* rsdt-table_offset_entry to be filled by Guest linker */
 +bios_linker_loader_add_pointer(linker,
 +   ACPI_BUILD_TABLE_FILE,
 +   ACPI_BUILD_TABLE_FILE,
 +   table_data, 
 rsdt-table_offset_entry[i],
 +   sizeof(uint32_t));

 Why are these pointers always 32 bit? Can they ever be 64 bit?
 Laszlo, can you confirm that UEFI puts APCI tables below 4G address
 space?

 I confirmed that before, in the v2 discussion:

 http://thread.gmane.org/gmane.comp.emulators.qemu/316670/focus=317560

 But in fact the RSDT / XSDT that QEMU exports for UEFI doesn't matter.

If this table is never used, presumably we should just
not generate it at all, then?

-- PMM



Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Peter Maydell
On 9 April 2015 at 14:51, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 9 Apr 2015 14:27:58 +0100
 Peter Maydell peter.mayd...@linaro.org wrote:

 On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
  On Thu, 09 Apr 2015 13:50:52 +0100
  Alex Bennée alex.ben...@linaro.org wrote:
 
 
  Shannon Zhao zhaoshengl...@huawei.com writes:
   +for (i = 0; i  table_offsets-len; ++i) {
   +/* rsdt-table_offset_entry to be filled by Guest linker */
   +bios_linker_loader_add_pointer(linker,
   +   ACPI_BUILD_TABLE_FILE,
   +   ACPI_BUILD_TABLE_FILE,
   +   table_data, 
   rsdt-table_offset_entry[i],
   +   sizeof(uint32_t));
 
  Why are these pointers always 32 bit? Can they ever be 64 bit?
  Laszlo, can you confirm that UEFI puts APCI tables below 4G address space?

 In the general case you can't guarantee that there will
 be any RAM at all below the 4G point. (The virt board
 isn't like that, obviously, but I believe there's real
 hardware out there that's designed that way.) I don't
 think we should have any 32 bit assumptions in the
 code at all -- pointer values should always be 64 bits
 everywhere.

 then that forces us to use xsdt instead of 32-bit rsdt

Does that matter much?

-- PMM



Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Peter Maydell
On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
 On Thu, 09 Apr 2015 13:50:52 +0100
 Alex Bennée alex.ben...@linaro.org wrote:


 Shannon Zhao zhaoshengl...@huawei.com writes:
  +for (i = 0; i  table_offsets-len; ++i) {
  +/* rsdt-table_offset_entry to be filled by Guest linker */
  +bios_linker_loader_add_pointer(linker,
  +   ACPI_BUILD_TABLE_FILE,
  +   ACPI_BUILD_TABLE_FILE,
  +   table_data, 
  rsdt-table_offset_entry[i],
  +   sizeof(uint32_t));

 Why are these pointers always 32 bit? Can they ever be 64 bit?
 Laszlo, can you confirm that UEFI puts APCI tables below 4G address space?

In the general case you can't guarantee that there will
be any RAM at all below the 4G point. (The virt board
isn't like that, obviously, but I believe there's real
hardware out there that's designed that way.) I don't
think we should have any 32 bit assumptions in the
code at all -- pointer values should always be 64 bits
everywhere.

-- PMM



Re: [Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-09 Thread Igor Mammedov
On Thu, 9 Apr 2015 14:27:58 +0100
Peter Maydell peter.mayd...@linaro.org wrote:

 On 9 April 2015 at 14:17, Igor Mammedov imamm...@redhat.com wrote:
  On Thu, 09 Apr 2015 13:50:52 +0100
  Alex Bennée alex.ben...@linaro.org wrote:
 
 
  Shannon Zhao zhaoshengl...@huawei.com writes:
   +for (i = 0; i  table_offsets-len; ++i) {
   +/* rsdt-table_offset_entry to be filled by Guest linker */
   +bios_linker_loader_add_pointer(linker,
   +   ACPI_BUILD_TABLE_FILE,
   +   ACPI_BUILD_TABLE_FILE,
   +   table_data, 
   rsdt-table_offset_entry[i],
   +   sizeof(uint32_t));
 
  Why are these pointers always 32 bit? Can they ever be 64 bit?
  Laszlo, can you confirm that UEFI puts APCI tables below 4G address space?
 
 In the general case you can't guarantee that there will
 be any RAM at all below the 4G point. (The virt board
 isn't like that, obviously, but I believe there's real
 hardware out there that's designed that way.) I don't
 think we should have any 32 bit assumptions in the
 code at all -- pointer values should always be 64 bits
 everywhere.

then that forces us to use xsdt instead of 32-bit rsdt

 -- PMM
 




[Qemu-devel] [PATCH v4 10/20] hw/arm/virt-acpi-build: Generate RSDT table

2015-04-03 Thread Shannon Zhao
From: Shannon Zhao shannon.z...@linaro.org

RSDT points to other tables FADT, MADT, GTDT.

Signed-off-by: Shannon Zhao zhaoshengl...@huawei.com
Signed-off-by: Shannon Zhao shannon.z...@linaro.org
---
 hw/arm/virt-acpi-build.c | 27 +++
 1 file changed, 27 insertions(+)

diff --git a/hw/arm/virt-acpi-build.c b/hw/arm/virt-acpi-build.c
index a7aba75..85e84b1 100644
--- a/hw/arm/virt-acpi-build.c
+++ b/hw/arm/virt-acpi-build.c
@@ -176,6 +176,30 @@ static void acpi_dsdt_add_virtio(Aml *scope, const hwaddr 
*mmio_addrs,
 }
 }
 
+/* RSDT */
+static void
+build_rsdt(GArray *table_data, GArray *linker, GArray *table_offsets)
+{
+AcpiRsdtDescriptorRev1 *rsdt;
+size_t rsdt_len;
+int i;
+
+rsdt_len = sizeof(*rsdt) + sizeof(uint32_t) * table_offsets-len;
+rsdt = acpi_data_push(table_data, rsdt_len);
+memcpy(rsdt-table_offset_entry, table_offsets-data,
+   sizeof(uint32_t) * table_offsets-len);
+for (i = 0; i  table_offsets-len; ++i) {
+/* rsdt-table_offset_entry to be filled by Guest linker */
+bios_linker_loader_add_pointer(linker,
+   ACPI_BUILD_TABLE_FILE,
+   ACPI_BUILD_TABLE_FILE,
+   table_data, 
rsdt-table_offset_entry[i],
+   sizeof(uint32_t));
+}
+build_header(linker, table_data,
+ (void *)rsdt, RSDT, rsdt_len, 1);
+}
+
 /* GTDT */
 static void
 build_gtdt(GArray *table_data, GArray *linker, VirtGuestInfo *guest_info)
@@ -348,6 +372,9 @@ void virt_acpi_build(VirtGuestInfo *guest_info, 
AcpiBuildTables *tables)
 acpi_add_table(table_offsets, tables_blob);
 build_gtdt(tables_blob, tables-linker, guest_info);
 
+/* RSDT is pointed to by RSDP */
+build_rsdt(tables_blob, tables-linker, table_offsets);
+
 /* Cleanup memory that's no longer used. */
 g_array_free(table_offsets, true);
 }
-- 
2.0.4