After ACPI get a signal to eject a vcpu, then it will notify the vcpu thread of needing to exit, before the vcpu exiting, will release the vcpu related objects.
Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com> --- cpus.c | 36 ++++++++++++++++++++++++++++++++++++ hw/acpi/piix4.c | 16 ++++++++++++---- include/qom/cpu.h | 9 +++++++++ include/sysemu/kvm.h | 1 + kvm-all.c | 26 ++++++++++++++++++++++++++ 5 files changed, 84 insertions(+), 4 deletions(-) diff --git a/cpus.c b/cpus.c index 70cc617..6b793cb 100644 --- a/cpus.c +++ b/cpus.c @@ -697,6 +697,30 @@ 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) +{ + CPUState *pcpu, *pcpu1; + + pcpu = first_cpu; + pcpu1 = NULL; + + while (pcpu) { + if (pcpu == cpu && pcpu1) { + pcpu1->next_cpu = cpu->next_cpu; + break; + } + pcpu1 = pcpu; + pcpu = pcpu->next_cpu; + } + + if (kvm_destroy_vcpu(cpu) < 0) { + fprintf(stderr, "kvm_destroy_vcpu failed.\n"); + exit(1); + } + + qdev_free(DEVICE(X86_CPU(cpu))); +} + static void flush_queued_work(CPUState *cpu) { struct qemu_work_item *wi; @@ -788,6 +812,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; @@ -1080,6 +1109,13 @@ static void qemu_dummy_start_vcpu(CPUState *cpu) } } +void qemu_down_vcpu(CPUState *cpu) +{ + cpu->stop = true; + cpu->exit = true; + qemu_cpu_kick(cpu); +} + void qemu_init_vcpu(CPUState *cpu) { cpu->nr_cores = smp_cores; diff --git a/hw/acpi/piix4.c b/hw/acpi/piix4.c index 1aaa7a4..44bc809 100644 --- a/hw/acpi/piix4.c +++ b/hw/acpi/piix4.c @@ -611,10 +611,18 @@ 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 *cpus = &s->gpe_cpu; + CPUState *cs = NULL; + + cs = qemu_get_cpu(cpuid); + if (cs == NULL) { + return; + } + + cpus->old_sts[cpuid / 8] &= ~(1 << (cpuid % 8)); + qemu_down_vcpu(cs); } static uint64_t cpu_status_read(void *opaque, hwaddr addr, unsigned int size) @@ -647,7 +655,7 @@ static void cpu_status_write(void *opaque, hwaddr addr, uint64_t data, } if (cpuid != 0) { - acpi_piix_eject_vcpu(cpuid); + acpi_piix_eject_vcpu(s, cpuid); } } diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 3e49936..fa8ec8a 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -180,6 +180,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; @@ -489,6 +490,14 @@ void cpu_exit(CPUState *cpu); void cpu_resume(CPUState *cpu); /** + * qemu_down_vcpu: + * @cpu: The vCPU will to down. + * + * Down a vCPU. + */ +void qemu_down_vcpu(CPUState *cpu); + +/** * qemu_init_vcpu: * @cpu: The vCPU to initialize. * diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index de74411..fd85605 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -158,6 +158,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 716860f..fda3601 100644 --- a/kvm-all.c +++ b/kvm-all.c @@ -225,6 +225,32 @@ 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