qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH 4/5] QEMU Release vcpu and finally exit vcpu thr


From: ShaoHe Feng
Subject: Re: [Qemu-devel] [PATCH 4/5] QEMU Release vcpu and finally exit vcpu thread safely
Date: Tue, 29 Nov 2011 13:37:09 +0800
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:7.0.1) Gecko/20110929 Thunderbird/7.0.1

Ping Fan,

 IMO, QEMU should Release vcpu and finally exit vcpu thread safely in
tcg mode?
---
 cpus.c |   21 ++++++++++++++++++++-
 1 files changed, 20 insertions(+), 1 deletions(-)

diff --git a/cpus.c b/cpus.c
index 82530c4..cc52327 100644
--- a/cpus.c
+++ b/cpus.c
@@ -753,7 +753,7 @@ static void tcg_exec_all(void);
 static void *qemu_tcg_cpu_thread_fn(void *arg)
 {
     CPUState *env = arg;
-
+    CPUState *prev = NULL;
     qemu_tcg_init_cpu_signals();
     qemu_thread_get_self(env->thread);
 
@@ -775,10 +775,29 @@ static void *qemu_tcg_cpu_thread_fn(void *arg)
         if (use_icount && qemu_clock_deadline(vm_clock) <= 0) {
             qemu_notify_event();
         }
+        /*1,try to zap; 2, can safe to destroy*/
+        if (env->state == CPU_STATE_ZAPPED) {
+            goto zapout;
+        }
         qemu_tcg_wait_io_event();
     }
 
     return NULL;
+zapout:
+    prev = first_cpu;
+    if (prev == env) {
+        first_cpu = env->next_cpu;
+    } else {
+        while (prev != NULL) {
+            if (prev->next_cpu == env) {
+                break;
+            }
+            prev = prev->next_cpu;
+        }
+        prev->next_cpu = env->next_cpu;
+    }
+    cpu_free(env);
+    return NULL;
 }
 
 static void qemu_cpu_kick_thread(CPUState *env)
-- 
1.7.5.4

, Liu Ping Fan wrote:
> From: Liu Ping Fan <address@hidden>
>
> When guest driver tell us that the vcpu is no longer needed,
> qemu can release the vcpu and finally exit vcpu thread
>
> Signed-off-by: Liu Ping Fan <address@hidden>
> ---
>  cpu-defs.h        |    5 +++++
>  cpus.c            |   21 +++++++++++++++++++++
>  hmp-commands.hx   |    2 +-
>  hw/acpi_piix4.c   |   19 ++++++++++++++++---
>  hw/pci_cpustate.c |   22 ++++++++++++++++++++++
>  kvm-all.c         |   11 ++++++++++-
>  monitor.c         |   12 +++++++-----
>  7 files changed, 82 insertions(+), 10 deletions(-)
>
> diff --git a/cpu-defs.h b/cpu-defs.h
> index db48a7a..cb69a07 100644
> --- a/cpu-defs.h
> +++ b/cpu-defs.h
> @@ -153,6 +153,10 @@ typedef struct CPUWatchpoint {
>      QTAILQ_ENTRY(CPUWatchpoint) entry;
>  } CPUWatchpoint;
>
> +#define CPU_STATE_RUNNING 0
> +#define CPU_STATE_ZAPREQ 1
> +#define CPU_STATE_ZAPPED 2
> +
>  #define CPU_TEMP_BUF_NLONGS 128
>  #define CPU_COMMON                                                      \
>      struct TranslationBlock *current_tb; /* currently executing TB  */  \
> @@ -210,6 +214,7 @@ typedef struct CPUWatchpoint {
>      uint32_t created;                                                   \
>      uint32_t stop;   /* Stop request */                                 \
>      uint32_t stopped; /* Artificially stopped */                        \
> +    uint32_t state; /*state indicator*/                             \
>      struct QemuThread *thread;                                          \
>      struct QemuCond *halt_cond;                                         \
>      int thread_kicked;                                                  \
> diff --git a/cpus.c b/cpus.c
> index c996ac5..e479476 100644
> --- a/cpus.c
> +++ b/cpus.c
> @@ -33,6 +33,7 @@
>
>  #include "qemu-thread.h"
>  #include "cpus.h"
> +#include "cpu.h"
>
>  #ifndef _WIN32
>  #include "compatfd.h"
> @@ -778,6 +779,7 @@ static void qemu_kvm_wait_io_event(CPUState *env)
>  static void *qemu_kvm_cpu_thread_fn(void *arg)
>  {
>      CPUState *env = arg;
> +    CPUState *prev = NULL;
>      int r;
>
>      qemu_mutex_lock(&qemu_global_mutex);
> @@ -808,10 +810,29 @@ static void *qemu_kvm_cpu_thread_fn(void *arg)
>                  cpu_handle_guest_debug(env);
>              }
>          }
> +        /*1,try to zap; 2, can safe to destroy*/
> +        if (env->state == CPU_STATE_ZAPPED) {
> +            goto zapout;
> +        }
>          qemu_kvm_wait_io_event(env);
>      }
>
>      return NULL;
> +zapout:
> +    prev = first_cpu;
> +    if (prev == env) {
> +        first_cpu = env->next_cpu;
> +    } else {
> +        while (prev != NULL) {
> +            if (prev->next_cpu == env) {
> +                break;
> +            }
> +            prev = prev->next_cpu;
> +        }
> +        prev->next_cpu = env->next_cpu;
> +    }
> +    cpu_free(env);
> +    return NULL;
>  }
>
>  static void *qemu_tcg_cpu_thread_fn(void *arg)
> diff --git a/hmp-commands.hx b/hmp-commands.hx
> index ed5c9b9..b642a34 100644
> --- a/hmp-commands.hx
> +++ b/hmp-commands.hx
> @@ -1218,7 +1218,7 @@ ETEXI
>      {
>          .name       = "cpu_set",
>          .args_type  = "cpu:i,state:s",
> -        .params     = "cpu [online|offline]",
> +        .params     = "cpu [online|offline|zap]",
>          .help       = "change cpu state",
>          .mhandler.cmd  = do_cpu_set_nr,
>      },
> diff --git a/hw/acpi_piix4.c b/hw/acpi_piix4.c
> index f585226..1f3ed06 100644
> --- a/hw/acpi_piix4.c
> +++ b/hw/acpi_piix4.c
> @@ -605,10 +605,23 @@ void qemu_system_cpu_hot_add(int cpu, int state)
>          env->cpuid_apic_id = cpu;
>      }
>
> -    if (state)
> -        enable_processor(s, cpu);
> -    else
> +    switch (state) {
> +    /*zap vcpu*/
> +    case 0:
> +        env = qemu_get_cpu(cpu);
> +        /*1 means try to zap*/
> +        env->state = CPU_STATE_ZAPREQ;
> +        disable_processor(s, cpu);
> +        break;
> +    /*offline vcpu*/
> +    case 1:
>          disable_processor(s, cpu);
> +        break;
> +    /*onine vcpu*/
> +    case 2:
> +        enable_processor(s, cpu);
> +        break;
> +    }
>
>      pm_update_sci(s);
>  }
> diff --git a/hw/pci_cpustate.c b/hw/pci_cpustate.c
> index fd31a1f..18402cf 100644
> --- a/hw/pci_cpustate.c
> +++ b/hw/pci_cpustate.c
> @@ -24,6 +24,8 @@
>  #include "loader.h"
>  #include "sysemu.h"
>  #include "iov.h"
> +#include <linux/kvm.h>
> +#include "kvm.h"
>
>  #define PCI_DEVICE_ID_CPUSTATE  0x1010
>  #define CPUSTATE_REGS_SIZE  0x1000
> @@ -52,6 +54,26 @@ static void
>  cpustate_mmio_write(void *opaque, target_phys_addr_t addr, uint64_t val,
>                   unsigned size)
>  {
> +    CPUState *env;
> +    int ret;
> +    struct kvm_vcpu_state state;
> +    switch (addr) {
> +    /*apic id*/
> +    case 0:
> +        env = cpu_phyid_to_cpu(val);
> +        if (env != NULL) {
> +            if (env->state == CPU_STATE_ZAPREQ) {
> +                state.vcpu_id = env->cpu_index;
> +                state.state = 1;
> +                ret = kvm_vm_ioctl(env->kvm_state, KVM_SETSTATE_VCPU, 
> &state);
> +            }
> +        }
> +        break;
> +    case 4:
> +        break;
> +    default:
> +        break;
> +    }
>  }
>
>  static uint64_t
> diff --git a/kvm-all.c b/kvm-all.c
> index 8dd354e..b295262 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -64,6 +64,7 @@ struct KVMState
>      int vmfd;
>      int coalesced_mmio;
>      struct kvm_coalesced_mmio_ring *coalesced_mmio_ring;
> +    long mmap_size;
>      int broken_set_mem_region;
>      int migration_log;
>      int vcpu_events;
> @@ -228,7 +229,7 @@ int kvm_init_vcpu(CPUState *env)
>          DPRINTF("KVM_GET_VCPU_MMAP_SIZE failed\n");
>          goto err;
>      }
> -
> +    env->kvm_state->mmap_size = mmap_size;
>      env->kvm_run = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED,
>                          env->kvm_fd, 0);
>      if (env->kvm_run == MAP_FAILED) {
> @@ -1026,6 +1027,13 @@ int kvm_cpu_exec(CPUState *env)
>          case KVM_EXIT_INTERNAL_ERROR:
>              ret = kvm_handle_internal_error(env, run);
>              break;
> +        case KVM_EXIT_VCPU_DEAD:
> +            ret = munmap(env->kvm_run, env->kvm_state->mmap_size);
> +            ret = close(env->kvm_fd);
> +            env->state = CPU_STATE_ZAPPED;
> +            qemu_mutex_unlock_iothread();
> +            goto out;
> +            break;
>          default:
>              DPRINTF("kvm_arch_handle_exit\n");
>              ret = kvm_arch_handle_exit(env, run);
> @@ -1033,6 +1041,7 @@ int kvm_cpu_exec(CPUState *env)
>          }
>      } while (ret == 0);
>
> +out:
>      if (ret < 0) {
>          cpu_dump_state(env, stderr, fprintf, CPU_DUMP_CODE);
>          vm_stop(VMSTOP_PANIC);
> diff --git a/monitor.c b/monitor.c
> index cb485bf..51c8c52 100644
> --- a/monitor.c
> +++ b/monitor.c
> @@ -971,11 +971,13 @@ static void do_cpu_set_nr(Monitor *mon, const QDict 
> *qdict)
>      status = qdict_get_str(qdict, "state");
>      value = qdict_get_int(qdict, "cpu");
>
> -    if (!strcmp(status, "online"))
> -       state = 1;
> -    else if (!strcmp(status, "offline"))
> -       state = 0;
> -    else {
> +    if (!strcmp(status, "online")) {
> +        state = 2;
> +    } else if (!strcmp(status, "offline")) {
> +        state = 1;
> +    } else if (!strcmp(status, "zap")) {
> +        state = 0;
> +    } else {
>          monitor_printf(mon, "invalid status: %s\n", status);
>          return;
>      }




reply via email to

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