Re: [patch] fold struct vcpu_info into CPUState

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

 



On Fri, Oct 17, 2008 at 1:28 PM, Jes Sorensen <jes@xxxxxxx> wrote:
> Glauber Costa wrote:
>>>
>>> @@ -93,7 +74,20 @@
>>>
>>>  CPUState *qemu_kvm_cpu_env(int index)
>>>  {
>
> [snip]
>>>
>>>  }
>>
>> This doesn't seem right. This function exists because we used to have
>> a vcpu and and env structs, that were separated but
>> should be tied together in some uses.
>> Now, there's absolutely nothing in here that is not qemu-specific.
>> This is just a function to return and env given a cpu number.
>> You'll lose the current_env optimization that probably matters a lot
>> in your case, but I'm afraid you will just have to live with that:
>> it sucks for qemu too, and when it is fixed, it will be fixed for both
>> (means getting rid of the ugly cpu_single_env)
>
> Hi Glauber,
>
> I see this function as a temporary transition type thing, it wasn't
> my intention for it to stay permanently, but it's not really called from
> a lot of performance critical places for now.

One more reason to provide a general purpose qemu function, instead of
a kvm specific one.

As for the patch itself, I'll re-review it later. stay tuned

>>>    if (env) {
>>> -        if (!vcpu)
>>> +        if (!current_env->vcpu_info.created)
>>>            signal = 1;
>>
>> !vcpu is probably meant to catch the case in witch the vcpu tls
>> variable is not yet assigned. By dereferencing current_env here,
>> you are probably doing an invalid access. So unless you can prove this
>> is not an issue, should add another test.
>
> Hmmm I think the test got lost because I moved this over in multiple
> steps. It was a thread variable 'cpu_info' prior, but we have no
> guarantee here that current_env is valid. Thanks.
>
>>> -        if (vcpu && env != vcpu->env &&
>>> !vcpu_info[env->cpu_index].signalled)
>>> +        /*
>>> +         * Testing for vcpu_info.created here is really redundant
>>> +         */
>>> +        if (current_env->vcpu_info.created &&
>>> +            env != current_env && env->vcpu_info.signalled)
>>
>> should be !env->vcpu_info.signalled instead?
>
> Good catch!
>
>>>  static void flush_queued_work(CPUState *env)
>>>  {
>>> -    struct vcpu_info *vi = &vcpu_info[env->cpu_index];
>>> +    struct vcpu_info *vi = &env->vcpu_info;
>>>    struct qemu_kvm_work_item *wi;
>>
>> "vi" is not a good name, since emacs users will likely complain.
>> vcpu_info is a much better name.
>
> I'm an Emacs user! It's just a temporary variable, I really don't think
> this matters. We could name it 'ed' just to be different, if you prefer.
>
> Here's an updated version of that patch.
>
> Cheers,
> Jes
>
> PS: I am gone through Wednesday, so should give you a few days to
>    review :)
>
> Merge vcpu_info into CPUState.
>
> Moves definition of vcpu related structs to new header qemu-kvm-vcpu.h
> and declares this struct in i386/ia64/ppc CPUState structs if USE_KVM
> is defined. In addition conver qemu-kvm.c to pull vcpu_info out of
> CPUState.
>
> This eliminates ugly static sized array of struct vcpu_info.
>
> Signed-off-by: Jes Sorensen <jes@xxxxxxx>
>
> ---
>  qemu/qemu-kvm-vcpu.h   |   34 +++++++++++
>  qemu/qemu-kvm.c        |  143
> ++++++++++++++++++++++++++-----------------------
>  qemu/target-i386/cpu.h |    4 +
>  qemu/target-ia64/cpu.h |    5 +
>  qemu/target-ppc/cpu.h  |    5 +
>  5 files changed, 126 insertions(+), 65 deletions(-)
>
> Index: kvm-userspace.git/qemu/qemu-kvm-vcpu.h
> ===================================================================
> --- /dev/null
> +++ kvm-userspace.git/qemu/qemu-kvm-vcpu.h
> @@ -0,0 +1,34 @@
> +/*
> + * qemu/kvm vcpu definitions
> + *
> + * Copyright (C) 2006-2008 Qumranet Technologies
> + *
> + * Licensed under the terms of the GNU GPL version 2 or higher.
> + */
> +#ifndef QEMU_KVM_VCPU_H
> +#define QEMU_KVM_VCPU_H
> +
> +#include <pthread.h>
> +
> +struct qemu_kvm_work_item {
> +    struct qemu_kvm_work_item *next;
> +    void (*func)(void *data);
> +    void *data;
> +    int done;
> +};
> +
> +/*
> + * KVM vcpu struct
> + */
> +struct vcpu_info {
> +    int sipi_needed;
> +    int init;
> +    pthread_t thread;
> +    int signalled;
> +    int stop;
> +    int stopped;
> +    int created;
> +    struct qemu_kvm_work_item *queued_work_first, *queued_work_last;
> +};
> +
> +#endif
> Index: kvm-userspace.git/qemu/qemu-kvm.c
> ===================================================================
> --- kvm-userspace.git.orig/qemu/qemu-kvm.c
> +++ kvm-userspace.git/qemu/qemu-kvm.c
> @@ -22,13 +22,13 @@
>  #include "compatfd.h"
>
>  #include "qemu-kvm.h"
> +#include "qemu-kvm-vcpu.h"
>  #include <libkvm.h>
>  #include <pthread.h>
>  #include <sys/utsname.h>
>  #include <sys/syscall.h>
>  #include <sys/mman.h>
>
> -#define bool _Bool
>  #define false 0
>  #define true 1
>
> @@ -43,31 +43,12 @@
>  pthread_cond_t qemu_system_cond = PTHREAD_COND_INITIALIZER;
>  pthread_cond_t qemu_pause_cond = PTHREAD_COND_INITIALIZER;
>  pthread_cond_t qemu_work_cond = PTHREAD_COND_INITIALIZER;
> -__thread struct vcpu_info *vcpu;
> +__thread struct CPUState *current_env;
>
>  static int qemu_system_ready;
>
>  #define SIG_IPI (SIGRTMIN+4)
>
> -struct qemu_kvm_work_item {
> -    struct qemu_kvm_work_item *next;
> -    void (*func)(void *data);
> -    void *data;
> -    bool done;
> -};
> -
> -struct vcpu_info {
> -    CPUState *env;
> -    int sipi_needed;
> -    int init;
> -    pthread_t thread;
> -    int signalled;
> -    int stop;
> -    int stopped;
> -    int created;
> -    struct qemu_kvm_work_item *queued_work_first, *queued_work_last;
> -} vcpu_info[256];
> -
>  pthread_t io_thread;
>  static int io_thread_fd = -1;
>  static int io_thread_sigfd = -1;
> @@ -93,7 +74,20 @@
>
>  CPUState *qemu_kvm_cpu_env(int index)
>  {
> -    return vcpu_info[index].env;
> +    CPUState *penv;
> +
> +    if (current_env->cpu_index == index)
> +        return current_env;
> +
> +    penv = first_cpu;
> +
> +    while (penv) {
> +        if (penv->cpu_index == index)
> +            return penv;
> +        penv = (CPUState *)penv->next_cpu;
> +    }
> +
> +    return NULL;
>  }
>
>  static void sig_ipi_handler(int n)
> @@ -102,10 +96,10 @@
>
>  static void on_vcpu(CPUState *env, void (*func)(void *data), void *data)
>  {
> -    struct vcpu_info *vi = &vcpu_info[env->cpu_index];
> +    struct vcpu_info *vi = &env->vcpu_info;
>     struct qemu_kvm_work_item wi;
>
> -    if (vi == vcpu) {
> +    if (env == current_env) {
>         func(data);
>         return;
>     }
> @@ -127,7 +121,7 @@
>
>  static void inject_interrupt(void *data)
>  {
> -    cpu_interrupt(vcpu->env, (int)data);
> +    cpu_interrupt(current_env, (int)data);
>  }
>
>  void kvm_inject_interrupt(CPUState *env, int mask)
> @@ -140,29 +134,33 @@
>     int signal = 0;
>
>     if (env) {
> -        if (!vcpu)
> +        if (current_env && !current_env->vcpu_info.created)
>             signal = 1;
> -        if (vcpu && env != vcpu->env &&
> !vcpu_info[env->cpu_index].signalled)
> +        /*
> +         * Testing for vcpu_info.created here is really redundant
> +         */
> +        if (current_env->vcpu_info.created &&
> +            env != current_env && !env->vcpu_info.signalled)
>             signal = 1;
>
>         if (signal) {
> -            vcpu_info[env->cpu_index].signalled = 1;
> -                if (vcpu_info[env->cpu_index].thread)
> -                    pthread_kill(vcpu_info[env->cpu_index].thread,
> SIG_IPI);
> +            env->vcpu_info.signalled = 1;
> +            if (env->vcpu_info.thread)
> +                pthread_kill(env->vcpu_info.thread, SIG_IPI);
>         }
>     }
>  }
>
>  void kvm_update_after_sipi(CPUState *env)
>  {
> -    vcpu_info[env->cpu_index].sipi_needed = 1;
> +    env->vcpu_info.sipi_needed = 1;
>     kvm_update_interrupt_request(env);
>  }
>
>  void kvm_apic_init(CPUState *env)
>  {
>     if (env->cpu_index != 0)
> -       vcpu_info[env->cpu_index].init = 1;
> +       env->vcpu_info.init = 1;
>     kvm_update_interrupt_request(env);
>  }
>
> @@ -240,7 +238,7 @@
>
>  static int has_work(CPUState *env)
>  {
> -    if (!vm_running || (env && vcpu_info[env->cpu_index].stopped))
> +    if (!vm_running || (env && env->vcpu_info.stopped))
>        return 0;
>     if (!env->halted)
>        return 1;
> @@ -249,7 +247,7 @@
>
>  static void flush_queued_work(CPUState *env)
>  {
> -    struct vcpu_info *vi = &vcpu_info[env->cpu_index];
> +    struct vcpu_info *vi = &env->vcpu_info;
>     struct qemu_kvm_work_item *wi;
>
>     if (!vi->queued_work_first)
> @@ -266,6 +264,7 @@
>
>  static void kvm_main_loop_wait(CPUState *env, int timeout)
>  {
> +    struct vcpu_info *vi = &env->vcpu_info;
>     struct timespec ts;
>     int r, e;
>     siginfo_t siginfo;
> @@ -291,49 +290,55 @@
>     cpu_single_env = env;
>     flush_queued_work(env);
>
> -    if (vcpu_info[env->cpu_index].stop) {
> -       vcpu_info[env->cpu_index].stop = 0;
> -       vcpu_info[env->cpu_index].stopped = 1;
> +    if (vi->stop) {
> +       vi->stop = 0;
> +       vi->stopped = 1;
>        pthread_cond_signal(&qemu_pause_cond);
>     }
>
> -    vcpu_info[env->cpu_index].signalled = 0;
> +    vi->signalled = 0;
>  }
>
>  static int all_threads_paused(void)
>  {
> -    int i;
> +    CPUState *penv = first_cpu;
> +
> +    while (penv) {
> +        if (penv->vcpu_info.stop)
> +            return 0;
> +        penv = (CPUState *)penv->next_cpu;
> +    }
>
> -    for (i = 0; i < smp_cpus; ++i)
> -       if (vcpu_info[i].stop)
> -           return 0;
>     return 1;
>  }
>
>  static void pause_all_threads(void)
>  {
> -    int i;
> +    CPUState *penv = first_cpu;
>
>     assert(!cpu_single_env);
>
> -    for (i = 0; i < smp_cpus; ++i) {
> -       vcpu_info[i].stop = 1;
> -       pthread_kill(vcpu_info[i].thread, SIG_IPI);
> +    while (penv) {
> +        penv->vcpu_info.stop = 1;
> +        pthread_kill(penv->vcpu_info.thread, SIG_IPI);
> +        penv = (CPUState *)penv->next_cpu;
>     }
> +
>     while (!all_threads_paused())
>        qemu_cond_wait(&qemu_pause_cond);
>  }
>
>  static void resume_all_threads(void)
>  {
> -    int i;
> +    CPUState *penv = first_cpu;
>
>     assert(!cpu_single_env);
>
> -    for (i = 0; i < smp_cpus; ++i) {
> -       vcpu_info[i].stop = 0;
> -       vcpu_info[i].stopped = 0;
> -       pthread_kill(vcpu_info[i].thread, SIG_IPI);
> +    while (penv) {
> +        penv->vcpu_info.stop = 0;
> +        penv->vcpu_info.stopped = 0;
> +        pthread_kill(penv->vcpu_info.thread, SIG_IPI);
> +        penv = (CPUState *)penv->next_cpu;
>     }
>  }
>
> @@ -348,8 +353,8 @@
>  static void update_regs_for_sipi(CPUState *env)
>  {
>     kvm_arch_update_regs_for_sipi(env);
> -    vcpu_info[env->cpu_index].sipi_needed = 0;
> -    vcpu_info[env->cpu_index].init = 0;
> +    env->vcpu_info.sipi_needed = 0;
> +    env->vcpu_info.init = 0;
>  }
>
>  static void update_regs_for_init(CPUState *env)
> @@ -376,21 +381,23 @@
>
>  void qemu_kvm_system_reset(void)
>  {
> -    int i;
> +    CPUState *penv = first_cpu;
>
>     pause_all_threads();
>
>     qemu_system_reset();
>
> -    for (i = 0; i < smp_cpus; ++i)
> -       kvm_arch_cpu_reset(vcpu_info[i].env);
> +    while (penv) {
> +        kvm_arch_cpu_reset(penv);
> +        penv = (CPUState *)penv->next_cpu;
> +    }
>
>     resume_all_threads();
>  }
>
>  static int kvm_main_loop_cpu(CPUState *env)
>  {
> -    struct vcpu_info *info = &vcpu_info[env->cpu_index];
> +    struct vcpu_info *info = &env->vcpu_info;
>
>     setup_kernel_sigmask(env);
>
> @@ -429,9 +436,8 @@
>     CPUState *env = _env;
>     sigset_t signals;
>
> -    vcpu = &vcpu_info[env->cpu_index];
> -    vcpu->env = env;
> -    vcpu->env->thread_id = kvm_get_thread_id();
> +    current_env = env;
> +    env->thread_id = kvm_get_thread_id();
>     sigfillset(&signals);
>     sigprocmask(SIG_BLOCK, &signals, NULL);
>     kvm_create_vcpu(kvm_context, env->cpu_index);
> @@ -439,7 +445,7 @@
>
>     /* signal VCPU creation */
>     pthread_mutex_lock(&qemu_mutex);
> -    vcpu->created = 1;
> +    current_env->vcpu_info.created = 1;
>     pthread_cond_signal(&qemu_vcpu_cond);
>
>     /* and wait for machine initialization */
> @@ -453,9 +459,9 @@
>
>  void kvm_init_new_ap(int cpu, CPUState *env)
>  {
> -    pthread_create(&vcpu_info[cpu].thread, NULL, ap_main_loop, env);
> +    pthread_create(&env->vcpu_info.thread, NULL, ap_main_loop, env);
>
> -    while (vcpu_info[cpu].created == 0)
> +    while (env->vcpu_info.created == 0)
>        qemu_cond_wait(&qemu_vcpu_cond);
>  }
>
> @@ -613,8 +619,12 @@
>
>  static int kvm_debug(void *opaque, int vcpu)
>  {
> +    CPUState *env;
> +
> +    env = qemu_kvm_cpu_env(vcpu);
> +
>     kvm_debug_stop_requested = 1;
> -    vcpu_info[vcpu].stopped = 1;
> +    env->vcpu_info.stopped = 1;
>     return 1;
>  }
>
> @@ -710,8 +720,11 @@
>
>  static int kvm_shutdown(void *opaque, int vcpu)
>  {
> +    CPUState *env;
> +
> +    env = qemu_kvm_cpu_env(cpu_single_env->cpu_index);
>     /* stop the current vcpu from going back to guest mode */
> -    vcpu_info[cpu_single_env->cpu_index].stopped = 1;
> +    env->vcpu_info.stopped = 1;
>
>     qemu_system_reset_request();
>     return 1;
> Index: kvm-userspace.git/qemu/target-i386/cpu.h
> ===================================================================
> --- kvm-userspace.git.orig/qemu/target-i386/cpu.h
> +++ kvm-userspace.git/qemu/target-i386/cpu.h
> @@ -45,6 +45,7 @@
>  #include "cpu-defs.h"
>
>  #include "softfloat.h"
> +#include "qemu-kvm-vcpu.h"
>
>  #define R_EAX 0
>  #define R_ECX 1
> @@ -622,6 +623,9 @@
>  #define NR_IRQ_WORDS (256/ BITS_PER_LONG)
>     uint32_t kvm_interrupt_bitmap[NR_IRQ_WORDS];
>
> +#ifdef USE_KVM
> +    struct vcpu_info vcpu_info;
> +#endif
>     /* in order to simplify APIC support, we leave this pointer to the
>        user */
>     struct APICState *apic_state;
> Index: kvm-userspace.git/qemu/target-ia64/cpu.h
> ===================================================================
> --- kvm-userspace.git.orig/qemu/target-ia64/cpu.h
> +++ kvm-userspace.git/qemu/target-ia64/cpu.h
> @@ -40,10 +40,15 @@
>  #include "cpu-defs.h"
>
>  #include "softfloat.h"
> +#include "qemu-kvm-vcpu.h"
> +
>  typedef struct CPUIA64State {
>     CPU_COMMON;
>     uint32_t hflags;
>     int mp_state;
> +#ifdef USE_KVM
> +    struct vcpu_info vcpu_info;
> +#endif
>  } CPUIA64State;
>
>  #define CPUState CPUIA64State
> Index: kvm-userspace.git/qemu/target-ppc/cpu.h
> ===================================================================
> --- kvm-userspace.git.orig/qemu/target-ppc/cpu.h
> +++ kvm-userspace.git/qemu/target-ppc/cpu.h
> @@ -22,6 +22,7 @@
>
>  #include "config.h"
>  #include <inttypes.h>
> +#include "qemu-kvm-vcpu.h"
>
>  //#define PPC_EMULATE_32BITS_HYPV
>
> @@ -578,6 +579,10 @@
>
>     CPU_COMMON
>
> +#ifdef USE_KVM
> +    struct vcpu_info vcpu_info;
> +#endif
> +
>     int access_type; /* when a memory exception occurs, the access
>                         type is stored here */
>
>
>



-- 
Glauber  Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."
--
To unsubscribe from this list: send the line "unsubscribe kvm-ia64" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux KVM Devel]     [Linux Virtualization]     [Big List of Linux Books]     [Linux SCSI]     [Yosemite Forum]

  Powered by Linux