qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH 2/3] VCPU hotplug support


From: Igor Mammedov
Subject: [Qemu-devel] [PATCH 2/3] VCPU hotplug support
Date: Tue, 17 Jan 2012 14:17:09 +0100

Rebase of the missing bits from qemu-kvm for vcpu hotplug

Signed-off-by: Igor Mammedov <address@hidden>
---
 Makefile.objs     |    2 +-
 Makefile.target   |    2 +-
 hw/acpi_piix4.c   |   83 ++++++++++++++++++++++++++++++++++++++++++++++++++--
 hw/pc.c           |   21 +++++++++++++-
 hw/pc_piix.c      |    4 ++
 sysemu.h          |    2 +
 target-i386/cpu.h |    1 +
 7 files changed, 108 insertions(+), 7 deletions(-)

diff --git a/Makefile.objs b/Makefile.objs
index 45df666..2a8ccc1 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -212,7 +212,7 @@ hw-obj-$(CONFIG_USB_UHCI) += usb-uhci.o
 hw-obj-$(CONFIG_USB_OHCI) += usb-ohci.o
 hw-obj-$(CONFIG_USB_EHCI) += usb-ehci.o
 hw-obj-$(CONFIG_FDC) += fdc.o
-hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o icc_bus.o
+hw-obj-$(CONFIG_ACPI) += acpi.o icc_bus.o
 hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
 hw-obj-$(CONFIG_DMA) += dma.o
 hw-obj-$(CONFIG_HPET) += hpet.o
diff --git a/Makefile.target b/Makefile.target
index 06d79b8..4865dde 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -226,7 +226,7 @@ obj-y += device-hotplug.o
 # Hardware support
 obj-i386-y += vga.o
 obj-i386-y += mc146818rtc.o pc.o
-obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o
+obj-i386-y += cirrus_vga.o sga.o apic.o ioapic.o piix_pci.o acpi_piix4.o
 obj-i386-y += vmport.o
 obj-i386-y += pci-hotplug.o smbios.o wdt_ib700.o
 obj-i386-y += debugcon.o multiboot.o
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index bdc55a1..f1cdcc1 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -39,13 +39,19 @@
 #define ACPI_DBG_IO_ADDR  0xb044
 
 #define GPE_BASE 0xafe0
+#define PROC_BASE 0xaf00
 #define GPE_LEN 4
 #define PCI_BASE 0xae00
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
 
+#define PIIX4_CPU_HOTPLUG_STATUS 4
 #define PIIX4_PCI_HOTPLUG_STATUS 2
 
+struct gpe_regs {
+    uint8_t cpus_sts[32];
+};
+
 struct pci_status {
     uint32_t up;
     uint32_t down;
@@ -71,6 +77,7 @@ typedef struct PIIX4PMState {
 
     /* for pci hotplug */
     ACPIGPE gpe;
+    struct gpe_regs gpe_cpu;
     struct pci_status pci0_status;
     uint32_t pci0_hotplug_enable;
 } PIIX4PMState;
@@ -90,9 +97,11 @@ static void pm_update_sci(PIIX4PMState *s)
                    ACPI_BITMASK_POWER_BUTTON_ENABLE |
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
-        (((s->gpe.sts[0] & s->gpe.en[0]) & PIIX4_PCI_HOTPLUG_STATUS) != 0);
+        (((s->gpe.sts[0] & s->gpe.en[0]) &
+         (PIIX4_PCI_HOTPLUG_STATUS | PIIX4_CPU_HOTPLUG_STATUS)) != 0);
 
     qemu_set_irq(s->irq, sci_level);
+
     /* schedule a timer interruption if needed */
     acpi_pm_tmr_update(&s->tmr, (s->pm1a.en & ACPI_BITMASK_TIMER_ENABLE) &&
                        !(pmsts & ACPI_BITMASK_TIMER_STATUS));
@@ -219,10 +228,9 @@ static int vmstate_acpi_post_load(void *opaque, int 
version_id)
  {                                                                   \
      .name       = (stringify(_field)),                              \
      .version_id = 0,                                                \
-     .num        = GPE_LEN,                                          \
      .info       = &vmstate_info_uint16,                             \
      .size       = sizeof(uint16_t),                                 \
-     .flags      = VMS_ARRAY | VMS_POINTER,                          \
+     .flags      = VMS_SINGLE | VMS_POINTER,                         \
      .offset     = vmstate_offset_pointer(_state, _field, uint8_t),  \
  }
 
@@ -329,11 +337,16 @@ static void piix4_pm_machine_ready(Notifier *n, void 
*opaque)
 
 }
 
+static PIIX4PMState *global_piix4_pm_state; /* cpu hotadd */
+
 static int piix4_pm_initfn(PCIDevice *dev)
 {
     PIIX4PMState *s = DO_UPCAST(PIIX4PMState, dev, dev);
     uint8_t *pci_conf;
 
+    /* for cpu hotadd */
+    global_piix4_pm_state = s;
+
     pci_conf = s->dev.config;
     pci_conf[0x06] = 0x80;
     pci_conf[0x07] = 0x02;
@@ -425,7 +438,16 @@ device_init(piix4_pm_register);
 static uint32_t gpe_readb(void *opaque, uint32_t addr)
 {
     PIIX4PMState *s = opaque;
-    uint32_t val = acpi_gpe_ioport_readb(&s->gpe, addr);
+    uint32_t val = 0;
+    struct gpe_regs *g = &s->gpe_cpu;
+
+    switch (addr) {
+    case PROC_BASE ... PROC_BASE+31:
+        val = g->cpus_sts[addr - PROC_BASE];
+        break;
+    default:
+        val = acpi_gpe_ioport_readb(&s->gpe, addr);
+    }
 
     PIIX4_DPRINTF("gpe read %x == %x\n", addr, val);
     return val;
@@ -519,11 +541,20 @@ static int piix4_device_hotplug(DeviceState *qdev, 
PCIDevice *dev,
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
     struct pci_status *pci0_status = &s->pci0_status;
+    int i = 0, cpus = smp_cpus;
+
+    while (cpus > 0) {
+        s->gpe_cpu.cpus_sts[i++] = (cpus < 8) ? (1 << cpus) - 1 : 0xff;
+        cpus -= 8;
+    }
 
     register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
     register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
     acpi_gpe_blk(&s->gpe, GPE_BASE);
 
+    register_ioport_write(PROC_BASE, 32, 1, gpe_writeb, s);
+    register_ioport_read(PROC_BASE, 32, 1,  gpe_readb, s);
+
     register_ioport_write(PCI_BASE, 8, 4, pcihotplug_write, pci0_status);
     register_ioport_read(PCI_BASE, 8, 4,  pcihotplug_read, pci0_status);
 
@@ -536,6 +567,50 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, 
PIIX4PMState *s)
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 }
 
+extern const char *global_cpu_model;
+
+#ifdef TARGET_I386
+static void enable_processor(PIIX4PMState *s, int cpu)
+{
+    struct gpe_regs *g = &s->gpe_cpu;
+    ACPIGPE *gpe = &s->gpe;
+
+    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
+    g->cpus_sts[cpu/8] |= (1 << (cpu%8));
+}
+
+static void disable_processor(PIIX4PMState *s, int cpu)
+{
+    struct gpe_regs *g = &s->gpe_cpu;
+    ACPIGPE *gpe = &s->gpe;
+
+    *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
+    g->cpus_sts[cpu/8] &= ~(1 << (cpu%8));
+}
+
+void qemu_system_cpu_hot_add(int cpu, int state)
+{
+    CPUState *env;
+    PIIX4PMState *s = global_piix4_pm_state;
+
+    if (state && !qemu_get_cpu(cpu)) {
+        env = pc_new_cpu(global_cpu_model);
+        if (!env) {
+            fprintf(stderr, "cpu %d creation failed\n", cpu);
+            return;
+        }
+        env->cpuid_apic_id = cpu;
+    }
+
+    if (state) {
+        enable_processor(s, cpu);
+    } else {
+        disable_processor(s, cpu);
+    }
+    pm_update_sci(s);
+}
+#endif
+
 static void enable_device(PIIX4PMState *s, int slot)
 {
     s->gpe.sts[0] |= PIIX4_PCI_HOTPLUG_STATUS;
diff --git a/hw/pc.c b/hw/pc.c
index 33d8090..c7342d8 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -44,6 +44,8 @@
 #include "ui/qemu-spice.h"
 #include "memory.h"
 #include "exec-memory.h"
+#include "cpus.h"
+#include "kvm.h"
 
 /* output Bochs bios info messages */
 //#define DEBUG_BIOS
@@ -930,10 +932,22 @@ static void pc_cpu_reset(void *opaque)
     env->halted = !cpu_is_bsp(env);
 }
 
-static CPUState *pc_new_cpu(const char *cpu_model)
+CPUState *pc_new_cpu(const char *cpu_model)
 {
     CPUState *env;
 
+    if (cpu_model == NULL) {
+#ifdef TARGET_X86_64
+        cpu_model = "qemu64";
+#else
+        cpu_model = "qemu32";
+#endif
+    }
+
+    if (runstate_is_running()) {
+        pause_all_vcpus();
+    }
+
     env = cpu_init(cpu_model);
     if (!env) {
         fprintf(stderr, "Unable to find x86 CPU definition\n");
@@ -944,6 +958,11 @@ static CPUState *pc_new_cpu(const char *cpu_model)
     }
     qemu_register_reset(pc_cpu_reset, env);
     pc_cpu_reset(env);
+
+    cpu_synchronize_post_init(env);
+    if (runstate_is_running()) {
+        resume_all_vcpus();
+    }
     return env;
 }
 
diff --git a/hw/pc_piix.c b/hw/pc_piix.c
index b70431f..1c77ea1 100644
--- a/hw/pc_piix.c
+++ b/hw/pc_piix.c
@@ -53,6 +53,8 @@ static const int ide_iobase[MAX_IDE_BUS] = { 0x1f0, 0x170 };
 static const int ide_iobase2[MAX_IDE_BUS] = { 0x3f6, 0x376 };
 static const int ide_irq[MAX_IDE_BUS] = { 14, 15 };
 
+const char *global_cpu_model; /* cpu hotadd */
+
 static void ioapic_init(GSIState *gsi_state)
 {
     DeviceState *dev;
@@ -102,6 +104,8 @@ static void pc_init1(MemoryRegion *system_memory,
     MemoryRegion *rom_memory;
     DeviceState *dev;
 
+    global_cpu_model = cpu_model;
+
     pc_cpus_init(cpu_model);
 
     if (kvmclock_enabled) {
diff --git a/sysemu.h b/sysemu.h
index ddef2bb..678b478 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -155,6 +155,8 @@ void pcie_aer_inject_error_print(Monitor *mon, const 
QObject *data);
 int do_pcie_aer_inject_error(Monitor *mon,
                              const QDict *qdict, QObject **ret_data);
 
+void qemu_system_cpu_hot_add(int cpu, int state);
+
 /* serial ports */
 
 #define MAX_SERIAL_PORTS 4
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5dd1627..a9a6136 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -931,6 +931,7 @@ void cpu_x86_update_cr4(CPUX86State *env, uint32_t new_cr4);
 /* hw/pc.c */
 void cpu_smm_update(CPUX86State *env);
 uint64_t cpu_get_tsc(CPUX86State *env);
+CPUState *pc_new_cpu(const char *cpu_model);
 
 /* used to debug */
 #define X86_DUMP_FPU  0x0001 /* dump FPU state too */
-- 
1.7.7.5




reply via email to

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