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

[Xen-devel] [PATCH 1/4] HVM vcpu add/remove: qemu logic for vcpu add/revmoe



From: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>

-- at qemu side, get vcpu_avail which used for original cpu avail map;
-- setup gpe ioread/iowrite at qmeu;
-- setup vcpu add/remove user interface through monitor;
-- setup SCI logic;

Signed-off-by: Liu, Jinsong <jinsong.liu@xxxxxxxxx>

[ PATCH 4/4 ] HVM vcpu add/remove: qemu logic for vcpu add/revmoe

Port from qemu-xen-traditionnal to qemu-xen.

Signed-off-by: Anthony PERARD <anthony.perard@xxxxxxxxxx>
---
 hmp-commands.hx |  9 +++++++
 hw/acpi_piix4.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 monitor.c       | 18 ++++++++++++++
 qemu-options.hx |  3 +++
 sysemu.h        |  3 +++
 vl.c            |  6 +++++
 6 files changed, 113 insertions(+), 1 deletion(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 010b8c9..e92f173 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1581,3 +1581,12 @@ ETEXI
 STEXI
 @end table
 ETEXI
+
+HXCOMM TODO doc
+    {
+        .name       = "cpu_set",
+        .args_type  = "cpu_index:i,status:s",
+        .params     = "cpu [online|offline]",
+        .help       = "change cpu state",
+        .mhandler.cmd = do_cpu_set_nr,
+    },
diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
index 519269a..c73dc7c 100644
--- a/hw/acpi_piix4.c
+++ b/hw/acpi_piix4.c
@@ -45,8 +45,11 @@
 #define PCI_DOWN_BASE 0xae04
 #define PCI_EJ_BASE 0xae08
 #define PCI_RMV_BASE 0xae0c
+/* ioport to monitor cpu add/remove status */
+#define PROC_BASE 0xaf00
 
 #define PIIX4_PCI_HOTPLUG_STATUS 2
+#define PIIX4_CPU_HOTPLUG_STATUS 4
 
 struct pci_status {
     uint32_t up; /* deprecated, maintained for migration compatibility */
@@ -77,6 +80,9 @@ typedef struct PIIX4PMState {
     uint8_t disable_s3;
     uint8_t disable_s4;
     uint8_t s4_val;
+
+    /* CPU bitmap */
+    uint8_t cpus_sts[32];
 } PIIX4PMState;
 
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s);
@@ -95,7 +101,7 @@ static void pm_update_sci(PIIX4PMState *s)
                    ACPI_BITMASK_GLOBAL_LOCK_ENABLE |
                    ACPI_BITMASK_TIMER_ENABLE)) != 0) ||
         (((s->ar.gpe.sts[0] & s->ar.gpe.en[0])
-          & PIIX4_PCI_HOTPLUG_STATUS) != 0);
+          & (PIIX4_PCI_HOTPLUG_STATUS|PIIX4_CPU_HOTPLUG_STATUS)) != 0);
 
     qemu_set_irq(s->irq, sci_level);
     /* schedule a timer interruption if needed */
@@ -602,11 +608,48 @@ static uint32_t pcirmv_read(void *opaque, uint32_t addr)
     return s->pci0_hotplug_enable;
 }
 
+static uint32_t gpe_cpus_readb(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    PIIX4PMState *g = opaque;
+
+    switch (addr) {
+        case PROC_BASE ... PROC_BASE+31:
+            val = g->cpus_sts[addr - PROC_BASE];
+        default:
+            break;
+    }
+
+    return val;
+}
+
+static void gpe_cpus_writeb(void *opaque, uint32_t addr, uint32_t val)
+{
+    switch (addr) {
+        case PROC_BASE ... PROC_BASE + 31:
+            /* don't allow to change cpus_sts from inside a guest */
+            break;
+        default:
+            break;
+    }
+}
+
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
                                 PCIHotplugState state);
 
+extern uint64_t vcpu_avail;
+static PIIX4PMState *acpi_state;
 static void piix4_acpi_system_hot_add_init(PCIBus *bus, PIIX4PMState *s)
 {
+    int i = 0, cpus = max_cpus;
+    char *vcpumap = (char *)&vcpu_avail;
+
+    while (cpus > 0) {
+        s->cpus_sts[i] = vcpumap[i];
+        i++;
+        cpus -= 8;
+    }
+    acpi_state = s;
 
     register_ioport_write(GPE_BASE, GPE_LEN, 1, gpe_writeb, s);
     register_ioport_read(GPE_BASE, GPE_LEN, 1,  gpe_readb, s);
@@ -620,6 +663,9 @@ static void piix4_acpi_system_hot_add_init(PCIBus *bus, 
PIIX4PMState *s)
 
     register_ioport_read(PCI_RMV_BASE, 4, 4,  pcirmv_read, s);
 
+    register_ioport_read(PROC_BASE, 32, 1,  gpe_cpus_readb, s);
+    register_ioport_write(PROC_BASE, 32, 1, gpe_cpus_writeb, s);
+
     pci_bus_hotplug(bus, piix4_device_hotplug, &s->dev.qdev);
 }
 
@@ -660,3 +706,30 @@ static int piix4_device_hotplug(DeviceState *qdev, 
PCIDevice *dev,
 
     return 0;
 }
+
+static void enable_processor(PIIX4PMState *g, int cpu)
+{
+    g->ar.gpe.sts[0] |= 4;
+    g->cpus_sts[cpu/8] |= (1 << (cpu%8));
+}
+
+static void disable_processor(PIIX4PMState *g, int cpu)
+{
+    g->ar.gpe.sts[0] |= 4;
+    g->cpus_sts[cpu/8] &= ~(1 << (cpu%8));
+}
+
+void qemu_cpu_add_remove(int cpu, int state)
+{
+    if ((cpu <=0) || (cpu >= max_cpus)) {
+        fprintf(stderr, "vcpu out of range, should be [1~%d]\n", max_cpus - 1);
+        return;
+    }
+
+    if (state)
+        enable_processor(acpi_state, cpu);
+    else
+        disable_processor(acpi_state, cpu);
+
+    pm_update_sci(acpi_state);
+}
diff --git a/monitor.c b/monitor.c
index c0e32d6..564373c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -2421,6 +2421,24 @@ int monitor_handle_fd_param(Monitor *mon, const char 
*fdname)
     return fd;
 }
 
+static void do_cpu_set_nr(Monitor *mon, const QDict *qdict)
+{
+    int cpu_index = qdict_get_int(qdict, "cpu_index");
+    const char *status = qdict_get_str(qdict, "status");
+    int state;
+
+    if (!strcmp(status, "online")) {
+        state = 1;
+    } else if (!strcmp(status, "offline")) {
+        state = 0;
+    } else {
+        monitor_printf(mon, "invalid status: %s\n", status);
+        return;
+    }
+
+    qemu_cpu_add_remove(cpu_index, state);
+}
+
 /* mon_cmds and info_cmds would be sorted at runtime */
 static mon_cmd_t mon_cmds[] = {
 #include "hmp-commands.h"
diff --git a/qemu-options.hx b/qemu-options.hx
index de43b1b..0ba668f 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -94,6 +94,9 @@ given, the total number of CPUs @var{n} can be omitted. 
@var{maxcpus}
 specifies the maximum number of hotpluggable CPUs.
 ETEXI
 
+DEF("vcpu_avail", HAS_ARG, QEMU_OPTION_vcpu_avail,
+    "-vcpu_avail bitmap\n", QEMU_ARCH_ALL)
+
 DEF("numa", HAS_ARG, QEMU_OPTION_numa,
     "-numa node[,mem=size][,cpus=cpu[-cpu]][,nodeid=node]\n", QEMU_ARCH_ALL)
 STEXI
diff --git a/sysemu.h b/sysemu.h
index f5ac664..ed7b264 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -149,6 +149,9 @@ int pci_drive_hot_add(Monitor *mon, const QDict *qdict,
                       DriveInfo *dinfo, int type);
 void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 
+/* cpu hotplug */
+void qemu_cpu_add_remove(int cpu, int state);
+
 /* generic hotplug */
 void drive_hot_add(Monitor *mon, const QDict *qdict);
 
diff --git a/vl.c b/vl.c
index a3ab384..27ae6c1 100644
--- a/vl.c
+++ b/vl.c
@@ -207,6 +207,7 @@ int win2k_install_hack = 0;
 int singlestep = 0;
 int smp_cpus = 1;
 int max_cpus = 0;
+uint64_t vcpu_avail = 1;
 int smp_cores = 1;
 int smp_threads = 1;
 #ifdef CONFIG_VNC
@@ -3302,6 +3303,11 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 break;
+            case QEMU_OPTION_vcpu_avail:
+                vcpu_avail = atol(optarg);
+                fprintf(stderr, "qemu: the avail cpu bitmap is %lx\n",
+                        vcpu_avail);
+                break;
            case QEMU_OPTION_vnc:
 #ifdef CONFIG_VNC
                 display_remote++;
-- 
Anthony PERARD


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.