qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 21/27] pc: add memory hotplug 440fx machine


From: Igor Mammedov
Subject: [Qemu-devel] [PATCH 21/27] pc: add memory hotplug 440fx machine
Date: Thu, 21 Nov 2013 03:38:42 +0100

Add DimmBus for memory hotplug below 4Gb or above 4Gb depending
on initial memory size and hotplug memory size.

* if ram_size is less than 32-bit PCI hole start, reserve
  hotplug memory region as [ram_size,32bit-PCIhole-start)
  if hotplug memory region fits there,
  otherwise reserve hotplug memory region after "0x100000000ULL
  + above_4g_mem_size"

* setup memory hotplug callback to pass event to ACPI hadware.

Signed-off-by: Igor Mammedov <address@hidden>
---
 hw/i386/pc.c               |   52 ++++++++++++++++++++++++++++++++++++++++++++
 hw/i386/pc_piix.c          |    6 ++++-
 hw/pci-host/piix.c         |   13 ++++++++++-
 include/hw/i386/pc.h       |   16 +++++++++++++
 include/hw/pci-host/piix.h |    2 +
 5 files changed, 87 insertions(+), 2 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 85d0862..306ed22 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -1236,6 +1236,58 @@ void pc_acpi_dev_memory_hotplug_init(DimmBus 
*hotplug_mem_bus,
     }
 }
 
+static
+void pc_hotplug_memory_init_impl(Object *owner,
+                                 MemoryRegion *system_memory,
+                                 ram_addr_t low_hotplug_mem_start,
+                                 ram_addr_t low_hotplug_mem_end,
+                                 DimmBus *hotplug_mem_bus,
+                                 ram_addr_t *high_mem_end)
+{
+    QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory-opts"), NULL);
+    ram_addr_t ram_size = qemu_opt_get_size(opts, "mem", 0);
+    ram_addr_t maxmem = qemu_opt_get_size(opts, "maxmem", 0);
+    ram_addr_t hotplug_mem_size;
+
+    if (maxmem <= ram_size) {
+        /* Disable ACPI migration code and creation of memory devices in SSDT 
*/
+        qemu_opt_set_number(opts, "slots", 0);
+        return;
+    }
+
+    hotplug_mem_size = maxmem - ram_size;
+    if (hotplug_mem_size <= (low_hotplug_mem_end - low_hotplug_mem_start)) {
+        hotplug_mem_bus->base = low_hotplug_mem_start;
+    } else {
+        hotplug_mem_bus->base = ROUND_UP(*high_mem_end, 1ULL << 30);
+        *high_mem_end = hotplug_mem_bus->base + hotplug_mem_size;
+    }
+
+    memory_region_init(&hotplug_mem_bus->as, owner, "hotplug-memory",
+                       hotplug_mem_size);
+    memory_region_add_subregion(system_memory, hotplug_mem_bus->base,
+                                &hotplug_mem_bus->as);
+}
+
+pc_hotplug_memory_init_fn pc_hotplug_memory_init = pc_hotplug_memory_init_impl;
+
+void pc_hotplug_memory_init_compat_1_7(Object *owner,
+                                       MemoryRegion *system_memory,
+                                       ram_addr_t low_hotplug_mem_start,
+                                       ram_addr_t low_hotplug_mem_end,
+                                       DimmBus *hotplug_mem_bus,
+                                       ram_addr_t *high_mem_end)
+{
+    QemuOpts *opts = qemu_opts_find(qemu_find_opts("memory-opts"), NULL);
+    /*
+     * clearing slots tells acpi code that memory hotplug is disabled,
+     * so there is not need to migrate its state and create related
+     * SSDT table objects
+     */
+    qemu_opt_set_number(opts, "slots", 0);
+}
+
+
 qemu_irq *pc_allocate_cpu_irq(void)
 {
     return qemu_allocate_irqs(pic_irq_request, NULL, 1);
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index e1fe85a..7d30c12 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -48,6 +48,8 @@
 #include "exec/address-spaces.h"
 #include "hw/acpi/acpi.h"
 #include "cpu.h"
+#include "hw/acpi/piix4.h"
+#include "hw/pci-host/piix.h"
 #ifdef CONFIG_XEN
 #  include <xen/hvm/hvm_info_table.h>
 #endif
@@ -230,6 +232,8 @@ static void pc_init1(QEMUMachineInitArgs *args,
                               gsi[9], *smi_irq,
                               kvm_enabled(), fw_cfg);
         smbus_eeprom_init(smbus, 8, NULL, 0);
+        pc_acpi_dev_memory_hotplug_init(&i440fx_state->hotplug_mem_bus,
+                                        piix4_mem_hotplug, piix4_pm_find());
     }
 
     if (pci_enabled) {
@@ -250,6 +254,7 @@ static void pc_compat_1_7(QEMUMachineInitArgs *args)
 {
     smbios_type1_defaults = false;
     pc_pci_as_mapping_init = pc_pci_as_mapping_init_1_7;
+    pc_hotplug_memory_init = pc_hotplug_memory_init_compat_1_7;
 }
 
 static void pc_compat_1_6(QEMUMachineInitArgs *args)
@@ -367,7 +372,6 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
     .desc = "Standard PC (i440FX + PIIX, 1996)", \
     .hot_add_cpu = pc_hot_add_cpu
 
-
 #define PC_I440FX_1_8_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
 static QEMUMachine pc_i440fx_machine_v1_8 = {
     PC_I440FX_1_8_MACHINE_OPTIONS,
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index 8351430..2f2785b 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -282,6 +282,11 @@ static int i440fx_initfn(PCIDevice *dev)
     dev->config[I440FX_SMRAM] = 0x02;
 
     cpu_smm_register(&i440fx_set_smm, d);
+
+    qbus_create_inplace(&d->hotplug_mem_bus,
+                        sizeof(d->hotplug_mem_bus),
+                        TYPE_DIMM_BUS, DEVICE(d),
+                        "hotplug-membus");
     return 0;
 }
 
@@ -303,6 +308,8 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
     PCII440FXState *f;
     unsigned i;
     I440FXState *i440fx;
+    ram_addr_t below_4g_mem_size = ram_size - above_4g_mem_size;
+    ram_addr_t high_memory_end = 0x100000000ULL + above_4g_mem_size;
 
     dev = qdev_create(NULL, TYPE_I440FX_PCI_HOST_BRIDGE);
     s = PCI_HOST_BRIDGE(dev);
@@ -330,10 +337,14 @@ PCIBus *i440fx_init(PCII440FXState **pi440fx_state,
         i440fx->pci_info.w32.begin = 0xe0000000;
     }
 
+    pc_hotplug_memory_init(OBJECT(f), f->system_memory,
+                           below_4g_mem_size, i440fx->pci_info.w32.begin,
+                           &f->hotplug_mem_bus, &high_memory_end);
+
     /* setup pci memory mapping */
     pc_pci_as_mapping_init(OBJECT(f), f->system_memory,
                            f->pci_address_space,
-                           0x100000000ULL + above_4g_mem_size);
+                           high_memory_end);
 
     memory_region_init_alias(&f->smram_region, OBJECT(d), "smram-region",
                              f->pci_address_space, 0xa0000, 0x20000);
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 0c86ee5..fea7d60 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -154,6 +154,22 @@ void pc_acpi_dev_memory_hotplug_init(DimmBus 
*hotplug_mem_bus,
                                      hotplug_fn hotplug,
                                      Object *acpi_dev);
 
+typedef
+void (*pc_hotplug_memory_init_fn)(Object *owner,
+                                  MemoryRegion *system_memory,
+                                  ram_addr_t low_hotplug_mem_start,
+                                  ram_addr_t low_hotplug_mem_end,
+                                  DimmBus *hotplug_mem_bus,
+                                  ram_addr_t *high_mem_end);
+extern pc_hotplug_memory_init_fn pc_hotplug_memory_init;
+
+void pc_hotplug_memory_init_compat_1_7(Object *owner,
+                                       MemoryRegion *system_memory,
+                                       ram_addr_t low_hotplug_mem_start,
+                                       ram_addr_t low_hotplug_mem_end,
+                                       DimmBus *hotplug_mem_bus,
+                                       ram_addr_t *high_mem_end);
+
 qemu_irq *pc_allocate_cpu_irq(void);
 DeviceState *pc_vga_init(ISABus *isa_bus, PCIBus *pci_bus);
 void pc_basic_device_init(ISABus *isa_bus, qemu_irq *gsi,
diff --git a/include/hw/pci-host/piix.h b/include/hw/pci-host/piix.h
index 1155996..a301c9d 100644
--- a/include/hw/pci-host/piix.h
+++ b/include/hw/pci-host/piix.h
@@ -6,6 +6,7 @@
 #include "hw/pci/pci.h"
 #include "hw/pci/pci_host.h"
 #include "hw/pci-host/pam.h"
+#include "hw/mem/dimm.h"
 
 #define TYPE_I440FX_PCI_DEVICE "i440FX"
 #define I440FX_PCI_DEVICE(obj) \
@@ -22,6 +23,7 @@ struct PCII440FXState {
     PAMMemoryRegion pam_regions[13];
     MemoryRegion smram_region;
     uint8_t smm_enabled;
+    DimmBus hotplug_mem_bus;
 };
 
 #endif
-- 
1.7.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]