]> xenbits.xensource.com Git - qemu-xen-4.4-testing.git/commitdiff
HVM vcpu add/remove: qemu logic for vcpu add/revmoe
authorIan Jackson <ian.jackson@eu.citrix.com>
Mon, 4 Jan 2010 17:12:44 +0000 (17:12 +0000)
committerIan Jackson <Ian.Jackson@eu.citrix.com>
Mon, 4 Jan 2010 17:12:44 +0000 (17:12 +0000)
-- 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@intel.com>
[ PATCH 4/4 ] HVM vcpu add/remove: qemu logic for vcpu add/revmoe

hw/piix4acpi.c
i386-dm/helper2.c
monitor.c
sysemu.h
vl.c
xen-config-host.h

index 599d00d28d232b4ab51573a73db34da80614d203..ccbdf84d7c87e511a7a2b2ded695ca50892054c1 100644 (file)
@@ -69,6 +69,9 @@
 #define DEVFN_TO_PHP_SLOT_REG(devfn) (devfn >> 1)
 #define PHP_SLOT_REG_TO_DEVFN(reg, hilo) ((reg << 1) | hilo)
 
+/* ioport to monitor cpu add/remove status */
+#define PROC_BASE 0xaf00
+
 typedef struct PCIAcpiState {
     PCIDevice dev;
     uint16_t pm1_control; /* pm1a_ECNT_BLK */
@@ -79,6 +82,9 @@ typedef struct GPEState {
     uint8_t gpe0_sts[ACPI_GPE0_BLK_LEN / 2];
     uint8_t gpe0_en[ACPI_GPE0_BLK_LEN / 2];
 
+    /* CPU bitmap */
+    uint8_t cpus_sts[32];
+
     /* SCI IRQ level */
     uint8_t sci_asserted;
 
@@ -480,10 +486,48 @@ static int gpe_load(QEMUFile* f, void* opaque, int version_id)
     return 0;
 }
 
+static uint32_t gpe_cpus_readb(void *opaque, uint32_t addr)
+{
+    uint32_t val = 0;
+    GPEState *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)
+{
+    GPEState *g = opaque;
+    switch (addr) {
+        case PROC_BASE ... PROC_BASE + 31:
+            /* don't allow to change cpus_sts from inside a guest */
+            break;
+        default:
+            break;
+    }
+}
+
 static void gpe_acpi_init(void)
 {
     GPEState *s = &gpe_state;
     memset(s, 0, sizeof(GPEState));
+    int i = 0, cpus = vcpus;
+    char *vcpumap = (char *)&vcpu_avail;
+
+    while (cpus > 0) {
+        s->cpus_sts[i] = vcpumap[i];
+        i++;
+        cpus -= 8;
+    }
+
+    register_ioport_read(PROC_BASE, 32, 1,  gpe_cpus_readb, s);
+    register_ioport_write(PROC_BASE, 32, 1, gpe_cpus_writeb, s);
 
     register_ioport_read(ACPI_GPE0_BLK_ADDRESS,
                          ACPI_GPE0_BLK_LEN / 2,
@@ -682,3 +726,33 @@ void qemu_system_device_hot_add(int bus, int devfn, int state) {
 void i440fx_init_memory_mappings(PCIDevice *d) {
     /* our implementation doesn't need this */
 }
+
+static void enable_processor(GPEState *g, int cpu)
+{
+    g->gpe0_sts[0] |= 4;
+    g->cpus_sts[cpu/8] |= (1 << (cpu%8));
+}
+
+static void disable_processor(GPEState *g, int cpu)
+{
+    g->gpe0_sts[0] |= 4;
+    g->cpus_sts[cpu/8] &= ~(1 << (cpu%8));
+}
+
+void qemu_cpu_add_remove(int cpu, int state)
+{
+    if ((cpu <=0) || (cpu >= vcpus)) {
+        fprintf(stderr, "vcpu out of range, should be [1~%d]\n", vcpus - 1);
+        return;
+    }
+
+    if (state)
+        enable_processor(&gpe_state, cpu);
+    else
+        disable_processor(&gpe_state, cpu);
+
+    if (gpe_state.gpe0_en[0] & 4) {
+        qemu_set_irq(sci_irq, 1);
+        qemu_set_irq(sci_irq, 0);
+    }
+}
index 7fe03b0468c4f3839879b0d55cf81a045a307853..090202b76a268acec6f5042be1097059d89a62ca 100644 (file)
@@ -78,6 +78,7 @@ _syscall3(int, modify_ldt, int, func, void *, ptr, unsigned long, bytecount)
 
 int domid = -1;
 int vcpus = 1;
+uint64_t vcpu_avail = 1;
 
 int xc_handle = -1;
 
index c8fcab77b8a453a2f85ba6ada75c46248176537c..8915a6ed67d0d5297d4a6d0327f65e45891c4971 100644 (file)
--- a/monitor.c
+++ b/monitor.c
@@ -1473,6 +1473,22 @@ static void do_info_balloon(void)
         term_printf("balloon: actual=%d\n", (int)(actual >> 20));
 }
 
+static void do_cpu_set_nr(int value, const char *status)
+{
+    int state;
+
+    if (!strcmp(status, "online"))
+        state = 1;
+    else if (!strcmp(status, "offline"))
+        state = 0;
+    else {
+        term_printf("invalid status: %s\n", status);
+        return;
+    }
+
+    qemu_cpu_add_remove(value, state);
+}
+
 /* Please update qemu-doc.texi when adding or changing commands */
 static const term_cmd_t term_cmds[] = {
     { "help|?", "s?", do_help,
@@ -1583,6 +1599,8 @@ static const term_cmd_t term_cmds[] = {
       "target", "request VM to change it's memory allocation (in MB)" },
     { "set_link", "ss", do_set_link,
       "name [up|down]", "change the link status of a network adapter" },
+    { "cpu_set", "is", do_cpu_set_nr,
+      "cpu [online|offline]", "change cpu state" },
     { NULL, NULL, },
 };
 
index d4e7514bbe9773b5f204268ab796d8b3cdeb31d0..87b278bae071f618079b1574e7a32785b27cd463 100644 (file)
--- a/sysemu.h
+++ b/sysemu.h
@@ -173,6 +173,7 @@ extern int drive_add(const char *file, const char *fmt, ...);
 extern int drive_init(struct drive_opt *arg, int snapshot, void *machine);
 
 /* acpi */
+void qemu_cpu_add_remove(int cpu, int state);
 void qemu_system_hot_add_init(void);
 void qemu_system_device_hot_add(int pcibus, int slot, int state);
 
diff --git a/vl.c b/vl.c
index ce5740572fdb719b188741e405cf3a96f00e9d37..cb31e5ad466a5738c8612bbf9a1639ad99c3560c 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -4279,6 +4279,7 @@ enum {
     QEMU_OPTION_domainname,
     QEMU_OPTION_acpi,
     QEMU_OPTION_vcpus,
+    QEMU_OPTION_vcpu_avail,
 
     /* Debug/Expert options: */
     QEMU_OPTION_serial,
@@ -4453,6 +4454,7 @@ static const QEMUOption qemu_options[] = {
     { "pciemulation", HAS_ARG, QEMU_OPTION_pci_emulation },
     { "vncunused", 0, QEMU_OPTION_vncunused },
     { "vcpus", HAS_ARG, QEMU_OPTION_vcpus },
+    { "vcpu_avail", HAS_ARG, QEMU_OPTION_vcpu_avail },
 #if defined(CONFIG_XEN) && !defined(CONFIG_DM)
     { "xen-domid", HAS_ARG, QEMU_OPTION_xen_domid },
     { "xen-create", 0, QEMU_OPTION_xen_create },
@@ -5298,6 +5300,11 @@ int main(int argc, char **argv, char **envp)
                 vcpus = atoi(optarg);
                 fprintf(logfile, "qemu: the number of cpus is %d\n", vcpus);
                 break;
+            case QEMU_OPTION_vcpu_avail:
+                vcpu_avail = atol(optarg);
+                fprintf(logfile, "qemu: the avail cpu bitmap is %lx\n",  
+                                  vcpu_avail);
+                break;
             case QEMU_OPTION_acpi:
                 acpi_enabled = 1;
                 break;
index 3a04df9fe054ecc6f7a4d056e5de33bf36980f96..e3f546a32607b819541ac6b86105788339ca2b49 100644 (file)
@@ -31,6 +31,7 @@ void main_loop_prepare(void);
 extern int xc_handle;
 extern int xen_pause_requested;
 extern int vcpus;
+extern uint64_t vcpu_avail;
 
 #ifdef CONFIG_STUBDOM
 #define bdrv_host_device bdrv_raw