qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [Qemu-devel] [PATCH v4 0/3] pc: acpi-build: make linker & RSDP tables dynamic
@ 2015-02-09 13:59 Igor Mammedov
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access Igor Mammedov
                   ` (2 more replies)
  0 siblings, 3 replies; 9+ messages in thread
From: Igor Mammedov @ 2015-02-09 13:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst, marcel.a

changes since v3:
  * split out linker changes
  * fix Michael's patch, by passing build_state
    to callback so it would actually do something
  * split out RSDP migration in separate patch
  * s/imutable/immutable/

Patches 1-2: fix reboot issue after bridge hotplug
Patch 3: addresses RSDP reading race migration issue
         for new machine types

Linker and RSDP tables are build only once, so if later
during rebuild sizes of other ACPI tables change
pointers will be patched incorrectly due to wrong
offsets in RSDP and linker.

To fix it rebuild linker and RSDP tables along with
the rest of ACPI tables so that they would have
offsets that match just built tables.

Here is a simple reproducer:
 1: hotplug bridge using command:
     device_add pci-bridge,chassis_nr=1
 2: reset system from monitor:
     system_reset

As result pointers to ACPI tables are not correct
and guest can't read/parse ACPI tables and on top
of it linker corrupted them by patching at stale
offsets.

Windows guests just refuses to boot and
Linux guests are more resilient and try to boot without
ACPI, sometimes successfully.

Also make sure that new machine types won't see RSDP
changed in the middle of reading duing migration, by
migrating it along with the rest of the tables.

Igor Mammedov (2):
  pc: acpi-build: update linker on guest access
  pc: acpi-build: migrate RSDP table

Michael S. Tsirkin (1):
  acpi: update RSDP on guest access

 hw/i386/acpi-build.c | 33 ++++++++++++++++++++++++---------
 hw/i386/pc_piix.c    |  3 +++
 hw/i386/pc_q35.c     |  3 +++
 include/hw/i386/pc.h |  1 +
 4 files changed, 31 insertions(+), 9 deletions(-)

-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access
  2015-02-09 13:59 [Qemu-devel] [PATCH v4 0/3] pc: acpi-build: make linker & RSDP tables dynamic Igor Mammedov
@ 2015-02-09 13:59 ` Igor Mammedov
  2015-02-09 14:11   ` Marcel Apfelbaum
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker " Igor Mammedov
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table Igor Mammedov
  2 siblings, 1 reply; 9+ messages in thread
From: Igor Mammedov @ 2015-02-09 13:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst, marcel.a

From: "Michael S. Tsirkin" <mst@redhat.com>

RSDT offset can change across reboots and that makes
immutable RSDP, which is build at startup, point to
incorrect place in ACPI table blob. That results in
BIOS corrupting tables and guest OS failing to find
ACPI tables.
We really should have put it in a ROM region, but
we can't change that for old machine types,
let's just set the callback and update it explicitly.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
v2:
  * do not forget to pass build_state to callback
    otherwise it's NOP.
---
 hw/i386/acpi-build.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 4944249..5b2b017 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1526,6 +1526,7 @@ struct AcpiBuildState {
     /* Is table patched? */
     uint8_t patched;
     PcGuestInfo *guest_info;
+    void *rsdp;
 } AcpiBuildState;
 
 static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
@@ -1660,8 +1661,6 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
 
     /* We'll expose it all to Guest so we want to reduce
      * chance of size changes.
-     * RSDP is small so it's easy to keep it immutable, no need to
-     * bother with alignment.
      *
      * We used to align the tables to 4k, but of course this would
      * too simple to be enough.  4k turned out to be too small an
@@ -1733,6 +1732,7 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
 
     memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
            build_state->table_size);
+    memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp));
 
     cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
                                                build_state->table_size);
@@ -1805,11 +1805,14 @@ void acpi_setup(PcGuestInfo *guest_info)
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
     /*
-     * RSDP is small so it's easy to keep it immutable, no need to
-     * bother with ROM blobs.
+     * Though RSDP is small, its contents isn't immutable, so
+     * update it along with the rest of tables on guest access.
      */
-    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
-                    tables.rsdp->data, acpi_data_len(tables.rsdp));
+    fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
+                             acpi_build_update, build_state,
+                             tables.rsdp->data, acpi_data_len(tables.rsdp));
+
+    build_state->rsdp = tables.rsdp->data;
 
     qemu_register_reset(acpi_build_reset, build_state);
     acpi_build_reset(build_state);
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker on guest access
  2015-02-09 13:59 [Qemu-devel] [PATCH v4 0/3] pc: acpi-build: make linker & RSDP tables dynamic Igor Mammedov
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access Igor Mammedov
@ 2015-02-09 13:59 ` Igor Mammedov
  2015-02-09 14:11   ` Marcel Apfelbaum
  2015-02-15 19:45   ` Michael S. Tsirkin
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table Igor Mammedov
  2 siblings, 2 replies; 9+ messages in thread
From: Igor Mammedov @ 2015-02-09 13:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst, marcel.a

Linker table is build only once, so if later during
tables rebuild sizes of other ACPI tables change
pointers will be patched incorrectly due to wrong
offsets in linker. Resulting in guest not being able
to find ACPI tables.
Fix it by updating 'linker' table with the rest of
tables when firmware reads it.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/i386/acpi-build.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 5b2b017..21ea3db 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1527,6 +1527,8 @@ struct AcpiBuildState {
     uint8_t patched;
     PcGuestInfo *guest_info;
     void *rsdp;
+    ram_addr_t linker_ram;
+    uint32_t linker_size;
 } AcpiBuildState;
 
 static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
@@ -1733,6 +1735,8 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
     memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
            build_state->table_size);
     memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp));
+    memcpy(qemu_get_ram_ptr(build_state->linker_ram), tables.linker->data,
+           build_state->linker_size);
 
     cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
                                                build_state->table_size);
@@ -1799,7 +1803,9 @@ void acpi_setup(PcGuestInfo *guest_info)
     assert(build_state->table_ram != RAM_ADDR_MAX);
     build_state->table_size = acpi_data_len(tables.table_data);
 
-    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader", 0);
+    build_state->linker_ram =
+        acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
+    build_state->linker_size = acpi_data_len(tables.linker);
 
     fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
-- 
1.8.3.1

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

* [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table
  2015-02-09 13:59 [Qemu-devel] [PATCH v4 0/3] pc: acpi-build: make linker & RSDP tables dynamic Igor Mammedov
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access Igor Mammedov
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker " Igor Mammedov
@ 2015-02-09 13:59 ` Igor Mammedov
  2015-02-09 14:19   ` Marcel Apfelbaum
  2015-02-15 19:45   ` Michael S. Tsirkin
  2 siblings, 2 replies; 9+ messages in thread
From: Igor Mammedov @ 2015-02-09 13:59 UTC (permalink / raw)
  To: qemu-devel; +Cc: mst, marcel.a

Makes sure that RSDP stays the same
/i.e. matches ACPI tables blob in source/
if guest is migrated during RSDP reading or
has been already shadowed by firmware.

Fix applies only to new machine types starting
from 2.3, so it won't break migration for old
machine types.

Signed-off-by: Igor Mammedov <imammedo@redhat.com>
---
 hw/i386/acpi-build.c | 24 +++++++++++++++---------
 hw/i386/pc_piix.c    |  3 +++
 hw/i386/pc_q35.c     |  3 +++
 include/hw/i386/pc.h |  1 +
 4 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
index 21ea3db..1583cca 100644
--- a/hw/i386/acpi-build.c
+++ b/hw/i386/acpi-build.c
@@ -1810,15 +1810,21 @@ void acpi_setup(PcGuestInfo *guest_info)
     fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
                     tables.tcpalog->data, acpi_data_len(tables.tcpalog));
 
-    /*
-     * Though RSDP is small, its contents isn't immutable, so
-     * update it along with the rest of tables on guest access.
-     */
-    fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
-                             acpi_build_update, build_state,
-                             tables.rsdp->data, acpi_data_len(tables.rsdp));
-
-    build_state->rsdp = tables.rsdp->data;
+    if (guest_info->has_immutable_rsdp) {
+        /*
+         * Keep for compatibility with old machine types.
+         * Though RSDP is small, its contents isn't immutable, so
+         * update it along with the rest of tables on guest access.
+         */
+        fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
+                                 acpi_build_update, build_state,
+                                 tables.rsdp->data, acpi_data_len(tables.rsdp));
+        build_state->rsdp = tables.rsdp->data;
+    } else {
+        build_state->rsdp = qemu_get_ram_ptr(
+            acpi_add_rom_blob(build_state, tables.rsdp, ACPI_BUILD_RSDP_FILE, 0)
+        );
+    }
 
     qemu_register_reset(acpi_build_reset, build_state);
     acpi_build_reset(build_state);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index 38b42b0..e586c7b 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -60,6 +60,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
 static bool has_acpi_build = true;
+static bool has_immutable_rsdp;
 static int legacy_acpi_table_size;
 static bool smbios_defaults = true;
 static bool smbios_legacy_mode;
@@ -168,6 +169,7 @@ static void pc_init1(MachineState *machine,
 
     guest_info->isapc_ram_fw = !pci_enabled;
     guest_info->has_reserved_memory = has_reserved_memory;
+    guest_info->has_immutable_rsdp = has_immutable_rsdp;
 
     if (smbios_defaults) {
         MachineClass *mc = MACHINE_GET_CLASS(machine);
@@ -310,6 +312,7 @@ static void pc_init_pci(MachineState *machine)
 
 static void pc_compat_2_2(MachineState *machine)
 {
+    has_immutable_rsdp = true;
     x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
index 63027ee..6151f2f 100644
--- a/hw/i386/pc_q35.c
+++ b/hw/i386/pc_q35.c
@@ -50,6 +50,7 @@
 #define MAX_SATA_PORTS     6
 
 static bool has_acpi_build = true;
+static bool has_immutable_rsdp;
 static bool smbios_defaults = true;
 static bool smbios_legacy_mode;
 static bool smbios_uuid_encoded = true;
@@ -154,6 +155,7 @@ static void pc_q35_init(MachineState *machine)
     guest_info->isapc_ram_fw = false;
     guest_info->has_acpi_build = has_acpi_build;
     guest_info->has_reserved_memory = has_reserved_memory;
+    guest_info->has_immutable_rsdp = has_immutable_rsdp;
 
     /* Migration was not supported in 2.0 for Q35, so do not bother
      * with this hack (see hw/i386/acpi-build.c).
@@ -289,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
 
 static void pc_compat_2_2(MachineState *machine)
 {
+    has_immutable_rsdp = true;
     x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
     x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 69d9cf8..b0a80cf 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -104,6 +104,7 @@ struct PcGuestInfo {
     int legacy_acpi_table_size;
     bool has_acpi_build;
     bool has_reserved_memory;
+    bool has_immutable_rsdp;
 };
 
 /* parallel.c */
-- 
1.8.3.1

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

* Re: [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access Igor Mammedov
@ 2015-02-09 14:11   ` Marcel Apfelbaum
  0 siblings, 0 replies; 9+ messages in thread
From: Marcel Apfelbaum @ 2015-02-09 14:11 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: mst, marcel.a

On 02/09/2015 03:59 PM, Igor Mammedov wrote:
> From: "Michael S. Tsirkin" <mst@redhat.com>
>
> RSDT offset can change across reboots and that makes
> immutable RSDP, which is build at startup, point to
> incorrect place in ACPI table blob. That results in
> BIOS corrupting tables and guest OS failing to find
> ACPI tables.
> We really should have put it in a ROM region, but
> we can't change that for old machine types,
> let's just set the callback and update it explicitly.
>
> Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
> v2:
>    * do not forget to pass build_state to callback
>      otherwise it's NOP.
> ---
>   hw/i386/acpi-build.c | 15 +++++++++------
>   1 file changed, 9 insertions(+), 6 deletions(-)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 4944249..5b2b017 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1526,6 +1526,7 @@ struct AcpiBuildState {
>       /* Is table patched? */
>       uint8_t patched;
>       PcGuestInfo *guest_info;
> +    void *rsdp;
>   } AcpiBuildState;
>
>   static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
> @@ -1660,8 +1661,6 @@ void acpi_build(PcGuestInfo *guest_info, AcpiBuildTables *tables)
>
>       /* We'll expose it all to Guest so we want to reduce
>        * chance of size changes.
> -     * RSDP is small so it's easy to keep it immutable, no need to
> -     * bother with alignment.
>        *
>        * We used to align the tables to 4k, but of course this would
>        * too simple to be enough.  4k turned out to be too small an
> @@ -1733,6 +1732,7 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
>
>       memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
>              build_state->table_size);
> +    memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp));
>
>       cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
>                                                  build_state->table_size);
> @@ -1805,11 +1805,14 @@ void acpi_setup(PcGuestInfo *guest_info)
>                       tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>
>       /*
> -     * RSDP is small so it's easy to keep it immutable, no need to
> -     * bother with ROM blobs.
> +     * Though RSDP is small, its contents isn't immutable, so
> +     * update it along with the rest of tables on guest access.
>        */
> -    fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
> -                    tables.rsdp->data, acpi_data_len(tables.rsdp));
> +    fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
> +                             acpi_build_update, build_state,
> +                             tables.rsdp->data, acpi_data_len(tables.rsdp));
> +
> +    build_state->rsdp = tables.rsdp->data;
>
>       qemu_register_reset(acpi_build_reset, build_state);
>       acpi_build_reset(build_state);
>

Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>

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

* Re: [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker on guest access
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker " Igor Mammedov
@ 2015-02-09 14:11   ` Marcel Apfelbaum
  2015-02-15 19:45   ` Michael S. Tsirkin
  1 sibling, 0 replies; 9+ messages in thread
From: Marcel Apfelbaum @ 2015-02-09 14:11 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: mst, marcel.a

On 02/09/2015 03:59 PM, Igor Mammedov wrote:
> Linker table is build only once, so if later during
> tables rebuild sizes of other ACPI tables change
> pointers will be patched incorrectly due to wrong
> offsets in linker. Resulting in guest not being able
> to find ACPI tables.
> Fix it by updating 'linker' table with the rest of
> tables when firmware reads it.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>   hw/i386/acpi-build.c | 8 +++++++-
>   1 file changed, 7 insertions(+), 1 deletion(-)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 5b2b017..21ea3db 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1527,6 +1527,8 @@ struct AcpiBuildState {
>       uint8_t patched;
>       PcGuestInfo *guest_info;
>       void *rsdp;
> +    ram_addr_t linker_ram;
> +    uint32_t linker_size;
>   } AcpiBuildState;
>
>   static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
> @@ -1733,6 +1735,8 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
>       memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
>              build_state->table_size);
>       memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp));
> +    memcpy(qemu_get_ram_ptr(build_state->linker_ram), tables.linker->data,
> +           build_state->linker_size);
>
>       cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
>                                                  build_state->table_size);
> @@ -1799,7 +1803,9 @@ void acpi_setup(PcGuestInfo *guest_info)
>       assert(build_state->table_ram != RAM_ADDR_MAX);
>       build_state->table_size = acpi_data_len(tables.table_data);
>
> -    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader", 0);
> +    build_state->linker_ram =
> +        acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
> +    build_state->linker_size = acpi_data_len(tables.linker);
>
>       fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                       tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>


Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>

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

* Re: [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table Igor Mammedov
@ 2015-02-09 14:19   ` Marcel Apfelbaum
  2015-02-15 19:45   ` Michael S. Tsirkin
  1 sibling, 0 replies; 9+ messages in thread
From: Marcel Apfelbaum @ 2015-02-09 14:19 UTC (permalink / raw)
  To: Igor Mammedov, qemu-devel; +Cc: mst, marcel.a

On 02/09/2015 03:59 PM, Igor Mammedov wrote:
> Makes sure that RSDP stays the same
> /i.e. matches ACPI tables blob in source/
> if guest is migrated during RSDP reading or
> has been already shadowed by firmware.
>
> Fix applies only to new machine types starting
> from 2.3, so it won't break migration for old
> machine types.
>
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>   hw/i386/acpi-build.c | 24 +++++++++++++++---------
>   hw/i386/pc_piix.c    |  3 +++
>   hw/i386/pc_q35.c     |  3 +++
>   include/hw/i386/pc.h |  1 +
>   4 files changed, 22 insertions(+), 9 deletions(-)
>
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 21ea3db..1583cca 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1810,15 +1810,21 @@ void acpi_setup(PcGuestInfo *guest_info)
>       fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                       tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>
> -    /*
> -     * Though RSDP is small, its contents isn't immutable, so
> -     * update it along with the rest of tables on guest access.
> -     */
> -    fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
> -                             acpi_build_update, build_state,
> -                             tables.rsdp->data, acpi_data_len(tables.rsdp));
> -
> -    build_state->rsdp = tables.rsdp->data;
> +    if (guest_info->has_immutable_rsdp) {
> +        /*
> +         * Keep for compatibility with old machine types.
> +         * Though RSDP is small, its contents isn't immutable, so
> +         * update it along with the rest of tables on guest access.
> +         */
> +        fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
> +                                 acpi_build_update, build_state,
> +                                 tables.rsdp->data, acpi_data_len(tables.rsdp));
> +        build_state->rsdp = tables.rsdp->data;
> +    } else {
> +        build_state->rsdp = qemu_get_ram_ptr(
> +            acpi_add_rom_blob(build_state, tables.rsdp, ACPI_BUILD_RSDP_FILE, 0)
> +        );
> +    }
>
>       qemu_register_reset(acpi_build_reset, build_state);
>       acpi_build_reset(build_state);
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 38b42b0..e586c7b 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -60,6 +60,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
>   static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
>
>   static bool has_acpi_build = true;
> +static bool has_immutable_rsdp;
>   static int legacy_acpi_table_size;
>   static bool smbios_defaults = true;
>   static bool smbios_legacy_mode;
> @@ -168,6 +169,7 @@ static void pc_init1(MachineState *machine,
>
>       guest_info->isapc_ram_fw = !pci_enabled;
>       guest_info->has_reserved_memory = has_reserved_memory;
> +    guest_info->has_immutable_rsdp = has_immutable_rsdp;
>
>       if (smbios_defaults) {
>           MachineClass *mc = MACHINE_GET_CLASS(machine);
> @@ -310,6 +312,7 @@ static void pc_init_pci(MachineState *machine)
>
>   static void pc_compat_2_2(MachineState *machine)
>   {
> +    has_immutable_rsdp = true;
>       x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
>       x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
>       x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 63027ee..6151f2f 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -50,6 +50,7 @@
>   #define MAX_SATA_PORTS     6
>
>   static bool has_acpi_build = true;
> +static bool has_immutable_rsdp;
>   static bool smbios_defaults = true;
>   static bool smbios_legacy_mode;
>   static bool smbios_uuid_encoded = true;
> @@ -154,6 +155,7 @@ static void pc_q35_init(MachineState *machine)
>       guest_info->isapc_ram_fw = false;
>       guest_info->has_acpi_build = has_acpi_build;
>       guest_info->has_reserved_memory = has_reserved_memory;
> +    guest_info->has_immutable_rsdp = has_immutable_rsdp;
>
>       /* Migration was not supported in 2.0 for Q35, so do not bother
>        * with this hack (see hw/i386/acpi-build.c).
> @@ -289,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
>
>   static void pc_compat_2_2(MachineState *machine)
>   {
> +    has_immutable_rsdp = true;
>       x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
>       x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
>       x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 69d9cf8..b0a80cf 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -104,6 +104,7 @@ struct PcGuestInfo {
>       int legacy_acpi_table_size;
>       bool has_acpi_build;
>       bool has_reserved_memory;
> +    bool has_immutable_rsdp;
>   };
>
>   /* parallel.c */
>

Reviewed-by: Marcel Apfelbaum <marcel@redhat.com>

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

* Re: [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker on guest access
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker " Igor Mammedov
  2015-02-09 14:11   ` Marcel Apfelbaum
@ 2015-02-15 19:45   ` Michael S. Tsirkin
  1 sibling, 0 replies; 9+ messages in thread
From: Michael S. Tsirkin @ 2015-02-15 19:45 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, marcel.a

On Mon, Feb 09, 2015 at 01:59:54PM +0000, Igor Mammedov wrote:
> Linker table is build only once, so if later during
> tables rebuild sizes of other ACPI tables change
> pointers will be patched incorrectly due to wrong
> offsets in linker. Resulting in guest not being able
> to find ACPI tables.
> Fix it by updating 'linker' table with the rest of
> tables when firmware reads it.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>
> ---
>  hw/i386/acpi-build.c | 8 +++++++-
>  1 file changed, 7 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 5b2b017..21ea3db 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1527,6 +1527,8 @@ struct AcpiBuildState {
>      uint8_t patched;
>      PcGuestInfo *guest_info;
>      void *rsdp;
> +    ram_addr_t linker_ram;
> +    uint32_t linker_size;
>  } AcpiBuildState;
>  
>  static bool acpi_get_mcfg(AcpiMcfgInfo *mcfg)
> @@ -1733,6 +1735,8 @@ static void acpi_build_update(void *build_opaque, uint32_t offset)
>      memcpy(qemu_get_ram_ptr(build_state->table_ram), tables.table_data->data,
>             build_state->table_size);
>      memcpy(build_state->rsdp, tables.rsdp->data, acpi_data_len(tables.rsdp));
> +    memcpy(qemu_get_ram_ptr(build_state->linker_ram), tables.linker->data,
> +           build_state->linker_size);
>  
>      cpu_physical_memory_set_dirty_range_nocode(build_state->table_ram,
>                                                 build_state->table_size);

OK, but it looks like linker data needs to be marked dirty
as well. I'll send a patch to do this.

> @@ -1799,7 +1803,9 @@ void acpi_setup(PcGuestInfo *guest_info)
>      assert(build_state->table_ram != RAM_ADDR_MAX);
>      build_state->table_size = acpi_data_len(tables.table_data);
>  
> -    acpi_add_rom_blob(NULL, tables.linker, "etc/table-loader", 0);
> +    build_state->linker_ram =
> +        acpi_add_rom_blob(build_state, tables.linker, "etc/table-loader", 0);
> +    build_state->linker_size = acpi_data_len(tables.linker);
>  
>      fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                      tables.tcpalog->data, acpi_data_len(tables.tcpalog));
> -- 
> 1.8.3.1

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

* Re: [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table
  2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table Igor Mammedov
  2015-02-09 14:19   ` Marcel Apfelbaum
@ 2015-02-15 19:45   ` Michael S. Tsirkin
  1 sibling, 0 replies; 9+ messages in thread
From: Michael S. Tsirkin @ 2015-02-15 19:45 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, marcel.a

On Mon, Feb 09, 2015 at 01:59:55PM +0000, Igor Mammedov wrote:
> Makes sure that RSDP stays the same
> /i.e. matches ACPI tables blob in source/
> if guest is migrated during RSDP reading or
> has been already shadowed by firmware.
> 
> Fix applies only to new machine types starting
> from 2.3, so it won't break migration for old
> machine types.
> 
> Signed-off-by: Igor Mammedov <imammedo@redhat.com>

This worries me: the RAM block is not marked dirty when we modify it
with memcpy, so might it grow stale?
I would prefer that we give it the same handling as table_ram.
Will send a patch on top.

> ---
>  hw/i386/acpi-build.c | 24 +++++++++++++++---------
>  hw/i386/pc_piix.c    |  3 +++
>  hw/i386/pc_q35.c     |  3 +++
>  include/hw/i386/pc.h |  1 +
>  4 files changed, 22 insertions(+), 9 deletions(-)
> 
> diff --git a/hw/i386/acpi-build.c b/hw/i386/acpi-build.c
> index 21ea3db..1583cca 100644
> --- a/hw/i386/acpi-build.c
> +++ b/hw/i386/acpi-build.c
> @@ -1810,15 +1810,21 @@ void acpi_setup(PcGuestInfo *guest_info)
>      fw_cfg_add_file(guest_info->fw_cfg, ACPI_BUILD_TPMLOG_FILE,
>                      tables.tcpalog->data, acpi_data_len(tables.tcpalog));
>  
> -    /*
> -     * Though RSDP is small, its contents isn't immutable, so
> -     * update it along with the rest of tables on guest access.
> -     */
> -    fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
> -                             acpi_build_update, build_state,
> -                             tables.rsdp->data, acpi_data_len(tables.rsdp));
> -
> -    build_state->rsdp = tables.rsdp->data;
> +    if (guest_info->has_immutable_rsdp) {
> +        /*
> +         * Keep for compatibility with old machine types.
> +         * Though RSDP is small, its contents isn't immutable, so
> +         * update it along with the rest of tables on guest access.
> +         */
> +        fw_cfg_add_file_callback(guest_info->fw_cfg, ACPI_BUILD_RSDP_FILE,
> +                                 acpi_build_update, build_state,
> +                                 tables.rsdp->data, acpi_data_len(tables.rsdp));
> +        build_state->rsdp = tables.rsdp->data;
> +    } else {
> +        build_state->rsdp = qemu_get_ram_ptr(
> +            acpi_add_rom_blob(build_state, tables.rsdp, ACPI_BUILD_RSDP_FILE, 0)
> +        );
> +    }
>  
>      qemu_register_reset(acpi_build_reset, build_state);
>      acpi_build_reset(build_state);
> diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
> index 38b42b0..e586c7b 100644
> --- a/hw/i386/pc_piix.c
> +++ b/hw/i386/pc_piix.c
> @@ -60,6 +60,7 @@ static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
>  static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
>  
>  static bool has_acpi_build = true;
> +static bool has_immutable_rsdp;
>  static int legacy_acpi_table_size;
>  static bool smbios_defaults = true;
>  static bool smbios_legacy_mode;
> @@ -168,6 +169,7 @@ static void pc_init1(MachineState *machine,
>  
>      guest_info->isapc_ram_fw = !pci_enabled;
>      guest_info->has_reserved_memory = has_reserved_memory;
> +    guest_info->has_immutable_rsdp = has_immutable_rsdp;
>  
>      if (smbios_defaults) {
>          MachineClass *mc = MACHINE_GET_CLASS(machine);
> @@ -310,6 +312,7 @@ static void pc_init_pci(MachineState *machine)
>  
>  static void pc_compat_2_2(MachineState *machine)
>  {
> +    has_immutable_rsdp = true;
>      x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
>      x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
>      x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
> diff --git a/hw/i386/pc_q35.c b/hw/i386/pc_q35.c
> index 63027ee..6151f2f 100644
> --- a/hw/i386/pc_q35.c
> +++ b/hw/i386/pc_q35.c
> @@ -50,6 +50,7 @@
>  #define MAX_SATA_PORTS     6
>  
>  static bool has_acpi_build = true;
> +static bool has_immutable_rsdp;
>  static bool smbios_defaults = true;
>  static bool smbios_legacy_mode;
>  static bool smbios_uuid_encoded = true;
> @@ -154,6 +155,7 @@ static void pc_q35_init(MachineState *machine)
>      guest_info->isapc_ram_fw = false;
>      guest_info->has_acpi_build = has_acpi_build;
>      guest_info->has_reserved_memory = has_reserved_memory;
> +    guest_info->has_immutable_rsdp = has_immutable_rsdp;
>  
>      /* Migration was not supported in 2.0 for Q35, so do not bother
>       * with this hack (see hw/i386/acpi-build.c).
> @@ -289,6 +291,7 @@ static void pc_q35_init(MachineState *machine)
>  
>  static void pc_compat_2_2(MachineState *machine)
>  {
> +    has_immutable_rsdp = true;
>      x86_cpu_compat_set_features("kvm64", FEAT_1_EDX, 0, CPUID_VME);
>      x86_cpu_compat_set_features("kvm32", FEAT_1_EDX, 0, CPUID_VME);
>      x86_cpu_compat_set_features("Conroe", FEAT_1_EDX, 0, CPUID_VME);
> diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
> index 69d9cf8..b0a80cf 100644
> --- a/include/hw/i386/pc.h
> +++ b/include/hw/i386/pc.h
> @@ -104,6 +104,7 @@ struct PcGuestInfo {
>      int legacy_acpi_table_size;
>      bool has_acpi_build;
>      bool has_reserved_memory;
> +    bool has_immutable_rsdp;
>  };
>  
>  /* parallel.c */
> -- 
> 1.8.3.1

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

end of thread, other threads:[~2015-02-15 19:45 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-02-09 13:59 [Qemu-devel] [PATCH v4 0/3] pc: acpi-build: make linker & RSDP tables dynamic Igor Mammedov
2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 1/3] acpi: update RSDP on guest access Igor Mammedov
2015-02-09 14:11   ` Marcel Apfelbaum
2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 2/3] pc: acpi-build: update linker " Igor Mammedov
2015-02-09 14:11   ` Marcel Apfelbaum
2015-02-15 19:45   ` Michael S. Tsirkin
2015-02-09 13:59 ` [Qemu-devel] [PATCH v4 3/3] pc: acpi-build: migrate RSDP table Igor Mammedov
2015-02-09 14:19   ` Marcel Apfelbaum
2015-02-15 19:45   ` 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).