All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support
@ 2013-10-09  9:43 Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 01/10] x86: move apic_state field from CPUX86State to X86CPU Chen Fan
                   ` (10 more replies)
  0 siblings, 11 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Via implementing ACPI standard methods _EJ0 in bios, after Guest OS hot remove
one vCPU, it is able to send a signal to QEMU, then QEMU could notify
the assigned vCPU of exiting. meanwhile, and intruduce the QOM command 'cpu-del' to remove
vCPU from QEMU itself.

this work is based on Andreas Färber's qom-cpu branch tree.
    git://github.com/afaerber/qemu-cpu.git

this series patches must be used with seabios patch and KVM patch together.

for KVM patches:
    http://comments.gmane.org/gmane.comp.emulators.kvm.devel/114347

for seabios patches:
    http://comments.gmane.org/gmane.comp.emulators.qemu/230460

Chen Fan (10):
  x86: move apic_state field from CPUX86State to X86CPU
  apic: remove redundant variable 'apic_no' from apic_init_common()
  apic: remove local_apics array and using CPU_FOREACH instead
  x86: add x86_cpu_unrealizefn() for cpu apic remove
  qmp: add 'cpu-del' command support
  qom cpu: rename variable 'cpu_added_notifier' to
    'cpu_hotplug_notifier'
  qom cpu: add UNPLUG cpu notifier support
  i386: implement pc interface pc_hot_del_cpu()
  piix4: implement function cpu_status_write() for vcpu ejection
  cpus: reclaim allocated vCPU objects

 cpu-exec.c                      |  2 +-
 cpus.c                          | 51 +++++++++++++++++++++--
 hw/acpi/piix4.c                 | 66 ++++++++++++++++++++++++------
 hw/i386/kvm/apic.c              | 18 +++++++-
 hw/i386/kvmvapic.c              |  8 ++--
 hw/i386/pc.c                    | 51 ++++++++++++++++++-----
 hw/i386/pc_piix.c               |  3 +-
 hw/intc/apic.c                  | 91 ++++++++++++++++++++++-------------------
 hw/intc/apic_common.c           | 17 ++------
 include/hw/boards.h             |  2 +
 include/hw/i386/apic_internal.h |  6 +--
 include/hw/i386/pc.h            |  1 +
 include/qom/cpu.h               | 20 +++++++++
 include/sysemu/kvm.h            |  1 +
 include/sysemu/sysemu.h         |  2 +-
 kvm-all.c                       | 25 +++++++++++
 qapi-schema.json                | 12 ++++++
 qmp-commands.hx                 | 23 +++++++++++
 qmp.c                           |  9 ++++
 qom/cpu.c                       | 26 +++++++++---
 target-i386/cpu-qom.h           |  5 +++
 target-i386/cpu.c               | 57 ++++++++++++++++++++------
 target-i386/cpu.h               |  4 --
 target-i386/helper.c            |  9 ++--
 target-i386/kvm.c               | 23 +++++------
 target-i386/misc_helper.c       |  8 ++--
 26 files changed, 403 insertions(+), 137 deletions(-)

-- 
1.8.1.4


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

* [Qemu-devel] [RFC qom-cpu v4 01/10] x86: move apic_state field from CPUX86State to X86CPU
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 02/10] apic: remove redundant variable 'apic_no' from apic_init_common() Chen Fan
                   ` (9 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

This motion is preparing for refactoring vCPU apic subsequently.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 cpu-exec.c                |  2 +-
 cpus.c                    |  5 ++---
 hw/i386/kvmvapic.c        |  8 +++-----
 hw/i386/pc.c              | 17 ++++++++---------
 target-i386/cpu-qom.h     |  4 ++++
 target-i386/cpu.c         | 22 ++++++++++------------
 target-i386/cpu.h         |  4 ----
 target-i386/helper.c      |  9 ++++-----
 target-i386/kvm.c         | 23 ++++++++++-------------
 target-i386/misc_helper.c |  8 ++++----
 10 files changed, 46 insertions(+), 56 deletions(-)

diff --git a/cpu-exec.c b/cpu-exec.c
index 30cfa2a..2711c58 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -320,7 +320,7 @@ int cpu_exec(CPUArchState *env)
 #if !defined(CONFIG_USER_ONLY)
                     if (interrupt_request & CPU_INTERRUPT_POLL) {
                         cpu->interrupt_request &= ~CPU_INTERRUPT_POLL;
-                        apic_poll_irq(env->apic_state);
+                        apic_poll_irq(x86_env_get_cpu(env)->apic_state);
                     }
 #endif
                     if (interrupt_request & CPU_INTERRUPT_INIT) {
diff --git a/cpus.c b/cpus.c
index e566297..4ace860 100644
--- a/cpus.c
+++ b/cpus.c
@@ -1383,12 +1383,11 @@ void qmp_inject_nmi(Error **errp)
 
     CPU_FOREACH(cs) {
         X86CPU *cpu = X86_CPU(cs);
-        CPUX86State *env = &cpu->env;
 
-        if (!env->apic_state) {
+        if (!cpu->apic_state) {
             cpu_interrupt(cs, CPU_INTERRUPT_NMI);
         } else {
-            apic_deliver_nmi(env->apic_state);
+            apic_deliver_nmi(cpu->apic_state);
         }
     }
 #elif defined(TARGET_S390X)
diff --git a/hw/i386/kvmvapic.c b/hw/i386/kvmvapic.c
index 1c2dbf5..9fa346b 100644
--- a/hw/i386/kvmvapic.c
+++ b/hw/i386/kvmvapic.c
@@ -366,7 +366,7 @@ static int vapic_enable(VAPICROMState *s, X86CPU *cpu)
         (((hwaddr)cpu_number) << VAPIC_CPU_SHIFT);
     cpu_physical_memory_rw(vapic_paddr + offsetof(VAPICState, enabled),
                            (void *)&enabled, sizeof(enabled), 1);
-    apic_enable_vapic(cpu->env.apic_state, vapic_paddr);
+    apic_enable_vapic(cpu->apic_state, vapic_paddr);
 
     s->state = VAPIC_ACTIVE;
 
@@ -496,12 +496,10 @@ static void vapic_enable_tpr_reporting(bool enable)
     };
     CPUState *cs;
     X86CPU *cpu;
-    CPUX86State *env;
 
     CPU_FOREACH(cs) {
         cpu = X86_CPU(cs);
-        env = &cpu->env;
-        info.apic = env->apic_state;
+        info.apic = cpu->apic_state;
         run_on_cpu(cs, vapic_do_enable_tpr_reporting, &info);
     }
 }
@@ -697,7 +695,7 @@ static void vapic_write(void *opaque, hwaddr addr, uint64_t data,
     default:
     case 4:
         if (!kvm_irqchip_in_kernel()) {
-            apic_poll_irq(env->apic_state);
+            apic_poll_irq(cpu->apic_state);
         }
         break;
     }
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 0c313fe..832c9b2 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -169,13 +169,14 @@ void cpu_smm_update(CPUX86State *env)
 int cpu_get_pic_interrupt(CPUX86State *env)
 {
     int intno;
+    X86CPU *cpu = x86_env_get_cpu(env);
 
-    intno = apic_get_interrupt(env->apic_state);
+    intno = apic_get_interrupt(cpu->apic_state);
     if (intno >= 0) {
         return intno;
     }
     /* read the irq from the PIC */
-    if (!apic_accept_pic_intr(env->apic_state)) {
+    if (!apic_accept_pic_intr(cpu->apic_state)) {
         return -1;
     }
 
@@ -187,15 +188,13 @@ static void pic_irq_request(void *opaque, int irq, int level)
 {
     CPUState *cs = first_cpu;
     X86CPU *cpu = X86_CPU(cs);
-    CPUX86State *env = &cpu->env;
 
     DPRINTF("pic_irqs: %s irq %d\n", level? "raise" : "lower", irq);
-    if (env->apic_state) {
+    if (cpu->apic_state) {
         CPU_FOREACH(cs) {
             cpu = X86_CPU(cs);
-            env = &cpu->env;
-            if (apic_accept_pic_intr(env->apic_state)) {
-                apic_deliver_pic_intr(env->apic_state, level);
+            if (apic_accept_pic_intr(cpu->apic_state)) {
+                apic_deliver_pic_intr(cpu->apic_state, level);
             }
         }
     } else {
@@ -890,7 +889,7 @@ DeviceState *cpu_get_current_apic(void)
 {
     if (current_cpu) {
         X86CPU *cpu = X86_CPU(current_cpu);
-        return cpu->env.apic_state;
+        return cpu->apic_state;
     } else {
         return NULL;
     }
@@ -984,7 +983,7 @@ void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
     }
 
     /* map APIC MMIO area if CPU has APIC */
-    if (cpu && cpu->env.apic_state) {
+    if (cpu && cpu->apic_state) {
         /* XXX: what if the base changes? */
         sysbus_mmio_map_overlap(SYS_BUS_DEVICE(icc_bridge), 0,
                                 APIC_DEFAULT_ADDRESS, 0x1000);
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index f4fab15..775c82d 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -66,6 +66,10 @@ typedef struct X86CPU {
 
     CPUX86State env;
 
+    /* in order to simplify APIC support, we leave this pointer to the
+       user */
+    struct DeviceState *apic_state;
+
     bool hyperv_vapic;
     bool hyperv_relaxed_timing;
     int hyperv_spinlock_attempts;
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index d0c9bdb..c9d5626 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2415,7 +2415,7 @@ static void x86_cpu_reset(CPUState *s)
 #if !defined(CONFIG_USER_ONLY)
     /* We hard-wire the BSP to the first CPU. */
     if (s->cpu_index == 0) {
-        apic_designate_bsp(env->apic_state);
+        apic_designate_bsp(cpu->apic_state);
     }
 
     s->halted = !cpu_is_bsp(cpu);
@@ -2425,7 +2425,7 @@ static void x86_cpu_reset(CPUState *s)
 #ifndef CONFIG_USER_ONLY
 bool cpu_is_bsp(X86CPU *cpu)
 {
-    return cpu_get_apic_base(cpu->env.apic_state) & MSR_IA32_APICBASE_BSP;
+    return cpu_get_apic_base(cpu->apic_state) & MSR_IA32_APICBASE_BSP;
 }
 
 /* TODO: remove me, when reset over QOM tree is implemented */
@@ -2466,31 +2466,29 @@ static void x86_cpu_apic_create(X86CPU *cpu, Error **errp)
         apic_type = "xen-apic";
     }
 
-    env->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
-    if (env->apic_state == NULL) {
+    cpu->apic_state = qdev_try_create(qdev_get_parent_bus(dev), apic_type);
+    if (cpu->apic_state == NULL) {
         error_setg(errp, "APIC device '%s' could not be created", apic_type);
         return;
     }
 
     object_property_add_child(OBJECT(cpu), "apic",
-                              OBJECT(env->apic_state), NULL);
-    qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id);
+                              OBJECT(cpu->apic_state), NULL);
+    qdev_prop_set_uint8(cpu->apic_state, "id", env->cpuid_apic_id);
     /* TODO: convert to link<> */
-    apic = APIC_COMMON(env->apic_state);
+    apic = APIC_COMMON(cpu->apic_state);
     apic->cpu = cpu;
 }
 
 static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
 {
-    CPUX86State *env = &cpu->env;
-
-    if (env->apic_state == NULL) {
+    if (cpu->apic_state == NULL) {
         return;
     }
 
-    if (qdev_init(env->apic_state)) {
+    if (qdev_init(cpu->apic_state)) {
         error_setg(errp, "APIC device '%s' could not be initialized",
-                   object_get_typename(OBJECT(env->apic_state)));
+                   object_get_typename(OBJECT(cpu->apic_state)));
         return;
     }
 }
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 5723eff..fdc0f81 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -891,10 +891,6 @@ typedef struct CPUX86State {
     int tsc_khz;
     void *kvm_xsave_buf;
 
-    /* in order to simplify APIC support, we leave this pointer to the
-       user */
-    struct DeviceState *apic_state;
-
     uint64_t mcg_cap;
     uint64_t mcg_ctl;
     uint64_t mce_banks[MCE_BANKS_DEF*4];
diff --git a/target-i386/helper.c b/target-i386/helper.c
index 7c196ff..f2e76ad 100644
--- a/target-i386/helper.c
+++ b/target-i386/helper.c
@@ -1248,7 +1248,8 @@ void cpu_report_tpr_access(CPUX86State *env, TPRAccess access)
     } else {
         cpu_restore_state(env, env->mem_io_pc);
 
-        apic_handle_tpr_access_report(env->apic_state, env->eip, access);
+        apic_handle_tpr_access_report(x86_env_get_cpu(env)->apic_state,
+                                      env->eip, access);
     }
 }
 #endif /* !CONFIG_USER_ONLY */
@@ -1295,14 +1296,12 @@ void do_cpu_init(X86CPU *cpu)
     cpu_reset(cs);
     cs->interrupt_request = sipi;
     env->pat = pat;
-    apic_init_reset(env->apic_state);
+    apic_init_reset(cpu->apic_state);
 }
 
 void do_cpu_sipi(X86CPU *cpu)
 {
-    CPUX86State *env = &cpu->env;
-
-    apic_sipi(env->apic_state);
+    apic_sipi(cpu->apic_state);
 }
 #else
 void do_cpu_init(X86CPU *cpu)
diff --git a/target-i386/kvm.c b/target-i386/kvm.c
index 749aa09..db2f218 100644
--- a/target-i386/kvm.c
+++ b/target-i386/kvm.c
@@ -1074,8 +1074,8 @@ static int kvm_put_sregs(X86CPU *cpu)
     sregs.cr3 = env->cr[3];
     sregs.cr4 = env->cr[4];
 
-    sregs.cr8 = cpu_get_apic_tpr(env->apic_state);
-    sregs.apic_base = cpu_get_apic_base(env->apic_state);
+    sregs.cr8 = cpu_get_apic_tpr(cpu->apic_state);
+    sregs.apic_base = cpu_get_apic_base(cpu->apic_state);
 
     sregs.efer = env->efer;
 
@@ -1624,8 +1624,7 @@ static int kvm_get_mp_state(X86CPU *cpu)
 
 static int kvm_get_apic(X86CPU *cpu)
 {
-    CPUX86State *env = &cpu->env;
-    DeviceState *apic = env->apic_state;
+    DeviceState *apic = cpu->apic_state;
     struct kvm_lapic_state kapic;
     int ret;
 
@@ -1642,8 +1641,7 @@ static int kvm_get_apic(X86CPU *cpu)
 
 static int kvm_put_apic(X86CPU *cpu)
 {
-    CPUX86State *env = &cpu->env;
-    DeviceState *apic = env->apic_state;
+    DeviceState *apic = cpu->apic_state;
     struct kvm_lapic_state kapic;
 
     if (apic && kvm_irqchip_in_kernel()) {
@@ -1967,7 +1965,7 @@ void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run)
         }
 
         DPRINTF("setting tpr\n");
-        run->cr8 = cpu_get_apic_tpr(env->apic_state);
+        run->cr8 = cpu_get_apic_tpr(x86_cpu->apic_state);
     }
 }
 
@@ -1981,8 +1979,8 @@ void kvm_arch_post_run(CPUState *cpu, struct kvm_run *run)
     } else {
         env->eflags &= ~IF_MASK;
     }
-    cpu_set_apic_tpr(env->apic_state, run->cr8);
-    cpu_set_apic_base(env->apic_state, run->apic_base);
+    cpu_set_apic_tpr(x86_cpu->apic_state, run->cr8);
+    cpu_set_apic_base(x86_cpu->apic_state, run->apic_base);
 }
 
 int kvm_arch_process_async_events(CPUState *cs)
@@ -2019,7 +2017,7 @@ int kvm_arch_process_async_events(CPUState *cs)
 
     if (cs->interrupt_request & CPU_INTERRUPT_POLL) {
         cs->interrupt_request &= ~CPU_INTERRUPT_POLL;
-        apic_poll_irq(env->apic_state);
+        apic_poll_irq(cpu->apic_state);
     }
     if (((cs->interrupt_request & CPU_INTERRUPT_HARD) &&
          (env->eflags & IF_MASK)) ||
@@ -2037,7 +2035,7 @@ int kvm_arch_process_async_events(CPUState *cs)
     if (cs->interrupt_request & CPU_INTERRUPT_TPR) {
         cs->interrupt_request &= ~CPU_INTERRUPT_TPR;
         kvm_cpu_synchronize_state(cs);
-        apic_handle_tpr_access_report(env->apic_state, env->eip,
+        apic_handle_tpr_access_report(cpu->apic_state, env->eip,
                                       env->tpr_access_type);
     }
 
@@ -2061,11 +2059,10 @@ static int kvm_handle_halt(X86CPU *cpu)
 
 static int kvm_handle_tpr_access(X86CPU *cpu)
 {
-    CPUX86State *env = &cpu->env;
     CPUState *cs = CPU(cpu);
     struct kvm_run *run = cs->kvm_run;
 
-    apic_handle_tpr_access_report(env->apic_state, run->tpr_access.rip,
+    apic_handle_tpr_access_report(cpu->apic_state, run->tpr_access.rip,
                                   run->tpr_access.is_write ? TPR_ACCESS_WRITE
                                                            : TPR_ACCESS_READ);
     return 1;
diff --git a/target-i386/misc_helper.c b/target-i386/misc_helper.c
index 93933fd..52424f4 100644
--- a/target-i386/misc_helper.c
+++ b/target-i386/misc_helper.c
@@ -155,7 +155,7 @@ target_ulong helper_read_crN(CPUX86State *env, int reg)
         break;
     case 8:
         if (!(env->hflags2 & HF2_VINTR_MASK)) {
-            val = cpu_get_apic_tpr(env->apic_state);
+            val = cpu_get_apic_tpr(x86_env_get_cpu(env)->apic_state);
         } else {
             val = env->v_tpr;
         }
@@ -179,7 +179,7 @@ void helper_write_crN(CPUX86State *env, int reg, target_ulong t0)
         break;
     case 8:
         if (!(env->hflags2 & HF2_VINTR_MASK)) {
-            cpu_set_apic_tpr(env->apic_state, t0);
+            cpu_set_apic_tpr(x86_env_get_cpu(env)->apic_state, t0);
         }
         env->v_tpr = t0 & 0x0f;
         break;
@@ -286,7 +286,7 @@ void helper_wrmsr(CPUX86State *env)
         env->sysenter_eip = val;
         break;
     case MSR_IA32_APICBASE:
-        cpu_set_apic_base(env->apic_state, val);
+        cpu_set_apic_base(x86_env_get_cpu(env)->apic_state, val);
         break;
     case MSR_EFER:
         {
@@ -437,7 +437,7 @@ void helper_rdmsr(CPUX86State *env)
         val = env->sysenter_eip;
         break;
     case MSR_IA32_APICBASE:
-        val = cpu_get_apic_base(env->apic_state);
+        val = cpu_get_apic_base(x86_env_get_cpu(env)->apic_state);
         break;
     case MSR_EFER:
         val = env->efer;
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 02/10] apic: remove redundant variable 'apic_no' from apic_init_common()
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 01/10] x86: move apic_state field from CPUX86State to X86CPU Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 03/10] apic: remove local_apics array and using CPU_FOREACH instead Chen Fan
                   ` (8 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

In struct APICCommonState, there is an id field yet, which was set earlier,
qdev_prop_set_uint8(env->apic_state, "id", env->cpuid_apic_id);
so we use the id field instead of the variable 'apic_no' to represent the unique apic
index.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/intc/apic_common.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index a0beb10..82fbb7f 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -289,13 +289,9 @@ static int apic_init_common(ICCDevice *dev)
     APICCommonState *s = APIC_COMMON(dev);
     APICCommonClass *info;
     static DeviceState *vapic;
-    static int apic_no;
     static bool mmio_registered;
 
-    if (apic_no >= MAX_APICS) {
-        return -1;
-    }
-    s->idx = apic_no++;
+    s->idx = s->id;
 
     info = APIC_COMMON_GET_CLASS(s);
     info->init(s);
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 03/10] apic: remove local_apics array and using CPU_FOREACH instead
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 01/10] x86: move apic_state field from CPUX86State to X86CPU Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 02/10] apic: remove redundant variable 'apic_no' from apic_init_common() Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 04/10] x86: add x86_cpu_unrealizefn() for cpu apic remove Chen Fan
                   ` (7 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Using CPU_FOREACH() marco instead of scaning the entire
local_apics array for fast searching apic.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/intc/apic.c                  | 73 ++++++++++++++++++-----------------------
 include/hw/i386/apic_internal.h |  2 --
 2 files changed, 32 insertions(+), 43 deletions(-)

diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index a913186..f8f2cbf 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -32,8 +32,6 @@
 #define SYNC_TO_VAPIC                   0x2
 #define SYNC_ISR_IRR_TO_VAPIC           0x4
 
-static APICCommonState *local_apics[MAX_APICS + 1];
-
 static void apic_set_irq(APICCommonState *s, int vector_num, int trigger_mode);
 static void apic_update_irq(APICCommonState *s);
 static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
@@ -200,18 +198,15 @@ static void apic_external_nmi(APICCommonState *s)
 
 #define foreach_apic(apic, deliver_bitmask, code) \
 {\
+    CPUState *cpu;\
     int __i, __j, __mask;\
-    for(__i = 0; __i < MAX_APIC_WORDS; __i++) {\
+    CPU_FOREACH(cpu) {\
+        apic = APIC_COMMON(X86_CPU(cpu)->apic_state);\
+        __i = apic->idx / 32;\
+        __j = apic->idx % 32;\
         __mask = deliver_bitmask[__i];\
-        if (__mask) {\
-            for(__j = 0; __j < 32; __j++) {\
-                if (__mask & (1 << __j)) {\
-                    apic = local_apics[__i * 32 + __j];\
-                    if (apic) {\
-                        code;\
-                    }\
-                }\
-            }\
+        if (__mask & (1 << __j)) {\
+            code;\
         }\
     }\
 }
@@ -235,9 +230,13 @@ static void apic_bus_deliver(const uint32_t *deliver_bitmask,
                     }
                 }
                 if (d >= 0) {
-                    apic_iter = local_apics[d];
-                    if (apic_iter) {
-                        apic_set_irq(apic_iter, vector_num, trigger_mode);
+                    CPUState *cpu;
+                    CPU_FOREACH(cpu) {
+                        apic_iter = APIC_COMMON(X86_CPU(cpu)->apic_state);
+                        if (apic_iter->idx == d) {
+                            apic_set_irq(apic_iter, vector_num, trigger_mode);
+                            break;
+                        }
                     }
                 }
             }
@@ -422,18 +421,14 @@ static void apic_eoi(APICCommonState *s)
 
 static int apic_find_dest(uint8_t dest)
 {
-    APICCommonState *apic = local_apics[dest];
-    int i;
-
-    if (apic && apic->id == dest)
-        return dest;  /* shortcut in case apic->id == apic->idx */
+    APICCommonState *apic;
+    CPUState *cpu;
 
-    for (i = 0; i < MAX_APICS; i++) {
-        apic = local_apics[i];
-	if (apic && apic->id == dest)
-            return i;
-        if (!apic)
-            break;
+    CPU_FOREACH(cpu) {
+        apic = APIC_COMMON(X86_CPU(cpu)->apic_state);
+        if (apic->id == dest) {
+            return apic->idx;
+        }
     }
 
     return -1;
@@ -443,7 +438,7 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
                                       uint8_t dest, uint8_t dest_mode)
 {
     APICCommonState *apic_iter;
-    int i;
+    CPUState *cpu;
 
     if (dest_mode == 0) {
         if (dest == 0xff) {
@@ -457,20 +452,17 @@ static void apic_get_delivery_bitmask(uint32_t *deliver_bitmask,
     } else {
         /* XXX: cluster mode */
         memset(deliver_bitmask, 0x00, MAX_APIC_WORDS * sizeof(uint32_t));
-        for(i = 0; i < MAX_APICS; i++) {
-            apic_iter = local_apics[i];
-            if (apic_iter) {
-                if (apic_iter->dest_mode == 0xf) {
-                    if (dest & apic_iter->log_dest)
-                        apic_set_bit(deliver_bitmask, i);
-                } else if (apic_iter->dest_mode == 0x0) {
-                    if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
-                        (dest & apic_iter->log_dest & 0x0f)) {
-                        apic_set_bit(deliver_bitmask, i);
-                    }
+        CPU_FOREACH(cpu) {
+            apic_iter = APIC_COMMON(X86_CPU(cpu)->apic_state);
+            if (apic_iter->dest_mode == 0xf) {
+                if (dest & apic_iter->log_dest) {
+                    apic_set_bit(deliver_bitmask, apic_iter->idx);
+                }
+            } else if (apic_iter->dest_mode == 0x0) {
+                if ((dest & 0xf0) == (apic_iter->log_dest & 0xf0) &&
+                    (dest & apic_iter->log_dest & 0x0f)) {
+                    apic_set_bit(deliver_bitmask, apic_iter->idx);
                 }
-            } else {
-                break;
             }
         }
     }
@@ -877,7 +869,6 @@ static void apic_init(APICCommonState *s)
                           APIC_SPACE_SIZE);
 
     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
-    local_apics[s->idx] = s;
 
     msi_supported = true;
 }
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 1b0a7fb..5b763ac 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -64,8 +64,6 @@
 #define VAPIC_ENABLE_BIT                0
 #define VAPIC_ENABLE_MASK               (1 << VAPIC_ENABLE_BIT)
 
-#define MAX_APICS 255
-
 typedef struct APICCommonState APICCommonState;
 
 #define TYPE_APIC_COMMON "apic-common"
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 04/10] x86: add x86_cpu_unrealizefn() for cpu apic remove
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (2 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 03/10] apic: remove local_apics array and using CPU_FOREACH instead Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support Chen Fan
                   ` (6 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Implement x86_cpu_unrealizefn() for corresponding x86_cpu_realizefn(),
which is mostly used to clear the apic related information at here.
and refactor apic initialization, use QOM realizefn.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/i386/kvm/apic.c              | 18 ++++++++++++++++--
 hw/intc/apic.c                  | 18 ++++++++++++++++--
 hw/intc/apic_common.c           | 11 +++--------
 include/hw/i386/apic_internal.h |  4 +++-
 target-i386/cpu-qom.h           |  1 +
 target-i386/cpu.c               | 35 +++++++++++++++++++++++++++++++++++
 6 files changed, 74 insertions(+), 13 deletions(-)

diff --git a/hw/i386/kvm/apic.c b/hw/i386/kvm/apic.c
index 5609063..87f1cce 100644
--- a/hw/i386/kvm/apic.c
+++ b/hw/i386/kvm/apic.c
@@ -171,21 +171,35 @@ static const MemoryRegionOps kvm_apic_io_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void kvm_apic_init(APICCommonState *s)
+static void kvm_apic_realize(DeviceState *dev, Error **errp)
 {
+    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonClass *acc = APIC_COMMON_GET_CLASS(s);
+
     memory_region_init_io(&s->io_memory, NULL, &kvm_apic_io_ops, s, "kvm-apic-msi",
                           APIC_SPACE_SIZE);
 
     if (kvm_has_gsi_routing()) {
         msi_supported = true;
     }
+
+    acc->parent_realize(dev, errp);
+}
+
+static void kvm_apic_unrealize(DeviceState *dev, Error **errp)
+{
+    APICCommonState *s = APIC_COMMON(dev);
+    memory_region_destroy(&s->io_memory);
 }
 
 static void kvm_apic_class_init(ObjectClass *klass, void *data)
 {
     APICCommonClass *k = APIC_COMMON_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = kvm_apic_init;
+    k->parent_realize = dc->realize;
+    dc->realize = kvm_apic_realize;
+    dc->unrealize = kvm_apic_unrealize;
     k->set_base = kvm_apic_set_base;
     k->set_tpr = kvm_apic_set_tpr;
     k->get_tpr = kvm_apic_get_tpr;
diff --git a/hw/intc/apic.c b/hw/intc/apic.c
index f8f2cbf..c022640 100644
--- a/hw/intc/apic.c
+++ b/hw/intc/apic.c
@@ -863,21 +863,35 @@ static const MemoryRegionOps apic_io_ops = {
     .endianness = DEVICE_NATIVE_ENDIAN,
 };
 
-static void apic_init(APICCommonState *s)
+static void apic_realize(DeviceState *dev, Error **errp)
 {
+    APICCommonState *s = APIC_COMMON(dev);
+    APICCommonClass *acc = APIC_COMMON_GET_CLASS(s);
+
     memory_region_init_io(&s->io_memory, OBJECT(s), &apic_io_ops, s, "apic-msi",
                           APIC_SPACE_SIZE);
 
     s->timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, apic_timer, s);
 
     msi_supported = true;
+
+    acc->parent_realize(dev, errp);
+}
+
+static void apic_unrealize(DeviceState *dev, Error **errp)
+{
+    APICCommonState *s = APIC_COMMON(dev);
+    memory_region_destroy(&s->io_memory);
 }
 
 static void apic_class_init(ObjectClass *klass, void *data)
 {
     APICCommonClass *k = APIC_COMMON_CLASS(klass);
+    DeviceClass *dc = DEVICE_CLASS(klass);
 
-    k->init = apic_init;
+    k->parent_realize = dc->realize;
+    dc->realize = apic_realize;
+    dc->unrealize = apic_unrealize;
     k->set_base = apic_set_base;
     k->set_tpr = apic_set_tpr;
     k->get_tpr = apic_get_tpr;
diff --git a/hw/intc/apic_common.c b/hw/intc/apic_common.c
index 82fbb7f..fbb276d 100644
--- a/hw/intc/apic_common.c
+++ b/hw/intc/apic_common.c
@@ -284,17 +284,15 @@ static int apic_load_old(QEMUFile *f, void *opaque, int version_id)
     return 0;
 }
 
-static int apic_init_common(ICCDevice *dev)
+static void apic_common_realize(DeviceState *dev, Error **errp)
 {
     APICCommonState *s = APIC_COMMON(dev);
-    APICCommonClass *info;
+    APICCommonClass *info = APIC_COMMON_GET_CLASS(s);
     static DeviceState *vapic;
     static bool mmio_registered;
 
     s->idx = s->id;
 
-    info = APIC_COMMON_GET_CLASS(s);
-    info->init(s);
     if (!mmio_registered) {
         ICCBus *b = ICC_BUS(qdev_get_parent_bus(DEVICE(dev)));
         memory_region_add_subregion(b->apic_address_space, 0, &s->io_memory);
@@ -310,8 +308,6 @@ static int apic_init_common(ICCDevice *dev)
     if (apic_report_tpr_access && info->enable_tpr_reporting) {
         info->enable_tpr_reporting(s, true);
     }
-
-    return 0;
 }
 
 static void apic_dispatch_pre_save(void *opaque)
@@ -377,14 +373,13 @@ static Property apic_properties_common[] = {
 
 static void apic_common_class_init(ObjectClass *klass, void *data)
 {
-    ICCDeviceClass *idc = ICC_DEVICE_CLASS(klass);
     DeviceClass *dc = DEVICE_CLASS(klass);
 
+    dc->realize = apic_common_realize;
     dc->vmsd = &vmstate_apic_common;
     dc->reset = apic_reset_common;
     dc->no_user = 1;
     dc->props = apic_properties_common;
-    idc->init = apic_init_common;
 }
 
 static const TypeInfo apic_common_type = {
diff --git a/include/hw/i386/apic_internal.h b/include/hw/i386/apic_internal.h
index 5b763ac..9f885e7 100644
--- a/include/hw/i386/apic_internal.h
+++ b/include/hw/i386/apic_internal.h
@@ -78,7 +78,9 @@ typedef struct APICCommonClass
 {
     ICCDeviceClass parent_class;
 
-    void (*init)(APICCommonState *s);
+    DeviceRealize parent_realize;
+    DeviceUnrealize parent_unrealize;
+
     void (*set_base)(APICCommonState *s, uint64_t val);
     void (*set_tpr)(APICCommonState *s, uint8_t val);
     uint8_t (*get_tpr)(APICCommonState *s);
diff --git a/target-i386/cpu-qom.h b/target-i386/cpu-qom.h
index 775c82d..f36e4ff 100644
--- a/target-i386/cpu-qom.h
+++ b/target-i386/cpu-qom.h
@@ -50,6 +50,7 @@ typedef struct X86CPUClass {
     /*< public >*/
 
     DeviceRealize parent_realize;
+    DeviceUnrealize parent_unrealize;
     void (*parent_reset)(CPUState *cpu);
 } X86CPUClass;
 
diff --git a/target-i386/cpu.c b/target-i386/cpu.c
index c9d5626..9ebf3c9 100644
--- a/target-i386/cpu.c
+++ b/target-i386/cpu.c
@@ -2492,10 +2492,31 @@ static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
         return;
     }
 }
+
+static void x86_cpu_apic_unrealize(X86CPU *cpu, Error **errp)
+{
+    Error *local_err = NULL;
+
+    if (cpu->apic_state == NULL) {
+        return;
+    }
+
+    object_property_set_bool(OBJECT(cpu->apic_state),
+                             false, "realized", &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+
+    qdev_free(cpu->apic_state);
+}
 #else
 static void x86_cpu_apic_realize(X86CPU *cpu, Error **errp)
 {
 }
+static void x86_cpu_apic_unrealize(X86CPU *cpu, Error **errp)
+{
+}
 #endif
 
 static void x86_cpu_realizefn(DeviceState *dev, Error **errp)
@@ -2571,6 +2592,18 @@ out:
     }
 }
 
+static void x86_cpu_unrealizefn(DeviceState *dev, Error **errp)
+{
+    X86CPU *cpu = X86_CPU(dev);
+    Error *local_err = NULL;
+
+    x86_cpu_apic_unrealize(cpu, &local_err);
+    if (local_err != NULL) {
+        error_propagate(errp, local_err);
+        return;
+    }
+}
+
 /* Enables contiguous-apic-ID mode, for compatibility */
 static bool compat_apic_id_mode;
 
@@ -2702,7 +2735,9 @@ static void x86_cpu_common_class_init(ObjectClass *oc, void *data)
     DeviceClass *dc = DEVICE_CLASS(oc);
 
     xcc->parent_realize = dc->realize;
+    xcc->parent_unrealize = dc->unrealize;
     dc->realize = x86_cpu_realizefn;
+    dc->unrealize = x86_cpu_unrealizefn;
     dc->bus_type = TYPE_ICC_BUS;
     dc->props = x86_cpu_properties;
 
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (3 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 04/10] x86: add x86_cpu_unrealizefn() for cpu apic remove Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-11-27 14:00   ` Eric Blake
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 06/10] qom cpu: rename variable 'cpu_added_notifier' to 'cpu_hotplug_notifier' Chen Fan
                   ` (5 subsequent siblings)
  10 siblings, 1 reply; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/i386/pc.c         |  6 ++++++
 hw/i386/pc_piix.c    |  3 ++-
 include/hw/boards.h  |  2 ++
 include/hw/i386/pc.h |  1 +
 qapi-schema.json     | 12 ++++++++++++
 qmp-commands.hx      | 23 +++++++++++++++++++++++
 qmp.c                |  9 +++++++++
 7 files changed, 55 insertions(+), 1 deletion(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 832c9b2..40d611e 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -956,6 +956,12 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
     pc_new_cpu(current_cpu_model, apic_id, icc_bridge, errp);
 }
 
+void pc_hot_del_cpu(const int64_t id, Error **errp)
+{
+    /* TODO: hot remove vCPU. */
+    error_setg(errp, "Hot-remove CPU is not supported.");
+}
+
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
 {
     int i;
diff --git a/hw/i386/pc_piix.c b/hw/i386/pc_piix.c
index c6042c7..e7039be 100644
--- a/hw/i386/pc_piix.c
+++ b/hw/i386/pc_piix.c
@@ -337,7 +337,8 @@ static void pc_xen_hvm_init(QEMUMachineInitArgs *args)
 #define PC_I440FX_MACHINE_OPTIONS \
     PC_DEFAULT_MACHINE_OPTIONS, \
     .desc = "Standard PC (i440FX + PIIX, 1996)", \
-    .hot_add_cpu = pc_hot_add_cpu
+    .hot_add_cpu = pc_hot_add_cpu, \
+    .hot_del_cpu = pc_hot_del_cpu
 
 #define PC_I440FX_1_7_MACHINE_OPTIONS PC_I440FX_MACHINE_OPTIONS
 static QEMUMachine pc_i440fx_machine_v1_7 = {
diff --git a/include/hw/boards.h b/include/hw/boards.h
index 5a7ae9f..5934828 100644
--- a/include/hw/boards.h
+++ b/include/hw/boards.h
@@ -20,6 +20,7 @@ typedef void QEMUMachineInitFunc(QEMUMachineInitArgs *args);
 typedef void QEMUMachineResetFunc(void);
 
 typedef void QEMUMachineHotAddCPUFunc(const int64_t id, Error **errp);
+typedef void QEMUMachineHotDelCPUFunc(const int64_t id, Error **errp);
 
 typedef struct QEMUMachine {
     const char *name;
@@ -28,6 +29,7 @@ typedef struct QEMUMachine {
     QEMUMachineInitFunc *init;
     QEMUMachineResetFunc *reset;
     QEMUMachineHotAddCPUFunc *hot_add_cpu;
+    QEMUMachineHotDelCPUFunc *hot_del_cpu;
     BlockInterfaceType block_default_type;
     int max_cpus;
     unsigned int no_serial:1,
diff --git a/include/hw/i386/pc.h b/include/hw/i386/pc.h
index 6083839..e7f4313 100644
--- a/include/hw/i386/pc.h
+++ b/include/hw/i386/pc.h
@@ -96,6 +96,7 @@ void pc_acpi_smi_interrupt(void *opaque, int irq, int level);
 
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge);
 void pc_hot_add_cpu(const int64_t id, Error **errp);
+void pc_hot_del_cpu(const int64_t id, Error **errp);
 void pc_acpi_init(const char *default_dsdt);
 
 PcGuestInfo *pc_guest_info_init(ram_addr_t below_4g_mem_size,
diff --git a/qapi-schema.json b/qapi-schema.json
index 145eca8..e2a47ea 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1479,6 +1479,18 @@
 ##
 { 'command': 'cpu-add', 'data': {'id': 'int'} }
 
+# @cpu-del
+
+# Deletes CPU with specified ID
+#
+# @id: ID of CPU to be deleted, valid values [0..max_cpus)
+#
+# Returns: Nothing on success
+#
+# Since 1.7
+##
+{ 'command': 'cpu-del', 'data': {'id': 'int'} }
+
 ##
 # @memsave:
 #
diff --git a/qmp-commands.hx b/qmp-commands.hx
index b17c46e..8f2bfdb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -411,6 +411,29 @@ Example:
 EQMP
 
     {
+        .name       = "cpu-del",
+        .args_type  = "id:i",
+        .mhandler.cmd_new = qmp_marshal_input_cpu_del,
+    },
+
+SQMP
+cpu-del
+-------
+
+Deletes virtual cpu
+
+Arguments:
+
+- "id": cpu id (json-int)
+
+Example:
+
+-> { "execute": "cpu-del", "arguments": { "id": 2 } }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "memsave",
         .args_type  = "val:l,size:i,filename:s,cpu:i?",
         .mhandler.cmd_new = qmp_marshal_input_memsave,
diff --git a/qmp.c b/qmp.c
index 4c149b3..84dc873 100644
--- a/qmp.c
+++ b/qmp.c
@@ -118,6 +118,15 @@ void qmp_cpu_add(int64_t id, Error **errp)
     }
 }
 
+void qmp_cpu_del(int64_t id, Error **errp)
+{
+    if (current_machine->hot_del_cpu) {
+        current_machine->hot_del_cpu(id, errp);
+    } else {
+        error_setg(errp, "Not supported");
+    }
+}
+
 #ifndef CONFIG_VNC
 /* If VNC support is enabled, the "true" query-vnc command is
    defined in the VNC subsystem */
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 06/10] qom cpu: rename variable 'cpu_added_notifier' to 'cpu_hotplug_notifier'
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (4 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 07/10] qom cpu: add UNPLUG cpu notifier support Chen Fan
                   ` (4 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Rename variable 'cpu_added_notifier' to 'cpu_hotplug_notifier', for
adding vcpu-remove notifier support.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/acpi/piix4.c         | 10 +++++-----
 hw/i386/pc.c            |  2 +-
 include/sysemu/sysemu.h |  2 +-
 qom/cpu.c               | 10 +++++-----
 4 files changed, 12 insertions(+), 12 deletions(-)

diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index b46bd5e..06f55d6 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -95,7 +95,7 @@ typedef struct PIIX4PMState {
     uint8_t s4_val;
 
     CPUStatus gpe_cpu;
-    Notifier cpu_added_notifier;
+    Notifier cpu_hotplug_notifier;
 } PIIX4PMState;
 
 #define TYPE_PIIX4_PM "PIIX4_PM"
@@ -661,9 +661,9 @@ static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
     pm_update_sci(s);
 }
 
-static void piix4_cpu_added_req(Notifier *n, void *opaque)
+static void piix4_cpu_hotplug(Notifier *n, void *opaque)
 {
-    PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_added_notifier);
+    PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_hotplug_notifier);
 
     piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
 }
@@ -696,8 +696,8 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
     memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
                           "acpi-cpu-hotplug", PIIX4_PROC_LEN);
     memory_region_add_subregion(parent, PIIX4_PROC_BASE, &s->io_cpu);
-    s->cpu_added_notifier.notify = piix4_cpu_added_req;
-    qemu_register_cpu_added_notifier(&s->cpu_added_notifier);
+    s->cpu_hotplug_notifier.notify = piix4_cpu_hotplug;
+    qemu_register_cpu_hotplug_notifier(&s->cpu_hotplug_notifier);
 }
 
 static void enable_device(PIIX4PMState *s, int slot)
diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 40d611e..8ab6e4f 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -406,7 +406,7 @@ void pc_cmos_init(ram_addr_t ram_size, ram_addr_t above_4g_mem_size,
     /* init CPU hotplug notifier */
     cpu_hotplug_cb.rtc_state = s;
     cpu_hotplug_cb.cpu_added_notifier.notify = rtc_notify_cpu_added;
-    qemu_register_cpu_added_notifier(&cpu_hotplug_cb.cpu_added_notifier);
+    qemu_register_cpu_hotplug_notifier(&cpu_hotplug_cb.cpu_added_notifier);
 
     if (set_boot_dev(s, boot_device)) {
         exit(1);
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index cd5791e..72c5ff9 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -158,7 +158,7 @@ void do_pci_device_hot_remove(Monitor *mon, const QDict *qdict);
 void drive_hot_add(Monitor *mon, const QDict *qdict);
 
 /* CPU hotplug */
-void qemu_register_cpu_added_notifier(Notifier *notifier);
+void qemu_register_cpu_hotplug_notifier(Notifier *notifier);
 
 /* pcie aer error injection */
 void pcie_aer_inject_error_print(Monitor *mon, const QObject *data);
diff --git a/qom/cpu.c b/qom/cpu.c
index 818fb26..0913c9c 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -67,12 +67,12 @@ static void cpu_common_get_memory_mapping(CPUState *cpu,
 }
 
 /* CPU hot-plug notifiers */
-static NotifierList cpu_added_notifiers =
-    NOTIFIER_LIST_INITIALIZER(cpu_add_notifiers);
+static NotifierList cpu_hotplug_notifiers =
+    NOTIFIER_LIST_INITIALIZER(cpu_hotplug_notifiers);
 
-void qemu_register_cpu_added_notifier(Notifier *notifier)
+void qemu_register_cpu_hotplug_notifier(Notifier *notifier)
 {
-    notifier_list_add(&cpu_added_notifiers, notifier);
+    notifier_list_add(&cpu_hotplug_notifiers, notifier);
 }
 
 void cpu_reset_interrupt(CPUState *cpu, int mask)
@@ -219,7 +219,7 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
 
     if (dev->hotplugged) {
         cpu_synchronize_post_init(cpu);
-        notifier_list_notify(&cpu_added_notifiers, dev);
+        notifier_list_notify(&cpu_hotplug_notifiers, dev);
         cpu_resume(cpu);
     }
 }
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 07/10] qom cpu: add UNPLUG cpu notifier support
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (5 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 06/10] qom cpu: rename variable 'cpu_added_notifier' to 'cpu_hotplug_notifier' Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 08/10] i386: implement pc interface pc_hot_del_cpu() Chen Fan
                   ` (3 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Move struct HotplugEventType from file piix4.c to file qom/cpu.c,
and add struct CPUNotifier for supporting UNPLUG cpu notifier.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/acpi/piix4.c   |  8 ++------
 include/qom/cpu.h | 10 ++++++++++
 qom/cpu.c         |  6 +++++-
 3 files changed, 17 insertions(+), 7 deletions(-)

diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index 06f55d6..dc506bf 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -636,11 +636,6 @@ static const MemoryRegionOps cpu_hotplug_ops = {
     },
 };
 
-typedef enum {
-    PLUG,
-    UNPLUG,
-} HotplugEventType;
-
 static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
                                   HotplugEventType action)
 {
@@ -664,8 +659,9 @@ static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
 static void piix4_cpu_hotplug(Notifier *n, void *opaque)
 {
     PIIX4PMState *s = container_of(n, PIIX4PMState, cpu_hotplug_notifier);
+    CPUNotifier *notifier = opaque;
 
-    piix4_cpu_hotplug_req(s, CPU(opaque), PLUG);
+    piix4_cpu_hotplug_req(s, CPU(notifier->dev), notifier->type);
 }
 
 static int piix4_device_hotplug(DeviceState *qdev, PCIDevice *dev,
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 7739e00..0238532 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -507,6 +507,16 @@ void qemu_init_vcpu(CPUState *cpu);
  */
 void cpu_single_step(CPUState *cpu, int enabled);
 
+typedef enum {
+    PLUG,
+    UNPLUG,
+} HotplugEventType;
+
+typedef struct CPUNotifier {
+    DeviceState *dev;
+    HotplugEventType type;
+} CPUNotifier;
+
 #ifdef CONFIG_SOFTMMU
 extern const struct VMStateDescription vmstate_cpu_common;
 #else
diff --git a/qom/cpu.c b/qom/cpu.c
index 0913c9c..d20783b 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -216,10 +216,14 @@ static ObjectClass *cpu_common_class_by_name(const char *cpu_model)
 static void cpu_common_realizefn(DeviceState *dev, Error **errp)
 {
     CPUState *cpu = CPU(dev);
+    CPUNotifier notifier;
+
+    notifier.dev = dev;
+    notifier.type = PLUG;
 
     if (dev->hotplugged) {
         cpu_synchronize_post_init(cpu);
-        notifier_list_notify(&cpu_hotplug_notifiers, dev);
+        notifier_list_notify(&cpu_hotplug_notifiers, &notifier);
         cpu_resume(cpu);
     }
 }
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 08/10] i386: implement pc interface pc_hot_del_cpu()
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (6 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 07/10] qom cpu: add UNPLUG cpu notifier support Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection Chen Fan
                   ` (2 subsequent siblings)
  10 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

Implement cpu interface pc_hot_del_cpu() for unrealizing device vCPU.
emiting vcpu-remove notifier to ACPI, then ACPI could send sci interrupt
to OS for hot-remove vcpu.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/i386/pc.c | 30 ++++++++++++++++++++++++++++--
 qom/cpu.c    | 12 ++++++++++++
 2 files changed, 40 insertions(+), 2 deletions(-)

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index 8ab6e4f..a6b9b78 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -958,8 +958,34 @@ void pc_hot_add_cpu(const int64_t id, Error **errp)
 
 void pc_hot_del_cpu(const int64_t id, Error **errp)
 {
-    /* TODO: hot remove vCPU. */
-    error_setg(errp, "Hot-remove CPU is not supported.");
+    CPUState *cpu;
+    bool found = false;
+    X86CPUClass *xcc;
+
+    CPU_FOREACH(cpu) {
+        CPUClass *cc = CPU_GET_CLASS(cpu);
+        int64_t cpuid = cc->get_arch_id(cpu);
+
+        if (cpuid == id) {
+            found = true;
+            break;
+        }
+    }
+
+    if (!found) {
+        error_setg(errp, "Unable to find cpu-index: %" PRIi64
+                   ", it doesn't exist or has been deleted.", id);
+        return;
+    }
+
+    if (cpu == first_cpu && !CPU_NEXT(cpu)) {
+        error_setg(errp, "Unable to delete the last "
+                   "one cpu when VM running.");
+        return;
+    }
+
+    xcc = X86_CPU_GET_CLASS(DEVICE(cpu));
+    xcc->parent_unrealize(DEVICE(cpu), errp);
 }
 
 void pc_cpus_init(const char *cpu_model, DeviceState *icc_bridge)
diff --git a/qom/cpu.c b/qom/cpu.c
index d20783b..89fc8bd 100644
--- a/qom/cpu.c
+++ b/qom/cpu.c
@@ -228,6 +228,17 @@ static void cpu_common_realizefn(DeviceState *dev, Error **errp)
     }
 }
 
+static void cpu_common_unrealizefn(DeviceState *dev, Error **errp)
+{
+    CPUNotifier notifier;
+
+    notifier.dev = dev;
+    notifier.type = UNPLUG;
+
+    notifier_list_notify(&cpu_hotplug_notifiers, &notifier);
+}
+
+
 static void cpu_common_initfn(Object *obj)
 {
     CPUState *cpu = CPU(obj);
@@ -258,6 +269,7 @@ static void cpu_class_init(ObjectClass *klass, void *data)
     k->gdb_read_register = cpu_common_gdb_read_register;
     k->gdb_write_register = cpu_common_gdb_write_register;
     dc->realize = cpu_common_realizefn;
+    dc->unrealize = cpu_common_unrealizefn;
     dc->no_user = 1;
 }
 
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (7 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 08/10] i386: implement pc interface pc_hot_del_cpu() Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-11-22  8:02   ` Vasilis Liaskovitis
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects Chen Fan
  2013-11-28 14:41 ` [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Igor Mammedov
  10 siblings, 1 reply; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

When OS eject a vcpu (like: echo 1 > /sys/bus/acpi/devices/LNXCPUXX/eject),
it will call acpi EJ0 method, the firmware will write the new cpumap, QEMU
will know which vcpu need to be ejected.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 hw/acpi/piix4.c | 37 ++++++++++++++++++++++++++++++++++++-
 1 file changed, 36 insertions(+), 1 deletion(-)

diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index dc506bf..fd27001 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -61,6 +61,7 @@ struct pci_status {
 
 typedef struct CPUStatus {
     uint8_t sts[PIIX4_PROC_LEN];
+    uint8_t old_sts[PIIX4_PROC_LEN];
 } CPUStatus;
 
 typedef struct PIIX4PMState {
@@ -611,6 +612,12 @@ static const MemoryRegionOps piix4_pci_ops = {
     },
 };
 
+static void acpi_piix_eject_vcpu(int64_t cpuid)
+{
+    /* TODO: eject a vcpu, release allocated vcpu and exit the vcpu pthread.  */
+    PIIX4_DPRINTF("vcpu: %" PRIu64 " need to be ejected.\n", cpuid);
+}
+
 static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
 {
     PIIX4PMState *s = opaque;
@@ -623,7 +630,27 @@ static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
 static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
                              unsigned int size)
 {
-    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
+    PIIX4PMState *s = opaque;
+    CPUStatus *cpus = &s->gpe_cpu;
+    uint8_t val;
+    int i;
+    int64_t cpuid = 0;
+
+    val = cpus->old_sts[addr] ^ data;
+
+    if (val == 0) {
+        return;
+    }
+
+    for (i = 0; i < 8; i++) {
+        if (val & 1 << i) {
+            cpuid = 8 * addr + i;
+        }
+    }
+
+    if (cpuid != 0) {
+        acpi_piix_eject_vcpu(cpuid);
+    }
 }
 
 static const MemoryRegionOps cpu_hotplug_ops = {
@@ -643,13 +670,20 @@ static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
     ACPIGPE *gpe = &s->ar.gpe;
     CPUClass *k = CPU_GET_CLASS(cpu);
     int64_t cpu_id;
+    int i;
 
     assert(s != NULL);
 
     *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
     cpu_id = k->get_arch_id(CPU(cpu));
+
+    for (i = 0; i < PIIX4_PROC_LEN; i++) {
+        g->old_sts[i] = g->sts[i];
+    }
+
     if (action == PLUG) {
         g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
+        g->old_sts[cpu_id / 8] |= (1 << (cpu_id % 8));
     } else {
         g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
     }
@@ -688,6 +722,7 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
 
         g_assert((id / 8) < PIIX4_PROC_LEN);
         s->gpe_cpu.sts[id / 8] |= (1 << (id % 8));
+        s->gpe_cpu.old_sts[id / 8] |= (1 << (id % 8));
     }
     memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
                           "acpi-cpu-hotplug", PIIX4_PROC_LEN);
-- 
1.8.1.4

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

* [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (8 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection Chen Fan
@ 2013-10-09  9:43 ` Chen Fan
  2013-11-28 14:48   ` Igor Mammedov
  2013-11-28 14:41 ` [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Igor Mammedov
  10 siblings, 1 reply; 23+ messages in thread
From: Chen Fan @ 2013-10-09  9:43 UTC (permalink / raw)
  To: qemu-devel; +Cc: Igor Mammedov, Andreas Färber

After ACPI get a signal to eject a vCPU, then it will notify
the vCPU thread to exit in KVM, and the vCPU must be removed from CPU list,
before the vCPU really removed, there will release the all related vCPU objects.

Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
---
 cpus.c               | 46 ++++++++++++++++++++++++++++++++++++++++++++++
 hw/acpi/piix4.c      | 23 +++++++++++++++++------
 include/qom/cpu.h    | 10 ++++++++++
 include/sysemu/kvm.h |  1 +
 kvm-all.c            | 25 +++++++++++++++++++++++++
 5 files changed, 99 insertions(+), 6 deletions(-)

diff --git a/cpus.c b/cpus.c
index 4ace860..942af0a 100644
--- a/cpus.c
+++ b/cpus.c
@@ -714,6 +714,26 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
     qemu_cpu_kick(cpu);
 }
 
+static void qemu_kvm_destroy_vcpu(CPUState *cpu)
+{
+    CPU_REMOVE(cpu);
+
+    if (kvm_destroy_vcpu(cpu) < 0) {
+        fprintf(stderr, "kvm_destroy_vcpu failed.\n");
+        exit(1);
+    }
+
+    object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
+    qdev_free(DEVICE(cpu));
+}
+
+static void qemu_tcg_destroy_vcpu(CPUState *cpu)
+{
+    CPU_REMOVE(cpu);
+    object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
+    qdev_free(DEVICE(cpu));
+}
+
 static void flush_queued_work(CPUState *cpu)
 {
     struct qemu_work_item *wi;
@@ -805,6 +825,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
             }
         }
         qemu_kvm_wait_io_event(cpu);
+        if (cpu->exit && !cpu_can_run(cpu)) {
+            qemu_kvm_destroy_vcpu(cpu);
+            qemu_mutex_unlock(&qemu_global_mutex);
+            return NULL;
+        }
     }
 
     return NULL;
@@ -857,6 +882,7 @@ static void tcg_exec_all(void);
 static void *qemu_tcg_cpu_thread_fn(void *arg)
 {
     CPUState *cpu = arg;
+    CPUState *remove_cpu = NULL;
 
     qemu_tcg_init_cpu_signals();
     qemu_thread_get_self(cpu->thread);
@@ -889,6 +915,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
             }
         }
         qemu_tcg_wait_io_event();
+        CPU_FOREACH(cpu) {
+            if (cpu->exit && !cpu_can_run(cpu)) {
+                remove_cpu = cpu;
+                break;
+            }
+        }
+        if (remove_cpu) {
+            qemu_tcg_destroy_vcpu(remove_cpu);
+            remove_cpu = NULL;
+        }
     }
 
     return NULL;
@@ -1045,6 +1081,13 @@ void resume_all_vcpus(void)
     }
 }
 
+void cpu_remove(CPUState *cpu)
+{
+    cpu->stop = true;
+    cpu->exit = true;
+    qemu_cpu_kick(cpu);
+}
+
 static void qemu_tcg_init_vcpu(CPUState *cpu)
 {
     /* share a single thread for all cpus with TCG */
@@ -1219,6 +1262,9 @@ static void tcg_exec_all(void)
                 break;
             }
         } else if (cpu->stop || cpu->stopped) {
+            if (cpu->exit) {
+                next_cpu = CPU_NEXT(cpu);
+            }
             break;
         }
     }
diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
index fd27001..bde8123 100644
--- a/hw/acpi/piix4.c
+++ b/hw/acpi/piix4.c
@@ -612,10 +612,21 @@ static const MemoryRegionOps piix4_pci_ops = {
     },
 };
 
-static void acpi_piix_eject_vcpu(int64_t cpuid)
+static void acpi_piix_eject_vcpu(PIIX4PMState *s, int64_t cpuid)
 {
-    /* TODO: eject a vcpu, release allocated vcpu and exit the vcpu pthread.  */
-    PIIX4_DPRINTF("vcpu: %" PRIu64 " need to be ejected.\n", cpuid);
+    CPUStatus *g = &s->gpe_cpu;
+    CPUState *cpu;
+
+    CPU_FOREACH(cpu) {
+        CPUClass *cc = CPU_GET_CLASS(cpu);
+        int64_t id = cc->get_arch_id(cpu);
+
+        if (cpuid == id) {
+            g->old_sts[cpuid / 8] &= ~(1 << (cpuid % 8));
+            cpu_remove(cpu);
+            break;
+        }
+    }
 }
 
 static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
@@ -634,7 +645,7 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
     CPUStatus *cpus = &s->gpe_cpu;
     uint8_t val;
     int i;
-    int64_t cpuid = 0;
+    int64_t cpuid = -1;
 
     val = cpus->old_sts[addr] ^ data;
 
@@ -648,8 +659,8 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
         }
     }
 
-    if (cpuid != 0) {
-        acpi_piix_eject_vcpu(cpuid);
+    if (cpuid != -1) {
+        acpi_piix_eject_vcpu(s, cpuid);
     }
 }
 
diff --git a/include/qom/cpu.h b/include/qom/cpu.h
index 0238532..eb8d32b 100644
--- a/include/qom/cpu.h
+++ b/include/qom/cpu.h
@@ -181,6 +181,7 @@ struct CPUState {
     bool created;
     bool stop;
     bool stopped;
+    bool exit;
     volatile sig_atomic_t exit_request;
     volatile sig_atomic_t tcg_exit_req;
     uint32_t interrupt_request;
@@ -206,6 +207,7 @@ struct CPUState {
 QTAILQ_HEAD(CPUTailQ, CPUState);
 extern struct CPUTailQ cpus;
 #define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
+#define CPU_REMOVE(cpu) QTAILQ_REMOVE(&cpus, cpu, node)
 #define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
 #define CPU_FOREACH_SAFE(cpu, next_cpu) \
     QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
@@ -487,6 +489,14 @@ void cpu_exit(CPUState *cpu);
 void cpu_resume(CPUState *cpu);
 
 /**
+ * qemu_remove_vcpu:
+ * @cpu: The vCPU to remove.
+ *
+ * Requests the CPU @cpu to be removed.
+ */
+void cpu_remove(CPUState *cpu);
+
+/**
  * qemu_init_vcpu:
  * @cpu: The vCPU to initialize.
  *
diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
index 3b25f27..f3f1279 100644
--- a/include/sysemu/kvm.h
+++ b/include/sysemu/kvm.h
@@ -167,6 +167,7 @@ int kvm_has_intx_set_mask(void);
 
 int kvm_init_vcpu(CPUState *cpu);
 int kvm_cpu_exec(CPUState *cpu);
+int kvm_destroy_vcpu(CPUState *cpu);
 
 #ifdef NEED_CPU_H
 
diff --git a/kvm-all.c b/kvm-all.c
index 4478969..605e00e 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -226,6 +226,31 @@ static void kvm_reset_vcpu(void *opaque)
     kvm_arch_reset_vcpu(cpu);
 }
 
+int kvm_destroy_vcpu(CPUState *cpu)
+{
+    KVMState *s = kvm_state;
+    long mmap_size;
+    int ret = 0;
+
+    DPRINTF("kvm_destroy_vcpu\n");
+
+    mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
+    if (mmap_size < 0) {
+        ret = mmap_size;
+        DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
+        goto err;
+    }
+
+    ret = munmap(cpu->kvm_run, mmap_size);
+    if (ret < 0) {
+        goto err;
+    }
+
+    close(cpu->kvm_fd);
+err:
+    return ret;
+}
+
 int kvm_init_vcpu(CPUState *cpu)
 {
     KVMState *s = kvm_state;
-- 
1.8.1.4


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

* Re: [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection Chen Fan
@ 2013-11-22  8:02   ` Vasilis Liaskovitis
  2013-11-25 18:38     ` Vasilis Liaskovitis
  0 siblings, 1 reply; 23+ messages in thread
From: Vasilis Liaskovitis @ 2013-11-22  8:02 UTC (permalink / raw)
  To: Chen Fan; +Cc: Igor Mammedov, qemu-devel, Andreas Färber

Hi,

On Wed, Oct 09, 2013 at 05:43:17PM +0800, Chen Fan wrote:
> When OS eject a vcpu (like: echo 1 > /sys/bus/acpi/devices/LNXCPUXX/eject),
> it will call acpi EJ0 method, the firmware will write the new cpumap, QEMU
> will know which vcpu need to be ejected.

I think that the _EJ0 callback (CPEJ method in hw/i386/acpi-dsdt-cpu-hotplug.dsl)
currently does not write the new cpumap, it only sleeps. So cpu_state_write is
never called on ejection, and the cpu objects remain allocated in qemu. Is there
an updated version of the patchseries with a CPEJ that writes the new cpumap?

thanks,

- Vasilis
> 
> Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> ---
>  hw/acpi/piix4.c | 37 ++++++++++++++++++++++++++++++++++++-
>  1 file changed, 36 insertions(+), 1 deletion(-)
> 
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index dc506bf..fd27001 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -61,6 +61,7 @@ struct pci_status {
>  
>  typedef struct CPUStatus {
>      uint8_t sts[PIIX4_PROC_LEN];
> +    uint8_t old_sts[PIIX4_PROC_LEN];
>  } CPUStatus;
>  
>  typedef struct PIIX4PMState {
> @@ -611,6 +612,12 @@ static const MemoryRegionOps piix4_pci_ops = {
>      },
>  };
>  
> +static void acpi_piix_eject_vcpu(int64_t cpuid)
> +{
> +    /* TODO: eject a vcpu, release allocated vcpu and exit the vcpu pthread.  */
> +    PIIX4_DPRINTF("vcpu: %" PRIu64 " need to be ejected.\n", cpuid);
> +}
> +
>  static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
>  {
>      PIIX4PMState *s = opaque;
> @@ -623,7 +630,27 @@ static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
>  static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
>                               unsigned int size)
>  {
> -    /* TODO: implement VCPU removal on guest signal that CPU can be removed */
> +    PIIX4PMState *s = opaque;
> +    CPUStatus *cpus = &s->gpe_cpu;
> +    uint8_t val;
> +    int i;
> +    int64_t cpuid = 0;
> +
> +    val = cpus->old_sts[addr] ^ data;
> +
> +    if (val == 0) {
> +        return;
> +    }
> +
> +    for (i = 0; i < 8; i++) {
> +        if (val & 1 << i) {
> +            cpuid = 8 * addr + i;
> +        }
> +    }
> +
> +    if (cpuid != 0) {
> +        acpi_piix_eject_vcpu(cpuid);
> +    }
>  }
>  
>  static const MemoryRegionOps cpu_hotplug_ops = {
> @@ -643,13 +670,20 @@ static void piix4_cpu_hotplug_req(PIIX4PMState *s, CPUState *cpu,
>      ACPIGPE *gpe = &s->ar.gpe;
>      CPUClass *k = CPU_GET_CLASS(cpu);
>      int64_t cpu_id;
> +    int i;
>  
>      assert(s != NULL);
>  
>      *gpe->sts = *gpe->sts | PIIX4_CPU_HOTPLUG_STATUS;
>      cpu_id = k->get_arch_id(CPU(cpu));
> +
> +    for (i = 0; i < PIIX4_PROC_LEN; i++) {
> +        g->old_sts[i] = g->sts[i];
> +    }
> +
>      if (action == PLUG) {
>          g->sts[cpu_id / 8] |= (1 << (cpu_id % 8));
> +        g->old_sts[cpu_id / 8] |= (1 << (cpu_id % 8));
>      } else {
>          g->sts[cpu_id / 8] &= ~(1 << (cpu_id % 8));
>      }
> @@ -688,6 +722,7 @@ static void piix4_acpi_system_hot_add_init(MemoryRegion *parent,
>  
>          g_assert((id / 8) < PIIX4_PROC_LEN);
>          s->gpe_cpu.sts[id / 8] |= (1 << (id % 8));
> +        s->gpe_cpu.old_sts[id / 8] |= (1 << (id % 8));
>      }
>      memory_region_init_io(&s->io_cpu, OBJECT(s), &cpu_hotplug_ops, s,
>                            "acpi-cpu-hotplug", PIIX4_PROC_LEN);
> -- 
> 1.8.1.4
> 
> 

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

* Re: [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection
  2013-11-22  8:02   ` Vasilis Liaskovitis
@ 2013-11-25 18:38     ` Vasilis Liaskovitis
  2013-11-27 12:11       ` Chen Fan
  0 siblings, 1 reply; 23+ messages in thread
From: Vasilis Liaskovitis @ 2013-11-25 18:38 UTC (permalink / raw)
  To: Chen Fan; +Cc: Igor Mammedov, qemu-devel, Andreas Färber

On Fri, Nov 22, 2013 at 09:02:27AM +0100, Vasilis Liaskovitis wrote:
> Hi,
> 
> On Wed, Oct 09, 2013 at 05:43:17PM +0800, Chen Fan wrote:
> > When OS eject a vcpu (like: echo 1 > /sys/bus/acpi/devices/LNXCPUXX/eject),
> > it will call acpi EJ0 method, the firmware will write the new cpumap, QEMU
> > will know which vcpu need to be ejected.
> 
> I think that the _EJ0 callback (CPEJ method in hw/i386/acpi-dsdt-cpu-hotplug.dsl)
> currently does not write the new cpumap, it only sleeps. So cpu_state_write is
> never called on ejection, and the cpu objects remain allocated in qemu. Is there
> an updated version of the patchseries with a CPEJ that writes the new cpumap?

oops, never mind. I missed your seabios patch mentioned in the head message,
got it now.

thanks,

- Vasilis

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

* Re: [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection
  2013-11-25 18:38     ` Vasilis Liaskovitis
@ 2013-11-27 12:11       ` Chen Fan
  0 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-11-27 12:11 UTC (permalink / raw)
  To: Vasilis Liaskovitis; +Cc: Igor Mammedov, qemu-devel, Andreas Färber

On Mon, 2013-11-25 at 19:38 +0100, Vasilis Liaskovitis wrote:
> On Fri, Nov 22, 2013 at 09:02:27AM +0100, Vasilis Liaskovitis wrote:
> > Hi,
> > 
> > On Wed, Oct 09, 2013 at 05:43:17PM +0800, Chen Fan wrote:
> > > When OS eject a vcpu (like: echo 1 > /sys/bus/acpi/devices/LNXCPUXX/eject),
> > > it will call acpi EJ0 method, the firmware will write the new cpumap, QEMU
> > > will know which vcpu need to be ejected.
> > 
> > I think that the _EJ0 callback (CPEJ method in hw/i386/acpi-dsdt-cpu-hotplug.dsl)
> > currently does not write the new cpumap, it only sleeps. So cpu_state_write is
> > never called on ejection, and the cpu objects remain allocated in qemu. Is there
> > an updated version of the patchseries with a CPEJ that writes the new cpumap?
> 
> oops, never mind. I missed your seabios patch mentioned in the head message,
> got it now.
> 
Ok, thanks for your attention.

> thanks,
> 
> - Vasilis

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

* Re: [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support Chen Fan
@ 2013-11-27 14:00   ` Eric Blake
  2013-11-28  1:14     ` Chen Fan
  0 siblings, 1 reply; 23+ messages in thread
From: Eric Blake @ 2013-11-27 14:00 UTC (permalink / raw)
  To: Chen Fan, qemu-devel; +Cc: Igor Mammedov, Andreas Färber

[-- Attachment #1: Type: text/plain, Size: 957 bytes --]

On 10/09/2013 03:43 AM, Chen Fan wrote:
> Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> ---
>  hw/i386/pc.c         |  6 ++++++
>  hw/i386/pc_piix.c    |  3 ++-
>  include/hw/boards.h  |  2 ++
>  include/hw/i386/pc.h |  1 +
>  qapi-schema.json     | 12 ++++++++++++
>  qmp-commands.hx      | 23 +++++++++++++++++++++++
>  qmp.c                |  9 +++++++++
>  7 files changed, 55 insertions(+), 1 deletion(-)

> +++ b/qapi-schema.json
> @@ -1479,6 +1479,18 @@
>  ##
>  { 'command': 'cpu-add', 'data': {'id': 'int'} }
>  
> +# @cpu-del
> +
> +# Deletes CPU with specified ID
> +#
> +# @id: ID of CPU to be deleted, valid values [0..max_cpus)
> +#
> +# Returns: Nothing on success
> +#
> +# Since 1.7

Since this mail is still titled RFC, there's no way it will make it into
1.7.  Are you shooting for 1.8?

-- 
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 621 bytes --]

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

* Re: [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support
  2013-11-27 14:00   ` Eric Blake
@ 2013-11-28  1:14     ` Chen Fan
  0 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-11-28  1:14 UTC (permalink / raw)
  To: Eric Blake; +Cc: Igor Mammedov, qemu-devel, Andreas Färber

On Wed, 2013-11-27 at 07:00 -0700, Eric Blake wrote:
> On 10/09/2013 03:43 AM, Chen Fan wrote:
> > Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> > ---
> >  hw/i386/pc.c         |  6 ++++++
> >  hw/i386/pc_piix.c    |  3 ++-
> >  include/hw/boards.h  |  2 ++
> >  include/hw/i386/pc.h |  1 +
> >  qapi-schema.json     | 12 ++++++++++++
> >  qmp-commands.hx      | 23 +++++++++++++++++++++++
> >  qmp.c                |  9 +++++++++
> >  7 files changed, 55 insertions(+), 1 deletion(-)
> 
> > +++ b/qapi-schema.json
> > @@ -1479,6 +1479,18 @@
> >  ##
> >  { 'command': 'cpu-add', 'data': {'id': 'int'} }
> >  
> > +# @cpu-del
> > +
> > +# Deletes CPU with specified ID
> > +#
> > +# @id: ID of CPU to be deleted, valid values [0..max_cpus)
> > +#
> > +# Returns: Nothing on success
> > +#
> > +# Since 1.7
> 
> Since this mail is still titled RFC, there's no way it will make it into
> 1.7.  Are you shooting for 1.8?
> 
Hi, this patchseries had not been commented yet, maybe I should send it
again after Rebase without RFC for 1.8. 

Thanks,
Chen

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

* Re: [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support
  2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
                   ` (9 preceding siblings ...)
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects Chen Fan
@ 2013-11-28 14:41 ` Igor Mammedov
  2013-12-04  2:15   ` Chen Fan
  2013-12-19  8:10   ` Chen Fan
  10 siblings, 2 replies; 23+ messages in thread
From: Igor Mammedov @ 2013-11-28 14:41 UTC (permalink / raw)
  To: Chen Fan; +Cc: qemu-devel, Andreas Färber

On Wed, 9 Oct 2013 17:43:08 +0800
Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:

> Via implementing ACPI standard methods _EJ0 in bios, after Guest OS hot remove
> one vCPU, it is able to send a signal to QEMU, then QEMU could notify
> the assigned vCPU of exiting. meanwhile, and intruduce the QOM command 'cpu-del' to remove
> vCPU from QEMU itself.

have you tried following sequence:
cpu-add 1
cpu-add 2
cpu-del 1
and then do migration?

> 
> this work is based on Andreas Färber's qom-cpu branch tree.
>     git://github.com/afaerber/qemu-cpu.git
> 
> this series patches must be used with seabios patch and KVM patch together.
> 
> for KVM patches:
>     http://comments.gmane.org/gmane.comp.emulators.kvm.devel/114347
> 
> for seabios patches:
>     http://comments.gmane.org/gmane.comp.emulators.qemu/230460
> 
> Chen Fan (10):
>   x86: move apic_state field from CPUX86State to X86CPU
>   apic: remove redundant variable 'apic_no' from apic_init_common()
>   apic: remove local_apics array and using CPU_FOREACH instead
>   x86: add x86_cpu_unrealizefn() for cpu apic remove
>   qmp: add 'cpu-del' command support
>   qom cpu: rename variable 'cpu_added_notifier' to
>     'cpu_hotplug_notifier'
>   qom cpu: add UNPLUG cpu notifier support
>   i386: implement pc interface pc_hot_del_cpu()
>   piix4: implement function cpu_status_write() for vcpu ejection
>   cpus: reclaim allocated vCPU objects
> 
>  cpu-exec.c                      |  2 +-
>  cpus.c                          | 51 +++++++++++++++++++++--
>  hw/acpi/piix4.c                 | 66 ++++++++++++++++++++++++------
>  hw/i386/kvm/apic.c              | 18 +++++++-
>  hw/i386/kvmvapic.c              |  8 ++--
>  hw/i386/pc.c                    | 51 ++++++++++++++++++-----
>  hw/i386/pc_piix.c               |  3 +-
>  hw/intc/apic.c                  | 91 ++++++++++++++++++++++-------------------
>  hw/intc/apic_common.c           | 17 ++------
>  include/hw/boards.h             |  2 +
>  include/hw/i386/apic_internal.h |  6 +--
>  include/hw/i386/pc.h            |  1 +
>  include/qom/cpu.h               | 20 +++++++++
>  include/sysemu/kvm.h            |  1 +
>  include/sysemu/sysemu.h         |  2 +-
>  kvm-all.c                       | 25 +++++++++++
>  qapi-schema.json                | 12 ++++++
>  qmp-commands.hx                 | 23 +++++++++++
>  qmp.c                           |  9 ++++
>  qom/cpu.c                       | 26 +++++++++---
>  target-i386/cpu-qom.h           |  5 +++
>  target-i386/cpu.c               | 57 ++++++++++++++++++++------
>  target-i386/cpu.h               |  4 --
>  target-i386/helper.c            |  9 ++--
>  target-i386/kvm.c               | 23 +++++------
>  target-i386/misc_helper.c       |  8 ++--
>  26 files changed, 403 insertions(+), 137 deletions(-)
> 

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

* Re: [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects
  2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects Chen Fan
@ 2013-11-28 14:48   ` Igor Mammedov
  2013-12-04  2:28     ` Chen Fan
  0 siblings, 1 reply; 23+ messages in thread
From: Igor Mammedov @ 2013-11-28 14:48 UTC (permalink / raw)
  To: Chen Fan; +Cc: qemu-devel, Andreas Färber

On Wed, 9 Oct 2013 17:43:18 +0800
Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:

> After ACPI get a signal to eject a vCPU, then it will notify
> the vCPU thread to exit in KVM, and the vCPU must be removed from CPU list,
> before the vCPU really removed, there will release the all related vCPU objects.
> 
> Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> ---
>  cpus.c               | 46 ++++++++++++++++++++++++++++++++++++++++++++++
>  hw/acpi/piix4.c      | 23 +++++++++++++++++------
>  include/qom/cpu.h    | 10 ++++++++++
>  include/sysemu/kvm.h |  1 +
>  kvm-all.c            | 25 +++++++++++++++++++++++++
>  5 files changed, 99 insertions(+), 6 deletions(-)
> 
> diff --git a/cpus.c b/cpus.c
> index 4ace860..942af0a 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -714,6 +714,26 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
>      qemu_cpu_kick(cpu);
>  }
>  
> +static void qemu_kvm_destroy_vcpu(CPUState *cpu)
> +{
> +    CPU_REMOVE(cpu);
> +
> +    if (kvm_destroy_vcpu(cpu) < 0) {
Does it actually do what it's supposed to do?
If I recall correctly KVM patches were dimmed as not correct approach.

perhaps in case of KVM for now, it should return failure (i.e. no unplug
for KVM).

> +        fprintf(stderr, "kvm_destroy_vcpu failed.\n");
> +        exit(1);
> +    }
> +
> +    object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
> +    qdev_free(DEVICE(cpu));
> +}
> +
> +static void qemu_tcg_destroy_vcpu(CPUState *cpu)
> +{
> +    CPU_REMOVE(cpu);
> +    object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
> +    qdev_free(DEVICE(cpu));
> +}
> +
>  static void flush_queued_work(CPUState *cpu)
>  {
>      struct qemu_work_item *wi;
> @@ -805,6 +825,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
>              }
>          }
>          qemu_kvm_wait_io_event(cpu);
> +        if (cpu->exit && !cpu_can_run(cpu)) {
> +            qemu_kvm_destroy_vcpu(cpu);
> +            qemu_mutex_unlock(&qemu_global_mutex);
> +            return NULL;
> +        }
>      }
>  
>      return NULL;
> @@ -857,6 +882,7 @@ static void tcg_exec_all(void);
>  static void *qemu_tcg_cpu_thread_fn(void *arg)
>  {
>      CPUState *cpu = arg;
> +    CPUState *remove_cpu = NULL;
>  
>      qemu_tcg_init_cpu_signals();
>      qemu_thread_get_self(cpu->thread);
> @@ -889,6 +915,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
>              }
>          }
>          qemu_tcg_wait_io_event();
> +        CPU_FOREACH(cpu) {
> +            if (cpu->exit && !cpu_can_run(cpu)) {
> +                remove_cpu = cpu;
> +                break;
> +            }
> +        }
> +        if (remove_cpu) {
> +            qemu_tcg_destroy_vcpu(remove_cpu);
> +            remove_cpu = NULL;
> +        }
>      }
>  
>      return NULL;
> @@ -1045,6 +1081,13 @@ void resume_all_vcpus(void)
>      }
>  }
>  
> +void cpu_remove(CPUState *cpu)
> +{
> +    cpu->stop = true;
> +    cpu->exit = true;
> +    qemu_cpu_kick(cpu);
> +}
> +
>  static void qemu_tcg_init_vcpu(CPUState *cpu)
>  {
>      /* share a single thread for all cpus with TCG */
> @@ -1219,6 +1262,9 @@ static void tcg_exec_all(void)
>                  break;
>              }
>          } else if (cpu->stop || cpu->stopped) {
> +            if (cpu->exit) {
> +                next_cpu = CPU_NEXT(cpu);
> +            }
>              break;
>          }
>      }
> diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> index fd27001..bde8123 100644
> --- a/hw/acpi/piix4.c
> +++ b/hw/acpi/piix4.c
> @@ -612,10 +612,21 @@ static const MemoryRegionOps piix4_pci_ops = {
>      },
>  };
>  
> -static void acpi_piix_eject_vcpu(int64_t cpuid)
> +static void acpi_piix_eject_vcpu(PIIX4PMState *s, int64_t cpuid)
>  {
> -    /* TODO: eject a vcpu, release allocated vcpu and exit the vcpu pthread.  */
> -    PIIX4_DPRINTF("vcpu: %" PRIu64 " need to be ejected.\n", cpuid);
> +    CPUStatus *g = &s->gpe_cpu;
> +    CPUState *cpu;
> +
> +    CPU_FOREACH(cpu) {
> +        CPUClass *cc = CPU_GET_CLASS(cpu);
> +        int64_t id = cc->get_arch_id(cpu);
> +
> +        if (cpuid == id) {
> +            g->old_sts[cpuid / 8] &= ~(1 << (cpuid % 8));
> +            cpu_remove(cpu);
> +            break;
> +        }
> +    }
>  }
>  
>  static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
> @@ -634,7 +645,7 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
>      CPUStatus *cpus = &s->gpe_cpu;
>      uint8_t val;
>      int i;
> -    int64_t cpuid = 0;
> +    int64_t cpuid = -1;
>  
>      val = cpus->old_sts[addr] ^ data;
>  
> @@ -648,8 +659,8 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
>          }
>      }
>  
> -    if (cpuid != 0) {
> -        acpi_piix_eject_vcpu(cpuid);
> +    if (cpuid != -1) {
> +        acpi_piix_eject_vcpu(s, cpuid);
>      }
>  }
>  
> diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> index 0238532..eb8d32b 100644
> --- a/include/qom/cpu.h
> +++ b/include/qom/cpu.h
> @@ -181,6 +181,7 @@ struct CPUState {
>      bool created;
>      bool stop;
>      bool stopped;
> +    bool exit;
>      volatile sig_atomic_t exit_request;
>      volatile sig_atomic_t tcg_exit_req;
>      uint32_t interrupt_request;
> @@ -206,6 +207,7 @@ struct CPUState {
>  QTAILQ_HEAD(CPUTailQ, CPUState);
>  extern struct CPUTailQ cpus;
>  #define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
> +#define CPU_REMOVE(cpu) QTAILQ_REMOVE(&cpus, cpu, node)
>  #define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
>  #define CPU_FOREACH_SAFE(cpu, next_cpu) \
>      QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
> @@ -487,6 +489,14 @@ void cpu_exit(CPUState *cpu);
>  void cpu_resume(CPUState *cpu);
>  
>  /**
> + * qemu_remove_vcpu:
> + * @cpu: The vCPU to remove.
> + *
> + * Requests the CPU @cpu to be removed.
> + */
> +void cpu_remove(CPUState *cpu);
> +
> +/**
>   * qemu_init_vcpu:
>   * @cpu: The vCPU to initialize.
>   *
> diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> index 3b25f27..f3f1279 100644
> --- a/include/sysemu/kvm.h
> +++ b/include/sysemu/kvm.h
> @@ -167,6 +167,7 @@ int kvm_has_intx_set_mask(void);
>  
>  int kvm_init_vcpu(CPUState *cpu);
>  int kvm_cpu_exec(CPUState *cpu);
> +int kvm_destroy_vcpu(CPUState *cpu);
>  
>  #ifdef NEED_CPU_H
>  
> diff --git a/kvm-all.c b/kvm-all.c
> index 4478969..605e00e 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -226,6 +226,31 @@ static void kvm_reset_vcpu(void *opaque)
>      kvm_arch_reset_vcpu(cpu);
>  }
>  
> +int kvm_destroy_vcpu(CPUState *cpu)
> +{
> +    KVMState *s = kvm_state;
> +    long mmap_size;
> +    int ret = 0;
> +
> +    DPRINTF("kvm_destroy_vcpu\n");
> +
> +    mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
> +    if (mmap_size < 0) {
> +        ret = mmap_size;
> +        DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
> +        goto err;
> +    }
> +
> +    ret = munmap(cpu->kvm_run, mmap_size);
> +    if (ret < 0) {
> +        goto err;
> +    }
> +
> +    close(cpu->kvm_fd);
> +err:
> +    return ret;
> +}
> +
>  int kvm_init_vcpu(CPUState *cpu)
>  {
>      KVMState *s = kvm_state;

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

* Re: [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support
  2013-11-28 14:41 ` [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Igor Mammedov
@ 2013-12-04  2:15   ` Chen Fan
  2013-12-04 15:42     ` Igor Mammedov
  2013-12-19  8:10   ` Chen Fan
  1 sibling, 1 reply; 23+ messages in thread
From: Chen Fan @ 2013-12-04  2:15 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, Andreas Färber

On Thu, 2013-11-28 at 15:41 +0100, Igor Mammedov wrote:
> On Wed, 9 Oct 2013 17:43:08 +0800
> Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> 
> > Via implementing ACPI standard methods _EJ0 in bios, after Guest OS hot remove
> > one vCPU, it is able to send a signal to QEMU, then QEMU could notify
> > the assigned vCPU of exiting. meanwhile, and intruduce the QOM command 'cpu-del' to remove
> > vCPU from QEMU itself.
> 
> have you tried following sequence:
> cpu-add 1
> cpu-add 2
> cpu-del 1
> and then do migration?
Hi, Igor, Thanks for your test case. I had test the above sequence, when
I add two vcpu, then delete the first one, I found command 'lscpu' show:
CPU(s):                 1
On-line CPU(s) list:   0,2
off -line CPU(s) list:  

I know it is wrong, but I want to know which is expected to show, A or
B?
A:
CPU(s):               2
On-line CPU(s) list:   0,2
off -line CPU(s) list:

B:
CPU(s):               2
On-line CPU(s) list:   0,1
off -line CPU(s) list:

Thanks,
Chen

> 
> > 
> > this work is based on Andreas Färber's qom-cpu branch tree.
> >     git://github.com/afaerber/qemu-cpu.git
> > 
> > this series patches must be used with seabios patch and KVM patch together.
> > 
> > for KVM patches:
> >     http://comments.gmane.org/gmane.comp.emulators.kvm.devel/114347
> > 
> > for seabios patches:
> >     http://comments.gmane.org/gmane.comp.emulators.qemu/230460
> > 
> > Chen Fan (10):
> >   x86: move apic_state field from CPUX86State to X86CPU
> >   apic: remove redundant variable 'apic_no' from apic_init_common()
> >   apic: remove local_apics array and using CPU_FOREACH instead
> >   x86: add x86_cpu_unrealizefn() for cpu apic remove
> >   qmp: add 'cpu-del' command support
> >   qom cpu: rename variable 'cpu_added_notifier' to
> >     'cpu_hotplug_notifier'
> >   qom cpu: add UNPLUG cpu notifier support
> >   i386: implement pc interface pc_hot_del_cpu()
> >   piix4: implement function cpu_status_write() for vcpu ejection
> >   cpus: reclaim allocated vCPU objects
> > 
> >  cpu-exec.c                      |  2 +-
> >  cpus.c                          | 51 +++++++++++++++++++++--
> >  hw/acpi/piix4.c                 | 66 ++++++++++++++++++++++++------
> >  hw/i386/kvm/apic.c              | 18 +++++++-
> >  hw/i386/kvmvapic.c              |  8 ++--
> >  hw/i386/pc.c                    | 51 ++++++++++++++++++-----
> >  hw/i386/pc_piix.c               |  3 +-
> >  hw/intc/apic.c                  | 91 ++++++++++++++++++++++-------------------
> >  hw/intc/apic_common.c           | 17 ++------
> >  include/hw/boards.h             |  2 +
> >  include/hw/i386/apic_internal.h |  6 +--
> >  include/hw/i386/pc.h            |  1 +
> >  include/qom/cpu.h               | 20 +++++++++
> >  include/sysemu/kvm.h            |  1 +
> >  include/sysemu/sysemu.h         |  2 +-
> >  kvm-all.c                       | 25 +++++++++++
> >  qapi-schema.json                | 12 ++++++
> >  qmp-commands.hx                 | 23 +++++++++++
> >  qmp.c                           |  9 ++++
> >  qom/cpu.c                       | 26 +++++++++---
> >  target-i386/cpu-qom.h           |  5 +++
> >  target-i386/cpu.c               | 57 ++++++++++++++++++++------
> >  target-i386/cpu.h               |  4 --
> >  target-i386/helper.c            |  9 ++--
> >  target-i386/kvm.c               | 23 +++++------
> >  target-i386/misc_helper.c       |  8 ++--
> >  26 files changed, 403 insertions(+), 137 deletions(-)
> > 
> 

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

* Re: [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects
  2013-11-28 14:48   ` Igor Mammedov
@ 2013-12-04  2:28     ` Chen Fan
  0 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-12-04  2:28 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, Andreas Färber

On Thu, 2013-11-28 at 15:48 +0100, Igor Mammedov wrote:
> On Wed, 9 Oct 2013 17:43:18 +0800
> Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> 
> > After ACPI get a signal to eject a vCPU, then it will notify
> > the vCPU thread to exit in KVM, and the vCPU must be removed from CPU list,
> > before the vCPU really removed, there will release the all related vCPU objects.
> > 
> > Signed-off-by: Chen Fan <chen.fan.fnst@cn.fujitsu.com>
> > ---
> >  cpus.c               | 46 ++++++++++++++++++++++++++++++++++++++++++++++
> >  hw/acpi/piix4.c      | 23 +++++++++++++++++------
> >  include/qom/cpu.h    | 10 ++++++++++
> >  include/sysemu/kvm.h |  1 +
> >  kvm-all.c            | 25 +++++++++++++++++++++++++
> >  5 files changed, 99 insertions(+), 6 deletions(-)
> > 
> > diff --git a/cpus.c b/cpus.c
> > index 4ace860..942af0a 100644
> > --- a/cpus.c
> > +++ b/cpus.c
> > @@ -714,6 +714,26 @@ void async_run_on_cpu(CPUState *cpu, void (*func)(void *data), void *data)
> >      qemu_cpu_kick(cpu);
> >  }
> >  
> > +static void qemu_kvm_destroy_vcpu(CPUState *cpu)
> > +{
> > +    CPU_REMOVE(cpu);
> > +
> > +    if (kvm_destroy_vcpu(cpu) < 0) {
> Does it actually do what it's supposed to do?
> If I recall correctly KVM patches were dimmed as not correct approach.
> 
> perhaps in case of KVM for now, it should return failure (i.e. no unplug
> for KVM).
yes, for now there must be to make some patches to release cpu for KVM.
hoping KVM developers could give some advices.

Thanks,
Chen

> 
> > +        fprintf(stderr, "kvm_destroy_vcpu failed.\n");
> > +        exit(1);
> > +    }
> > +
> > +    object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
> > +    qdev_free(DEVICE(cpu));
> > +}
> > +
> > +static void qemu_tcg_destroy_vcpu(CPUState *cpu)
> > +{
> > +    CPU_REMOVE(cpu);
> > +    object_property_set_bool(OBJECT(cpu), false, "realized", NULL);
> > +    qdev_free(DEVICE(cpu));
> > +}
> > +
> >  static void flush_queued_work(CPUState *cpu)
> >  {
> >      struct qemu_work_item *wi;
> > @@ -805,6 +825,11 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
> >              }
> >          }
> >          qemu_kvm_wait_io_event(cpu);
> > +        if (cpu->exit && !cpu_can_run(cpu)) {
> > +            qemu_kvm_destroy_vcpu(cpu);
> > +            qemu_mutex_unlock(&qemu_global_mutex);
> > +            return NULL;
> > +        }
> >      }
> >  
> >      return NULL;
> > @@ -857,6 +882,7 @@ static void tcg_exec_all(void);
> >  static void *qemu_tcg_cpu_thread_fn(void *arg)
> >  {
> >      CPUState *cpu = arg;
> > +    CPUState *remove_cpu = NULL;
> >  
> >      qemu_tcg_init_cpu_signals();
> >      qemu_thread_get_self(cpu->thread);
> > @@ -889,6 +915,16 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
> >              }
> >          }
> >          qemu_tcg_wait_io_event();
> > +        CPU_FOREACH(cpu) {
> > +            if (cpu->exit && !cpu_can_run(cpu)) {
> > +                remove_cpu = cpu;
> > +                break;
> > +            }
> > +        }
> > +        if (remove_cpu) {
> > +            qemu_tcg_destroy_vcpu(remove_cpu);
> > +            remove_cpu = NULL;
> > +        }
> >      }
> >  
> >      return NULL;
> > @@ -1045,6 +1081,13 @@ void resume_all_vcpus(void)
> >      }
> >  }
> >  
> > +void cpu_remove(CPUState *cpu)
> > +{
> > +    cpu->stop = true;
> > +    cpu->exit = true;
> > +    qemu_cpu_kick(cpu);
> > +}
> > +
> >  static void qemu_tcg_init_vcpu(CPUState *cpu)
> >  {
> >      /* share a single thread for all cpus with TCG */
> > @@ -1219,6 +1262,9 @@ static void tcg_exec_all(void)
> >                  break;
> >              }
> >          } else if (cpu->stop || cpu->stopped) {
> > +            if (cpu->exit) {
> > +                next_cpu = CPU_NEXT(cpu);
> > +            }
> >              break;
> >          }
> >      }
> > diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c
> > index fd27001..bde8123 100644
> > --- a/hw/acpi/piix4.c
> > +++ b/hw/acpi/piix4.c
> > @@ -612,10 +612,21 @@ static const MemoryRegionOps piix4_pci_ops = {
> >      },
> >  };
> >  
> > -static void acpi_piix_eject_vcpu(int64_t cpuid)
> > +static void acpi_piix_eject_vcpu(PIIX4PMState *s, int64_t cpuid)
> >  {
> > -    /* TODO: eject a vcpu, release allocated vcpu and exit the vcpu pthread.  */
> > -    PIIX4_DPRINTF("vcpu: %" PRIu64 " need to be ejected.\n", cpuid);
> > +    CPUStatus *g = &s->gpe_cpu;
> > +    CPUState *cpu;
> > +
> > +    CPU_FOREACH(cpu) {
> > +        CPUClass *cc = CPU_GET_CLASS(cpu);
> > +        int64_t id = cc->get_arch_id(cpu);
> > +
> > +        if (cpuid == id) {
> > +            g->old_sts[cpuid / 8] &= ~(1 << (cpuid % 8));
> > +            cpu_remove(cpu);
> > +            break;
> > +        }
> > +    }
> >  }
> >  
> >  static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size)
> > @@ -634,7 +645,7 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
> >      CPUStatus *cpus = &s->gpe_cpu;
> >      uint8_t val;
> >      int i;
> > -    int64_t cpuid = 0;
> > +    int64_t cpuid = -1;
> >  
> >      val = cpus->old_sts[addr] ^ data;
> >  
> > @@ -648,8 +659,8 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data,
> >          }
> >      }
> >  
> > -    if (cpuid != 0) {
> > -        acpi_piix_eject_vcpu(cpuid);
> > +    if (cpuid != -1) {
> > +        acpi_piix_eject_vcpu(s, cpuid);
> >      }
> >  }
> >  
> > diff --git a/include/qom/cpu.h b/include/qom/cpu.h
> > index 0238532..eb8d32b 100644
> > --- a/include/qom/cpu.h
> > +++ b/include/qom/cpu.h
> > @@ -181,6 +181,7 @@ struct CPUState {
> >      bool created;
> >      bool stop;
> >      bool stopped;
> > +    bool exit;
> >      volatile sig_atomic_t exit_request;
> >      volatile sig_atomic_t tcg_exit_req;
> >      uint32_t interrupt_request;
> > @@ -206,6 +207,7 @@ struct CPUState {
> >  QTAILQ_HEAD(CPUTailQ, CPUState);
> >  extern struct CPUTailQ cpus;
> >  #define CPU_NEXT(cpu) QTAILQ_NEXT(cpu, node)
> > +#define CPU_REMOVE(cpu) QTAILQ_REMOVE(&cpus, cpu, node)
> >  #define CPU_FOREACH(cpu) QTAILQ_FOREACH(cpu, &cpus, node)
> >  #define CPU_FOREACH_SAFE(cpu, next_cpu) \
> >      QTAILQ_FOREACH_SAFE(cpu, &cpus, node, next_cpu)
> > @@ -487,6 +489,14 @@ void cpu_exit(CPUState *cpu);
> >  void cpu_resume(CPUState *cpu);
> >  
> >  /**
> > + * qemu_remove_vcpu:
> > + * @cpu: The vCPU to remove.
> > + *
> > + * Requests the CPU @cpu to be removed.
> > + */
> > +void cpu_remove(CPUState *cpu);
> > +
> > +/**
> >   * qemu_init_vcpu:
> >   * @cpu: The vCPU to initialize.
> >   *
> > diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h
> > index 3b25f27..f3f1279 100644
> > --- a/include/sysemu/kvm.h
> > +++ b/include/sysemu/kvm.h
> > @@ -167,6 +167,7 @@ int kvm_has_intx_set_mask(void);
> >  
> >  int kvm_init_vcpu(CPUState *cpu);
> >  int kvm_cpu_exec(CPUState *cpu);
> > +int kvm_destroy_vcpu(CPUState *cpu);
> >  
> >  #ifdef NEED_CPU_H
> >  
> > diff --git a/kvm-all.c b/kvm-all.c
> > index 4478969..605e00e 100644
> > --- a/kvm-all.c
> > +++ b/kvm-all.c
> > @@ -226,6 +226,31 @@ static void kvm_reset_vcpu(void *opaque)
> >      kvm_arch_reset_vcpu(cpu);
> >  }
> >  
> > +int kvm_destroy_vcpu(CPUState *cpu)
> > +{
> > +    KVMState *s = kvm_state;
> > +    long mmap_size;
> > +    int ret = 0;
> > +
> > +    DPRINTF("kvm_destroy_vcpu\n");
> > +
> > +    mmap_size = kvm_ioctl(s, KVM_GET_VCPU_MMAP_SIZE, 0);
> > +    if (mmap_size < 0) {
> > +        ret = mmap_size;
> > +        DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
> > +        goto err;
> > +    }
> > +
> > +    ret = munmap(cpu->kvm_run, mmap_size);
> > +    if (ret < 0) {
> > +        goto err;
> > +    }
> > +
> > +    close(cpu->kvm_fd);
> > +err:
> > +    return ret;
> > +}
> > +
> >  int kvm_init_vcpu(CPUState *cpu)
> >  {
> >      KVMState *s = kvm_state;
> 
> 

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

* Re: [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support
  2013-12-04  2:15   ` Chen Fan
@ 2013-12-04 15:42     ` Igor Mammedov
  2013-12-05  1:08       ` Chen Fan
  0 siblings, 1 reply; 23+ messages in thread
From: Igor Mammedov @ 2013-12-04 15:42 UTC (permalink / raw)
  To: Chen Fan; +Cc: qemu-devel, Andreas Färber

On Wed, 04 Dec 2013 10:15:16 +0800
Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:

> On Thu, 2013-11-28 at 15:41 +0100, Igor Mammedov wrote:
> > On Wed, 9 Oct 2013 17:43:08 +0800
> > Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> > 
> > > Via implementing ACPI standard methods _EJ0 in bios, after Guest OS hot remove
> > > one vCPU, it is able to send a signal to QEMU, then QEMU could notify
> > > the assigned vCPU of exiting. meanwhile, and intruduce the QOM command 'cpu-del' to remove
> > > vCPU from QEMU itself.
> > 
> > have you tried following sequence:
> > cpu-add 1
> > cpu-add 2
> > cpu-del 1
> > and then do migration?
> Hi, Igor, Thanks for your test case. I had test the above sequence, when
> I add two vcpu, then delete the first one, I found command 'lscpu' show:
> CPU(s):                 1
> On-line CPU(s) list:   0,2
> off -line CPU(s) list:  
> 
> I know it is wrong, but I want to know which is expected to show, A or
> B?
> A:
> CPU(s):               2
> On-line CPU(s) list:   0,2
> off -line CPU(s) list:
> 
> B:
> CPU(s):               2
> On-line CPU(s) list:   0,1
> off -line CPU(s) list:
> 

if you deleted #1 CPU than A is correct.

There is certain thing that depend on cpu_index in QEMU code base,
migration is one of them. It should break if for arbitrary CPU removal/addition
is introduced.

> Thanks,
> Chen
> 
> > 
> > > 
> > > this work is based on Andreas Färber's qom-cpu branch tree.
> > >     git://github.com/afaerber/qemu-cpu.git
> > > 
> > > this series patches must be used with seabios patch and KVM patch together.
> > > 
> > > for KVM patches:
> > >     http://comments.gmane.org/gmane.comp.emulators.kvm.devel/114347
> > > 
> > > for seabios patches:
> > >     http://comments.gmane.org/gmane.comp.emulators.qemu/230460
> > > 
> > > Chen Fan (10):
> > >   x86: move apic_state field from CPUX86State to X86CPU
> > >   apic: remove redundant variable 'apic_no' from apic_init_common()
> > >   apic: remove local_apics array and using CPU_FOREACH instead
> > >   x86: add x86_cpu_unrealizefn() for cpu apic remove
> > >   qmp: add 'cpu-del' command support
> > >   qom cpu: rename variable 'cpu_added_notifier' to
> > >     'cpu_hotplug_notifier'
> > >   qom cpu: add UNPLUG cpu notifier support
> > >   i386: implement pc interface pc_hot_del_cpu()
> > >   piix4: implement function cpu_status_write() for vcpu ejection
> > >   cpus: reclaim allocated vCPU objects
> > > 
> > >  cpu-exec.c                      |  2 +-
> > >  cpus.c                          | 51 +++++++++++++++++++++--
> > >  hw/acpi/piix4.c                 | 66 ++++++++++++++++++++++++------
> > >  hw/i386/kvm/apic.c              | 18 +++++++-
> > >  hw/i386/kvmvapic.c              |  8 ++--
> > >  hw/i386/pc.c                    | 51 ++++++++++++++++++-----
> > >  hw/i386/pc_piix.c               |  3 +-
> > >  hw/intc/apic.c                  | 91 ++++++++++++++++++++++-------------------
> > >  hw/intc/apic_common.c           | 17 ++------
> > >  include/hw/boards.h             |  2 +
> > >  include/hw/i386/apic_internal.h |  6 +--
> > >  include/hw/i386/pc.h            |  1 +
> > >  include/qom/cpu.h               | 20 +++++++++
> > >  include/sysemu/kvm.h            |  1 +
> > >  include/sysemu/sysemu.h         |  2 +-
> > >  kvm-all.c                       | 25 +++++++++++
> > >  qapi-schema.json                | 12 ++++++
> > >  qmp-commands.hx                 | 23 +++++++++++
> > >  qmp.c                           |  9 ++++
> > >  qom/cpu.c                       | 26 +++++++++---
> > >  target-i386/cpu-qom.h           |  5 +++
> > >  target-i386/cpu.c               | 57 ++++++++++++++++++++------
> > >  target-i386/cpu.h               |  4 --
> > >  target-i386/helper.c            |  9 ++--
> > >  target-i386/kvm.c               | 23 +++++------
> > >  target-i386/misc_helper.c       |  8 ++--
> > >  26 files changed, 403 insertions(+), 137 deletions(-)
> > > 
> > 
> 
> 

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

* Re: [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support
  2013-12-04 15:42     ` Igor Mammedov
@ 2013-12-05  1:08       ` Chen Fan
  0 siblings, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-12-05  1:08 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, Andreas Färber

On Wed, 2013-12-04 at 16:42 +0100, Igor Mammedov wrote:
> On Wed, 04 Dec 2013 10:15:16 +0800
> Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> 
> > On Thu, 2013-11-28 at 15:41 +0100, Igor Mammedov wrote:
> > > On Wed, 9 Oct 2013 17:43:08 +0800
> > > Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> > > 
> > > > Via implementing ACPI standard methods _EJ0 in bios, after Guest OS hot remove
> > > > one vCPU, it is able to send a signal to QEMU, then QEMU could notify
> > > > the assigned vCPU of exiting. meanwhile, and intruduce the QOM command 'cpu-del' to remove
> > > > vCPU from QEMU itself.
> > > 
> > > have you tried following sequence:
> > > cpu-add 1
> > > cpu-add 2
> > > cpu-del 1
> > > and then do migration?
> > Hi, Igor, Thanks for your test case. I had test the above sequence, when
> > I add two vcpu, then delete the first one, I found command 'lscpu' show:
> > CPU(s):                 1
> > On-line CPU(s) list:   0,2
> > off -line CPU(s) list:  
> > 
> > I know it is wrong, but I want to know which is expected to show, A or
> > B?
> > A:
> > CPU(s):               2
> > On-line CPU(s) list:   0,2
> > off -line CPU(s) list:
> > 
> > B:
> > CPU(s):               2
> > On-line CPU(s) list:   0,1
> > off -line CPU(s) list:
> > 
> 
> if you deleted #1 CPU than A is correct.
> 
> There is certain thing that depend on cpu_index in QEMU code base,
> migration is one of them. It should break if for arbitrary CPU removal/addition
> is introduced.

Thanks for your explaining.

Chen


> > Thanks,
> > Chen
> > 
> > > 
> > > > 
> > > > this work is based on Andreas Färber's qom-cpu branch tree.
> > > >     git://github.com/afaerber/qemu-cpu.git
> > > > 
> > > > this series patches must be used with seabios patch and KVM patch together.
> > > > 
> > > > for KVM patches:
> > > >     http://comments.gmane.org/gmane.comp.emulators.kvm.devel/114347
> > > > 
> > > > for seabios patches:
> > > >     http://comments.gmane.org/gmane.comp.emulators.qemu/230460
> > > > 
> > > > Chen Fan (10):
> > > >   x86: move apic_state field from CPUX86State to X86CPU
> > > >   apic: remove redundant variable 'apic_no' from apic_init_common()
> > > >   apic: remove local_apics array and using CPU_FOREACH instead
> > > >   x86: add x86_cpu_unrealizefn() for cpu apic remove
> > > >   qmp: add 'cpu-del' command support
> > > >   qom cpu: rename variable 'cpu_added_notifier' to
> > > >     'cpu_hotplug_notifier'
> > > >   qom cpu: add UNPLUG cpu notifier support
> > > >   i386: implement pc interface pc_hot_del_cpu()
> > > >   piix4: implement function cpu_status_write() for vcpu ejection
> > > >   cpus: reclaim allocated vCPU objects
> > > > 
> > > >  cpu-exec.c                      |  2 +-
> > > >  cpus.c                          | 51 +++++++++++++++++++++--
> > > >  hw/acpi/piix4.c                 | 66 ++++++++++++++++++++++++------
> > > >  hw/i386/kvm/apic.c              | 18 +++++++-
> > > >  hw/i386/kvmvapic.c              |  8 ++--
> > > >  hw/i386/pc.c                    | 51 ++++++++++++++++++-----
> > > >  hw/i386/pc_piix.c               |  3 +-
> > > >  hw/intc/apic.c                  | 91 ++++++++++++++++++++++-------------------
> > > >  hw/intc/apic_common.c           | 17 ++------
> > > >  include/hw/boards.h             |  2 +
> > > >  include/hw/i386/apic_internal.h |  6 +--
> > > >  include/hw/i386/pc.h            |  1 +
> > > >  include/qom/cpu.h               | 20 +++++++++
> > > >  include/sysemu/kvm.h            |  1 +
> > > >  include/sysemu/sysemu.h         |  2 +-
> > > >  kvm-all.c                       | 25 +++++++++++
> > > >  qapi-schema.json                | 12 ++++++
> > > >  qmp-commands.hx                 | 23 +++++++++++
> > > >  qmp.c                           |  9 ++++
> > > >  qom/cpu.c                       | 26 +++++++++---
> > > >  target-i386/cpu-qom.h           |  5 +++
> > > >  target-i386/cpu.c               | 57 ++++++++++++++++++++------
> > > >  target-i386/cpu.h               |  4 --
> > > >  target-i386/helper.c            |  9 ++--
> > > >  target-i386/kvm.c               | 23 +++++------
> > > >  target-i386/misc_helper.c       |  8 ++--
> > > >  26 files changed, 403 insertions(+), 137 deletions(-)
> > > > 
> > > 
> > 
> > 
> 

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

* Re: [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support
  2013-11-28 14:41 ` [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Igor Mammedov
  2013-12-04  2:15   ` Chen Fan
@ 2013-12-19  8:10   ` Chen Fan
  1 sibling, 0 replies; 23+ messages in thread
From: Chen Fan @ 2013-12-19  8:10 UTC (permalink / raw)
  To: Igor Mammedov; +Cc: qemu-devel, Andreas Färber

On Thu, 2013-11-28 at 15:41 +0100, Igor Mammedov wrote:
> On Wed, 9 Oct 2013 17:43:08 +0800
> Chen Fan <chen.fan.fnst@cn.fujitsu.com> wrote:
> 
> > Via implementing ACPI standard methods _EJ0 in bios, after Guest OS hot remove
> > one vCPU, it is able to send a signal to QEMU, then QEMU could notify
> > the assigned vCPU of exiting. meanwhile, and intruduce the QOM command 'cpu-del' to remove
> > vCPU from QEMU itself.
> 
> have you tried following sequence:
> cpu-add 1
> cpu-add 2
> cpu-del 1
> and then do migration?

Hi, igor,
    I have one question to confirm, After I started VM with -smp 1,
maxcpus=4, then did following sequence:
1) cpu-add id=2
2) migrate

on the destination side,
when I configured the VM with -smp 2, maxcpus=4, then migration failed.
when I configured the VM with -smp 3, maxcpus=4, then the destination VM
has three VCPU threads and could not add cpu 1. was this a bug? or how
to do migration?

Thanks,
Chen

> > 
> > this work is based on Andreas Färber's qom-cpu branch tree.
> >     git://github.com/afaerber/qemu-cpu.git
> > 
> > this series patches must be used with seabios patch and KVM patch together.
> > 
> > for KVM patches:
> >     http://comments.gmane.org/gmane.comp.emulators.kvm.devel/114347
> > 
> > for seabios patches:
> >     http://comments.gmane.org/gmane.comp.emulators.qemu/230460
> > 
> > Chen Fan (10):
> >   x86: move apic_state field from CPUX86State to X86CPU
> >   apic: remove redundant variable 'apic_no' from apic_init_common()
> >   apic: remove local_apics array and using CPU_FOREACH instead
> >   x86: add x86_cpu_unrealizefn() for cpu apic remove
> >   qmp: add 'cpu-del' command support
> >   qom cpu: rename variable 'cpu_added_notifier' to
> >     'cpu_hotplug_notifier'
> >   qom cpu: add UNPLUG cpu notifier support
> >   i386: implement pc interface pc_hot_del_cpu()
> >   piix4: implement function cpu_status_write() for vcpu ejection
> >   cpus: reclaim allocated vCPU objects
> > 
> >  cpu-exec.c                      |  2 +-
> >  cpus.c                          | 51 +++++++++++++++++++++--
> >  hw/acpi/piix4.c                 | 66 ++++++++++++++++++++++++------
> >  hw/i386/kvm/apic.c              | 18 +++++++-
> >  hw/i386/kvmvapic.c              |  8 ++--
> >  hw/i386/pc.c                    | 51 ++++++++++++++++++-----
> >  hw/i386/pc_piix.c               |  3 +-
> >  hw/intc/apic.c                  | 91 ++++++++++++++++++++++-------------------
> >  hw/intc/apic_common.c           | 17 ++------
> >  include/hw/boards.h             |  2 +
> >  include/hw/i386/apic_internal.h |  6 +--
> >  include/hw/i386/pc.h            |  1 +
> >  include/qom/cpu.h               | 20 +++++++++
> >  include/sysemu/kvm.h            |  1 +
> >  include/sysemu/sysemu.h         |  2 +-
> >  kvm-all.c                       | 25 +++++++++++
> >  qapi-schema.json                | 12 ++++++
> >  qmp-commands.hx                 | 23 +++++++++++
> >  qmp.c                           |  9 ++++
> >  qom/cpu.c                       | 26 +++++++++---
> >  target-i386/cpu-qom.h           |  5 +++
> >  target-i386/cpu.c               | 57 ++++++++++++++++++++------
> >  target-i386/cpu.h               |  4 --
> >  target-i386/helper.c            |  9 ++--
> >  target-i386/kvm.c               | 23 +++++------
> >  target-i386/misc_helper.c       |  8 ++--
> >  26 files changed, 403 insertions(+), 137 deletions(-)
> > 
> 

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

end of thread, other threads:[~2013-12-19  8:12 UTC | newest]

Thread overview: 23+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-10-09  9:43 [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 01/10] x86: move apic_state field from CPUX86State to X86CPU Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 02/10] apic: remove redundant variable 'apic_no' from apic_init_common() Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 03/10] apic: remove local_apics array and using CPU_FOREACH instead Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 04/10] x86: add x86_cpu_unrealizefn() for cpu apic remove Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 05/10] qmp: add 'cpu-del' command support Chen Fan
2013-11-27 14:00   ` Eric Blake
2013-11-28  1:14     ` Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 06/10] qom cpu: rename variable 'cpu_added_notifier' to 'cpu_hotplug_notifier' Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 07/10] qom cpu: add UNPLUG cpu notifier support Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 08/10] i386: implement pc interface pc_hot_del_cpu() Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 09/10] piix4: implement function cpu_status_write() for vcpu ejection Chen Fan
2013-11-22  8:02   ` Vasilis Liaskovitis
2013-11-25 18:38     ` Vasilis Liaskovitis
2013-11-27 12:11       ` Chen Fan
2013-10-09  9:43 ` [Qemu-devel] [RFC qom-cpu v4 10/10] cpus: reclaim allocated vCPU objects Chen Fan
2013-11-28 14:48   ` Igor Mammedov
2013-12-04  2:28     ` Chen Fan
2013-11-28 14:41 ` [Qemu-devel] [RFC qom-cpu v4 00/10] i386: add cpu hot remove support Igor Mammedov
2013-12-04  2:15   ` Chen Fan
2013-12-04 15:42     ` Igor Mammedov
2013-12-05  1:08       ` Chen Fan
2013-12-19  8:10   ` Chen Fan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.