* [patch] fold struct vcpu_info into CPUState
@ 2008-09-29 15:24 Jes Sorensen
2008-10-05 10:02 ` Avi Kivity
2008-10-13 22:24 ` Glauber Costa
0 siblings, 2 replies; 15+ messages in thread
From: Jes Sorensen @ 2008-09-29 15:24 UTC (permalink / raw)
To: kvm, kvm-ia64
[-- Attachment #1: Type: text/plain, Size: 367 bytes --]
Hi,
Trying to get rid of the static declaration of the vcpu_info array, this
patch folds it into CPUState. I have only been able to test it on ia64,
but it seems to behave as expect, however ia64 SMP support is still a
bit flakey, so I would appreciate it if someone would test this on x86
and PPC. It builds on x86_64 at least.
Comments appreciated.
Thanks,
Jes
[-- Attachment #2: 0010-qemu-kvm-vcpu_info.patch --]
[-- Type: text/plain, Size: 11149 bytes --]
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@sgi.com>
---
qemu/qemu-kvm-vcpu.h | 34 +++++++++++
qemu/qemu-kvm.c | 141 ++++++++++++++++++++++++++-----------------------
qemu/target-i386/cpu.h | 4 +
qemu/target-ia64/cpu.h | 5 +
qemu/target-ppc/cpu.h | 5 +
5 files changed, 125 insertions(+), 64 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;
}
@@ -130,29 +124,33 @@
int signal = 0;
if (env) {
- if (!vcpu)
+ if (!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);
}
@@ -225,7 +223,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;
@@ -234,7 +232,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)
@@ -251,6 +249,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;
@@ -276,49 +275,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;
}
}
@@ -333,8 +338,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)
@@ -361,21 +366,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);
@@ -414,9 +421,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);
@@ -424,7 +430,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 */
@@ -438,9 +444,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);
}
@@ -598,8 +604,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;
}
@@ -695,8 +705,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
@@ -601,6 +602,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
@@ -41,10 +41,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 */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-09-29 15:24 [patch] fold struct vcpu_info into CPUState Jes Sorensen
@ 2008-10-05 10:02 ` Avi Kivity
2008-10-05 20:48 ` Glauber Costa
2008-10-13 22:24 ` Glauber Costa
1 sibling, 1 reply; 15+ messages in thread
From: Avi Kivity @ 2008-10-05 10:02 UTC (permalink / raw)
To: Jes Sorensen; +Cc: kvm, kvm-ia64, Glauber Costa
Jes Sorensen wrote:
> Hi,
>
> Trying to get rid of the static declaration of the vcpu_info array, this
> patch folds it into CPUState. I have only been able to test it on ia64,
> but it seems to behave as expect, however ia64 SMP support is still a
> bit flakey, so I would appreciate it if someone would test this on x86
> and PPC. It builds on x86_64 at least.
>
> Comments appreciated.
Looks reasonable to me. Glommer, please review this as well. Does this
help or interfere with your efforts?
--
error compiling committee.c: too many arguments to function
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-05 10:02 ` Avi Kivity
@ 2008-10-05 20:48 ` Glauber Costa
0 siblings, 0 replies; 15+ messages in thread
From: Glauber Costa @ 2008-10-05 20:48 UTC (permalink / raw)
To: Avi Kivity; +Cc: Jes Sorensen, kvm, kvm-ia64, Glauber Costa
On Sun, Oct 5, 2008 at 12:02 PM, Avi Kivity <avi@redhat.com> wrote:
> Jes Sorensen wrote:
>>
>> Hi,
>>
>> Trying to get rid of the static declaration of the vcpu_info array, this
>> patch folds it into CPUState. I have only been able to test it on ia64,
>> but it seems to behave as expect, however ia64 SMP support is still a
>> bit flakey, so I would appreciate it if someone would test this on x86
>> and PPC. It builds on x86_64 at least.
>>
>> Comments appreciated.
>
> Looks reasonable to me. Glommer, please review this as well. Does this
> help or interfere with your efforts?
I am travelling this week, and will only be able to provide an
extensible review in a few days. However, me and Jes have already
discussed, and it seem to get along fine with what I am doing.
It makes sense for the accelerator to be able to register an opaque of
its own in cpu state, so I will be working on a patch for exactly that
shortly
>
> --
> error compiling committee.c: too many arguments to function
>
> --
> To unsubscribe from this list: send the line "unsubscribe kvm" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>
--
Glauber Costa.
"Free as in Freedom"
http://glommer.net
"The less confident you are, the more serious you have to act."
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-09-29 15:24 [patch] fold struct vcpu_info into CPUState Jes Sorensen
2008-10-05 10:02 ` Avi Kivity
@ 2008-10-13 22:24 ` Glauber Costa
2008-10-17 15:28 ` Jes Sorensen
1 sibling, 1 reply; 15+ messages in thread
From: Glauber Costa @ 2008-10-13 22:24 UTC (permalink / raw)
To: Jes Sorensen; +Cc: kvm, kvm-ia64
> Index: kvm-userspace.git/qemu/qemu-kvm-vcpu.h
> ===================================================================
> --- /dev/null
> +++ kvm-userspace.git/qemu/qemu-kvm-vcpu.h
can't it be just qemu-kvm.h ?
> 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"
>
> +__thread struct CPUState *current_env;
>
> static int qemu_system_ready;
>
> #define SIG_IPI (SIGRTMIN+4)
>
> 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;
> }
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)
> 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.
> - 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?
> 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.
The rest seems pretty straightforward.
--
Glauber Costa.
"Free as in Freedom"
http://glommer.net
"The less confident you are, the more serious you have to act."
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-13 22:24 ` Glauber Costa
@ 2008-10-17 15:28 ` Jes Sorensen
2008-10-17 21:27 ` Glauber Costa
0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2008-10-17 15:28 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm, kvm-ia64
[-- Attachment #1: Type: text/plain, Size: 2381 bytes --]
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.
>> 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 :)
[-- Attachment #2: 0010-qemu-kvm-vcpu_info-v2.patch --]
[-- Type: text/plain, Size: 11375 bytes --]
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@sgi.com>
---
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 */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-17 15:28 ` Jes Sorensen
@ 2008-10-17 21:27 ` Glauber Costa
2008-10-24 15:57 ` Jes Sorensen
0 siblings, 1 reply; 15+ messages in thread
From: Glauber Costa @ 2008-10-17 21:27 UTC (permalink / raw)
To: Jes Sorensen; +Cc: kvm, kvm-ia64
On Fri, Oct 17, 2008 at 1:28 PM, Jes Sorensen <jes@sgi.com> 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@sgi.com>
>
> ---
> 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."
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-17 21:27 ` Glauber Costa
@ 2008-10-24 15:57 ` Jes Sorensen
2008-10-24 19:10 ` Hollis Blanchard
0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2008-10-24 15:57 UTC (permalink / raw)
To: Glauber Costa; +Cc: kvm, kvm-ia64, Hollis Blanchard
[-- Attachment #1: Type: text/plain, Size: 383 bytes --]
Hi,
Here's an updated version of the patch, which builds against Avi's
current tree. Please note this is a bit of a work in progress version
as I am trying to eliminate the need for the vcpu -> env linear
conversion, but I wanted to send out something before heading off for
the weekend.
Hollis if you have time to check this out for PPC, I would much
appreciate it.
Cheers,
Jes
[-- Attachment #2: 0010-qemu-kvm-vcpu_info-v3.patch --]
[-- Type: text/plain, Size: 15225 bytes --]
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@sgi.com>
---
libkvm/kvm-common.h | 4 -
libkvm/libkvm.c | 14 ++--
libkvm/libkvm.h | 6 +-
qemu/qemu-kvm-vcpu.h | 34 +++++++++++
qemu/qemu-kvm.c | 146 +++++++++++++++++++++++++------------------------
qemu/target-i386/cpu.h | 4 +
qemu/target-ia64/cpu.h | 5 +
qemu/target-ppc/cpu.h | 5 +
8 files changed, 136 insertions(+), 82 deletions(-)
Index: kvm-userspace.git/libkvm/kvm-common.h
===================================================================
--- kvm-userspace.git.orig/libkvm/kvm-common.h
+++ kvm-userspace.git/libkvm/kvm-common.h
@@ -84,11 +84,11 @@
void kvm_show_code(kvm_context_t kvm, int vcpu);
int handle_halt(kvm_context_t kvm, int vcpu);
-int handle_shutdown(kvm_context_t kvm, int vcpu);
+int handle_shutdown(kvm_context_t kvm, void *env);
void post_kvm_run(kvm_context_t kvm, int vcpu);
int pre_kvm_run(kvm_context_t kvm, int vcpu);
int handle_io_window(kvm_context_t kvm);
-int handle_debug(kvm_context_t kvm, int vcpu);
+int handle_debug(kvm_context_t kvm, void *env);
int try_push_interrupts(kvm_context_t kvm);
#endif
Index: kvm-userspace.git/libkvm/libkvm.c
===================================================================
--- kvm-userspace.git.orig/libkvm/libkvm.c
+++ kvm-userspace.git/libkvm/libkvm.c
@@ -738,9 +738,9 @@
return 0;
}
-int handle_debug(kvm_context_t kvm, int vcpu)
+int handle_debug(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->debug(kvm->opaque, vcpu);
+ return kvm->callbacks->debug(kvm->opaque, env);
}
int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
@@ -822,9 +822,9 @@
return kvm->callbacks->halt(kvm->opaque, vcpu);
}
-int handle_shutdown(kvm_context_t kvm, int vcpu)
+int handle_shutdown(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->shutdown(kvm->opaque, vcpu);
+ return kvm->callbacks->shutdown(kvm->opaque, env);
}
int try_push_interrupts(kvm_context_t kvm)
@@ -872,7 +872,7 @@
#endif
}
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)
{
int r;
int fd = kvm->vcpu_fd[vcpu];
@@ -948,7 +948,7 @@
r = handle_io(kvm, run, vcpu);
break;
case KVM_EXIT_DEBUG:
- r = handle_debug(kvm, vcpu);
+ r = handle_debug(kvm, env);
break;
case KVM_EXIT_MMIO:
r = handle_mmio(kvm, run);
@@ -962,7 +962,7 @@
#endif
break;
case KVM_EXIT_SHUTDOWN:
- r = handle_shutdown(kvm, vcpu);
+ r = handle_shutdown(kvm, env);
break;
#if defined(__s390__)
case KVM_EXIT_S390_SIEIC:
Index: kvm-userspace.git/libkvm/libkvm.h
===================================================================
--- kvm-userspace.git.orig/libkvm/libkvm.h
+++ kvm-userspace.git/libkvm/libkvm.h
@@ -55,7 +55,7 @@
/// generic memory writes to unmapped memory (For MMIO devices)
int (*mmio_write)(void *opaque, uint64_t addr, uint8_t *data,
int len);
- int (*debug)(void *opaque, int vcpu);
+ int (*debug)(void *opaque, void *env);
/*!
* \brief Called when the VCPU issues an 'hlt' instruction.
*
@@ -63,7 +63,7 @@
* on the host CPU.
*/
int (*halt)(void *opaque, int vcpu);
- int (*shutdown)(void *opaque, int vcpu);
+ int (*shutdown)(void *opaque, void *env);
int (*io_window)(void *opaque);
int (*try_push_interrupts)(void *opaque);
int (*try_push_nmi)(void *opaque);
@@ -181,7 +181,7 @@
* return except for when an error has occured, or when you have sent it
* an EINTR signal.
*/
-int kvm_run(kvm_context_t kvm, int vcpu);
+int kvm_run(kvm_context_t kvm, int vcpu, void *env);
/*!
* \brief Get interrupt flag from on last exit to userspace
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);
}
@@ -227,7 +225,7 @@
{
int r;
- r = kvm_run(kvm_context, env->cpu_index);
+ r = kvm_run(kvm_context, env->cpu_index, env);
if (r < 0) {
printf("kvm_run returned %d\n", r);
exit(1);
@@ -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,7 +353,7 @@
static void update_regs_for_sipi(CPUState *env)
{
kvm_arch_update_regs_for_sipi(env);
- vcpu_info[env->cpu_index].sipi_needed = 0;
+ env->vcpu_info.sipi_needed = 0;
}
static void update_regs_for_init(CPUState *env)
@@ -361,11 +366,11 @@
#ifdef TARGET_I386
/* restore SIPI vector */
- if(vcpu_info[env->cpu_index].sipi_needed)
+ if(env->vcpu_info.sipi_needed)
env->segs[R_CS] = cs;
-
- vcpu_info[env->cpu_index].init = 0;
#endif
+
+ env->vcpu_info.init = 0;
kvm_arch_load_regs(env);
}
@@ -387,21 +392,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);
@@ -442,9 +449,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);
@@ -452,7 +458,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 */
@@ -466,9 +472,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);
}
@@ -624,10 +630,10 @@
return 0;
}
-static int kvm_debug(void *opaque, int vcpu)
+static int kvm_debug(void *opaque, struct CPUState *env)
{
kvm_debug_stop_requested = 1;
- vcpu_info[vcpu].stopped = 1;
+ env->vcpu_info.stopped = 1;
return 1;
}
@@ -721,10 +727,10 @@
return kvm_arch_halt(opaque, vcpu);
}
-static int kvm_shutdown(void *opaque, int vcpu)
+static int kvm_shutdown(void *opaque, struct CPUState *env)
{
/* 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 */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-24 15:57 ` Jes Sorensen
@ 2008-10-24 19:10 ` Hollis Blanchard
2008-10-27 9:48 ` Jes Sorensen
2008-10-27 16:06 ` [patch] " Jes Sorensen
0 siblings, 2 replies; 15+ messages in thread
From: Hollis Blanchard @ 2008-10-24 19:10 UTC (permalink / raw)
To: Jes Sorensen; +Cc: Glauber Costa, kvm, kvm-ia64
On Fri, 2008-10-24 at 17:57 +0200, Jes Sorensen wrote:
> Hi,
>
> Here's an updated version of the patch, which builds against Avi's
> current tree. Please note this is a bit of a work in progress version
> as I am trying to eliminate the need for the vcpu -> env linear
> conversion, but I wanted to send out something before heading off for
> the weekend.
>
> Hollis if you have time to check this out for PPC, I would much
> appreciate it.
Unfortunately qemu segfaults halfway through guest kernel boot:
...
virtio-pci 0000:00:01.0: enabling device (0000 -> 0001)
vda:Segmentation fault
This is 100% repeatable, and it doesn't happen without your patch
applied.
0x10116f1c in kvm_update_interrupt_request (env=0x103d4718)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/qemu-kvm.c:142
142 if (current_env->vcpu_info.created &&
(gdb) bt
#0 0x10116f1c in kvm_update_interrupt_request (env=0x103d4718)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/qemu-kvm.c:142
#1 0x100b4a74 in cpu_interrupt (env=0x103d4718, mask=0x2)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/exec.c:1507
#2 0x10033d04 in ppc_set_irq (env=0x0, n_IRQ=0x2, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/ppc.c:41
#3 0x10033e4c in ppc40x_set_irq (opaque=0x103d4718, pin=0x4, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/ppc.c:400
#4 0x44004084 in ?? ()
#5 0x1007cc40 in qemu_set_irq (irq=0x103d4718, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/irq.c:38
#6 0x1006e408 in ppcuic_trigger_irq (uic=0x103f2c80)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/irq.h:19
#7 0x1007cc40 in qemu_set_irq (irq=0x103d4718, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/irq.c:38
#8 0x1006edf4 in bamboo_pci_set_irq (pic=0x103d4718, irq_num=0x2, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/ppc4xx_devs.c:837
#9 0x100170d4 in pci_set_irq (opaque=0x103d4718, irq_num=0x2, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/pci.c:560
#10 0x1007cc40 in qemu_set_irq (irq=0x103d4718, level=0x1)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/irq.c:38
#11 0x1003194c in virtio_update_irq (vdev=0x103d4718)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/virtio.c:205
#12 0x10032ef4 in virtio_blk_rw_complete (opaque=0x10438008, ret=0x0)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/hw/virtio-blk.c:119
#13 0x100ad680 in qcow_aio_read_cb (opaque=0x10432e58, ret=0x0)
at block-qcow2.c:1205
#14 0x1001c450 in posix_aio_read (opaque=0x103d4718) at block-raw-posix.c:550
#15 0x1000e5d8 in main_loop_wait (timeout=0xbfe5a978)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/vl.c:8352
#16 0x24000082 in ?? ()
#17 0x10117a00 in kvm_main_loop ()
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/qemu-kvm.c:614
#18 0x10011aa0 in main (argc=0x101b0000, argv=0x10380958)
at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/vl.c:8416
(gdb) p current_env
$1 = (struct CPUPPCState *) 0x0
(gdb)
It looks like qemu is actually switching threads when this happens...
I'm not sure what the current state is of qemu/KVM threads... I think we
have 1 thread per vcpu, plus 1 IO thread? If that's right, maybe
current_env isn't being initialized in the IO thread; I only see that
happening inside ap_main_loop(), which is the vcpu thread.
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-24 19:10 ` Hollis Blanchard
@ 2008-10-27 9:48 ` Jes Sorensen
2008-10-27 16:02 ` Hollis Blanchard
2008-10-27 16:06 ` [patch] " Jes Sorensen
1 sibling, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2008-10-27 9:48 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: Glauber Costa, kvm, kvm-ia64
Hollis Blanchard wrote:
> It looks like qemu is actually switching threads when this happens...
> I'm not sure what the current state is of qemu/KVM threads... I think we
> have 1 thread per vcpu, plus 1 IO thread? If that's right, maybe
> current_env isn't being initialized in the IO thread; I only see that
> happening inside ap_main_loop(), which is the vcpu thread.
>
Hmmm, this is bizarre. If it was the IO thread dieing because of this
I would expect the same to happen on ia64. Could you try and add a test
in the code to find out which thread you are when you die, and maybe
check for current_env being valid?
Thanks,
Jes
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-27 9:48 ` Jes Sorensen
@ 2008-10-27 16:02 ` Hollis Blanchard
2008-10-28 16:25 ` [patch] v4 - " Jes Sorensen
0 siblings, 1 reply; 15+ messages in thread
From: Hollis Blanchard @ 2008-10-27 16:02 UTC (permalink / raw)
To: Jes Sorensen; +Cc: Glauber Costa, kvm, kvm-ia64
On Mon, 2008-10-27 at 10:48 +0100, Jes Sorensen wrote:
> Hollis Blanchard wrote:
> > It looks like qemu is actually switching threads when this happens...
> > I'm not sure what the current state is of qemu/KVM threads... I think we
> > have 1 thread per vcpu, plus 1 IO thread? If that's right, maybe
> > current_env isn't being initialized in the IO thread; I only see that
> > happening inside ap_main_loop(), which is the vcpu thread.
> >
>
> Hmmm, this is bizarre. If it was the IO thread dieing because of this
> I would expect the same to happen on ia64. Could you try and add a test
> in the code to find out which thread you are when you die, and maybe
> check for current_env being valid?
I tested in gdb, and I can confirm that a) current_env was initialized
in one thread, and then used in another, and b) current_env was NULL
(invalid) when it was used.
Are you using virtio on ia64?
--
Hollis Blanchard
IBM Linux Technology Center
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] fold struct vcpu_info into CPUState
2008-10-24 19:10 ` Hollis Blanchard
2008-10-27 9:48 ` Jes Sorensen
@ 2008-10-27 16:06 ` Jes Sorensen
1 sibling, 0 replies; 15+ messages in thread
From: Jes Sorensen @ 2008-10-27 16:06 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: Glauber Costa, kvm, kvm-ia64
[-- Attachment #1: Type: text/plain, Size: 478 bytes --]
Hollis Blanchard wrote:
> This is 100% repeatable, and it doesn't happen without your patch
> applied.
>
> 0x10116f1c in kvm_update_interrupt_request (env=0x103d4718)
> at /home/hollisb/source/kvm-userspace-ppc.hg/qemu/qemu-kvm.c:142
> 142 if (current_env->vcpu_info.created &&
> (gdb) bt
Hollis,
Ok, I looked at the logic in this function again and I think I got some
of it wrong when I did the conversion.
Could you try out this one instead.
Thanks,
Jes
[-- Attachment #2: 0010-qemu-kvm-vcpu_info-v3.1.patch --]
[-- Type: text/plain, Size: 15240 bytes --]
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@sgi.com>
---
libkvm/kvm-common.h | 4 -
libkvm/libkvm.c | 14 ++--
libkvm/libkvm.h | 6 +-
qemu/qemu-kvm-vcpu.h | 34 +++++++++++
qemu/qemu-kvm.c | 146 +++++++++++++++++++++++++------------------------
qemu/target-i386/cpu.h | 4 +
qemu/target-ia64/cpu.h | 5 +
qemu/target-ppc/cpu.h | 5 +
8 files changed, 136 insertions(+), 82 deletions(-)
Index: kvm-userspace.git/libkvm/kvm-common.h
===================================================================
--- kvm-userspace.git.orig/libkvm/kvm-common.h
+++ kvm-userspace.git/libkvm/kvm-common.h
@@ -84,11 +84,11 @@
void kvm_show_code(kvm_context_t kvm, int vcpu);
int handle_halt(kvm_context_t kvm, int vcpu);
-int handle_shutdown(kvm_context_t kvm, int vcpu);
+int handle_shutdown(kvm_context_t kvm, void *env);
void post_kvm_run(kvm_context_t kvm, int vcpu);
int pre_kvm_run(kvm_context_t kvm, int vcpu);
int handle_io_window(kvm_context_t kvm);
-int handle_debug(kvm_context_t kvm, int vcpu);
+int handle_debug(kvm_context_t kvm, void *env);
int try_push_interrupts(kvm_context_t kvm);
#endif
Index: kvm-userspace.git/libkvm/libkvm.c
===================================================================
--- kvm-userspace.git.orig/libkvm/libkvm.c
+++ kvm-userspace.git/libkvm/libkvm.c
@@ -738,9 +738,9 @@
return 0;
}
-int handle_debug(kvm_context_t kvm, int vcpu)
+int handle_debug(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->debug(kvm->opaque, vcpu);
+ return kvm->callbacks->debug(kvm->opaque, env);
}
int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
@@ -822,9 +822,9 @@
return kvm->callbacks->halt(kvm->opaque, vcpu);
}
-int handle_shutdown(kvm_context_t kvm, int vcpu)
+int handle_shutdown(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->shutdown(kvm->opaque, vcpu);
+ return kvm->callbacks->shutdown(kvm->opaque, env);
}
int try_push_interrupts(kvm_context_t kvm)
@@ -872,7 +872,7 @@
#endif
}
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)
{
int r;
int fd = kvm->vcpu_fd[vcpu];
@@ -948,7 +948,7 @@
r = handle_io(kvm, run, vcpu);
break;
case KVM_EXIT_DEBUG:
- r = handle_debug(kvm, vcpu);
+ r = handle_debug(kvm, env);
break;
case KVM_EXIT_MMIO:
r = handle_mmio(kvm, run);
@@ -962,7 +962,7 @@
#endif
break;
case KVM_EXIT_SHUTDOWN:
- r = handle_shutdown(kvm, vcpu);
+ r = handle_shutdown(kvm, env);
break;
#if defined(__s390__)
case KVM_EXIT_S390_SIEIC:
Index: kvm-userspace.git/libkvm/libkvm.h
===================================================================
--- kvm-userspace.git.orig/libkvm/libkvm.h
+++ kvm-userspace.git/libkvm/libkvm.h
@@ -55,7 +55,7 @@
/// generic memory writes to unmapped memory (For MMIO devices)
int (*mmio_write)(void *opaque, uint64_t addr, uint8_t *data,
int len);
- int (*debug)(void *opaque, int vcpu);
+ int (*debug)(void *opaque, void *env);
/*!
* \brief Called when the VCPU issues an 'hlt' instruction.
*
@@ -63,7 +63,7 @@
* on the host CPU.
*/
int (*halt)(void *opaque, int vcpu);
- int (*shutdown)(void *opaque, int vcpu);
+ int (*shutdown)(void *opaque, void *env);
int (*io_window)(void *opaque);
int (*try_push_interrupts)(void *opaque);
int (*try_push_nmi)(void *opaque);
@@ -181,7 +181,7 @@
* return except for when an error has occured, or when you have sent it
* an EINTR signal.
*/
-int kvm_run(kvm_context_t kvm, int vcpu);
+int kvm_run(kvm_context_t kvm, int vcpu, void *env);
/*!
* \brief Get interrupt flag from on last exit to userspace
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 && 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);
}
@@ -227,7 +225,7 @@
{
int r;
- r = kvm_run(kvm_context, env->cpu_index);
+ r = kvm_run(kvm_context, env->cpu_index, env);
if (r < 0) {
printf("kvm_run returned %d\n", r);
exit(1);
@@ -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,7 +353,7 @@
static void update_regs_for_sipi(CPUState *env)
{
kvm_arch_update_regs_for_sipi(env);
- vcpu_info[env->cpu_index].sipi_needed = 0;
+ env->vcpu_info.sipi_needed = 0;
}
static void update_regs_for_init(CPUState *env)
@@ -361,11 +366,11 @@
#ifdef TARGET_I386
/* restore SIPI vector */
- if(vcpu_info[env->cpu_index].sipi_needed)
+ if(env->vcpu_info.sipi_needed)
env->segs[R_CS] = cs;
-
- vcpu_info[env->cpu_index].init = 0;
#endif
+
+ env->vcpu_info.init = 0;
kvm_arch_load_regs(env);
}
@@ -387,21 +392,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);
@@ -442,9 +449,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);
@@ -452,7 +458,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 */
@@ -466,9 +472,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);
}
@@ -624,10 +630,10 @@
return 0;
}
-static int kvm_debug(void *opaque, int vcpu)
+static int kvm_debug(void *opaque, struct CPUState *env)
{
kvm_debug_stop_requested = 1;
- vcpu_info[vcpu].stopped = 1;
+ env->vcpu_info.stopped = 1;
return 1;
}
@@ -721,10 +727,10 @@
return kvm_arch_halt(opaque, vcpu);
}
-static int kvm_shutdown(void *opaque, int vcpu)
+static int kvm_shutdown(void *opaque, struct CPUState *env)
{
/* 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 */
^ permalink raw reply [flat|nested] 15+ messages in thread
* [patch] v4 - fold struct vcpu_info into CPUState
2008-10-27 16:02 ` Hollis Blanchard
@ 2008-10-28 16:25 ` Jes Sorensen
2008-10-29 13:01 ` Anthony Liguori
0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2008-10-28 16:25 UTC (permalink / raw)
To: Hollis Blanchard; +Cc: Glauber Costa, kvm, kvm-ia64
[-- Attachment #1: Type: text/plain, Size: 522 bytes --]
Hi,
Here's an updated version of the patch. It should fix the problems
Hollis ran into, and also compile on x86_64 again :-)
I managed to get rid of all the runtime use of qemu_kvm_cpu_env(),
except for the hotplug code. But I think it's reasonable to do the
walk of the linked list in that case. However, the more I have looked
at this, the more obvious to me it becomes that it is right<tm> to
expose struct CPUState to libkvm, and avoid passing around int vcpu.
Comments and test reports very welcome!
Cheers,
Jes
[-- Attachment #2: 0010-qemu-kvm-vcpu_info-v4.patch --]
[-- Type: text/plain, Size: 20968 bytes --]
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@sgi.com>
---
libkvm/kvm-common.h | 8 +-
libkvm/libkvm.c | 28 ++++----
libkvm/libkvm.h | 10 +--
qemu/hw/acpi.c | 18 +++++
qemu/qemu-kvm-ia64.c | 4 -
qemu/qemu-kvm-powerpc.c | 5 -
qemu/qemu-kvm-vcpu.h | 34 ++++++++++
qemu/qemu-kvm-x86.c | 11 +--
qemu/qemu-kvm.c | 151 ++++++++++++++++++++++--------------------------
qemu/qemu-kvm.h | 6 -
qemu/target-i386/cpu.h | 4 +
qemu/target-ia64/cpu.h | 5 +
qemu/target-ppc/cpu.h | 5 +
13 files changed, 172 insertions(+), 117 deletions(-)
Index: kvm-userspace.git/libkvm/kvm-common.h
===================================================================
--- kvm-userspace.git.orig/libkvm/kvm-common.h
+++ kvm-userspace.git/libkvm/kvm-common.h
@@ -84,11 +84,11 @@
void kvm_show_code(kvm_context_t kvm, int vcpu);
int handle_halt(kvm_context_t kvm, int vcpu);
-int handle_shutdown(kvm_context_t kvm, int vcpu);
-void post_kvm_run(kvm_context_t kvm, int vcpu);
-int pre_kvm_run(kvm_context_t kvm, int vcpu);
+int handle_shutdown(kvm_context_t kvm, void *env);
+void post_kvm_run(kvm_context_t kvm, void *env);
+int pre_kvm_run(kvm_context_t kvm, void *env);
int handle_io_window(kvm_context_t kvm);
-int handle_debug(kvm_context_t kvm, int vcpu);
+int handle_debug(kvm_context_t kvm, void *env);
int try_push_interrupts(kvm_context_t kvm);
#endif
Index: kvm-userspace.git/libkvm/libkvm.c
===================================================================
--- kvm-userspace.git.orig/libkvm/libkvm.c
+++ kvm-userspace.git/libkvm/libkvm.c
@@ -738,9 +738,9 @@
return 0;
}
-int handle_debug(kvm_context_t kvm, int vcpu)
+int handle_debug(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->debug(kvm->opaque, vcpu);
+ return kvm->callbacks->debug(kvm->opaque, env);
}
int kvm_get_regs(kvm_context_t kvm, int vcpu, struct kvm_regs *regs)
@@ -822,9 +822,9 @@
return kvm->callbacks->halt(kvm->opaque, vcpu);
}
-int handle_shutdown(kvm_context_t kvm, int vcpu)
+int handle_shutdown(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->shutdown(kvm->opaque, vcpu);
+ return kvm->callbacks->shutdown(kvm->opaque, env);
}
int try_push_interrupts(kvm_context_t kvm)
@@ -837,14 +837,14 @@
return kvm->callbacks->try_push_nmi(kvm->opaque);
}
-void post_kvm_run(kvm_context_t kvm, int vcpu)
+void post_kvm_run(kvm_context_t kvm, void *env)
{
- kvm->callbacks->post_kvm_run(kvm->opaque, vcpu);
+ kvm->callbacks->post_kvm_run(kvm->opaque, env);
}
-int pre_kvm_run(kvm_context_t kvm, int vcpu)
+int pre_kvm_run(kvm_context_t kvm, void *env)
{
- return kvm->callbacks->pre_kvm_run(kvm->opaque, vcpu);
+ return kvm->callbacks->pre_kvm_run(kvm->opaque, env);
}
int kvm_get_interrupt_flag(kvm_context_t kvm, int vcpu)
@@ -872,7 +872,7 @@
#endif
}
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)
{
int r;
int fd = kvm->vcpu_fd[vcpu];
@@ -886,19 +886,19 @@
if (!kvm->irqchip_in_kernel)
run->request_interrupt_window = try_push_interrupts(kvm);
#endif
- r = pre_kvm_run(kvm, vcpu);
+ r = pre_kvm_run(kvm, env);
if (r)
return r;
r = ioctl(fd, KVM_RUN, 0);
if (r == -1 && errno != EINTR && errno != EAGAIN) {
r = -errno;
- post_kvm_run(kvm, vcpu);
+ post_kvm_run(kvm, env);
fprintf(stderr, "kvm_run: %s\n", strerror(-r));
return r;
}
- post_kvm_run(kvm, vcpu);
+ post_kvm_run(kvm, env);
#if defined(KVM_CAP_COALESCED_MMIO)
if (kvm->coalesced_mmio) {
@@ -948,7 +948,7 @@
r = handle_io(kvm, run, vcpu);
break;
case KVM_EXIT_DEBUG:
- r = handle_debug(kvm, vcpu);
+ r = handle_debug(kvm, env);
break;
case KVM_EXIT_MMIO:
r = handle_mmio(kvm, run);
@@ -962,7 +962,7 @@
#endif
break;
case KVM_EXIT_SHUTDOWN:
- r = handle_shutdown(kvm, vcpu);
+ r = handle_shutdown(kvm, env);
break;
#if defined(__s390__)
case KVM_EXIT_S390_SIEIC:
Index: kvm-userspace.git/libkvm/libkvm.h
===================================================================
--- kvm-userspace.git.orig/libkvm/libkvm.h
+++ kvm-userspace.git/libkvm/libkvm.h
@@ -55,7 +55,7 @@
/// generic memory writes to unmapped memory (For MMIO devices)
int (*mmio_write)(void *opaque, uint64_t addr, uint8_t *data,
int len);
- int (*debug)(void *opaque, int vcpu);
+ int (*debug)(void *opaque, void *env);
/*!
* \brief Called when the VCPU issues an 'hlt' instruction.
*
@@ -63,12 +63,12 @@
* on the host CPU.
*/
int (*halt)(void *opaque, int vcpu);
- int (*shutdown)(void *opaque, int vcpu);
+ int (*shutdown)(void *opaque, void *env);
int (*io_window)(void *opaque);
int (*try_push_interrupts)(void *opaque);
int (*try_push_nmi)(void *opaque);
- void (*post_kvm_run)(void *opaque, int vcpu);
- int (*pre_kvm_run)(void *opaque, int vcpu);
+ void (*post_kvm_run)(void *opaque, void *env);
+ int (*pre_kvm_run)(void *opaque, void *env);
int (*tpr_access)(void *opaque, int vcpu, uint64_t rip, int is_write);
#if defined(__powerpc__)
int (*powerpc_dcr_read)(int vcpu, uint32_t dcrn, uint32_t *data);
@@ -181,7 +181,7 @@
* return except for when an error has occured, or when you have sent it
* an EINTR signal.
*/
-int kvm_run(kvm_context_t kvm, int vcpu);
+int kvm_run(kvm_context_t kvm, int vcpu, void *env);
/*!
* \brief Get interrupt flag from on last exit to userspace
Index: kvm-userspace.git/qemu/hw/acpi.c
===================================================================
--- kvm-userspace.git.orig/qemu/hw/acpi.c
+++ kvm-userspace.git/qemu/hw/acpi.c
@@ -722,6 +722,24 @@
}
#if defined(TARGET_I386) || defined(TARGET_X86_64)
+#ifdef USE_KVM
+static CPUState *qemu_kvm_cpu_env(int index)
+{
+ CPUState *penv;
+
+ penv = first_cpu;
+
+ while (penv) {
+ if (penv->cpu_index == index)
+ return penv;
+ penv = (CPUState *)penv->next_cpu;
+ }
+
+ return NULL;
+}
+#endif
+
+
void qemu_system_cpu_hot_add(int cpu, int state)
{
CPUState *env;
Index: kvm-userspace.git/qemu/qemu-kvm-ia64.c
===================================================================
--- kvm-userspace.git.orig/qemu/qemu-kvm-ia64.c
+++ kvm-userspace.git/qemu/qemu-kvm-ia64.c
@@ -39,11 +39,11 @@
return 1;
}
-void kvm_arch_pre_kvm_run(void *opaque, int vcpu)
+void kvm_arch_pre_kvm_run(void *opaque, CPUState *env)
{
}
-void kvm_arch_post_kvm_run(void *opaque, int vcpu)
+void kvm_arch_post_kvm_run(void *opaque, CPUState *env)
{
}
Index: kvm-userspace.git/qemu/qemu-kvm-powerpc.c
===================================================================
--- kvm-userspace.git.orig/qemu/qemu-kvm-powerpc.c
+++ kvm-userspace.git/qemu/qemu-kvm-powerpc.c
@@ -142,14 +142,13 @@
return 1;
}
-void kvm_arch_pre_kvm_run(void *opaque, int vcpu)
+void kvm_arch_pre_kvm_run(void *opaque, CPUState *env)
{
return;
}
-void kvm_arch_post_kvm_run(void *opaque, int vcpu)
+void kvm_arch_post_kvm_run(void *opaque, CPUState *env)
{
- CPUState *env = qemu_kvm_cpu_env(vcpu);
cpu_single_env = env;
}
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-x86.c
===================================================================
--- kvm-userspace.git.orig/qemu/qemu-kvm-x86.c
+++ kvm-userspace.git/qemu/qemu-kvm-x86.c
@@ -618,17 +618,16 @@
return 1;
}
-void kvm_arch_pre_kvm_run(void *opaque, int vcpu)
+void kvm_arch_pre_kvm_run(void *opaque, CPUState *env)
{
- CPUState *env = cpu_single_env;
-
if (!kvm_irqchip_in_kernel(kvm_context))
- kvm_set_cr8(kvm_context, vcpu, cpu_get_apic_tpr(env));
+ kvm_set_cr8(kvm_context, env->cpu_index, cpu_get_apic_tpr(env));
}
-void kvm_arch_post_kvm_run(void *opaque, int vcpu)
+void kvm_arch_post_kvm_run(void *opaque, CPUState *env)
{
- CPUState *env = qemu_kvm_cpu_env(vcpu);
+ int vcpu = env->cpu_index;
+
cpu_single_env = env;
env->eflags = kvm_get_interrupt_flag(kvm_context, vcpu)
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;
@@ -91,21 +72,16 @@
cpu_single_env = env;
}
-CPUState *qemu_kvm_cpu_env(int index)
-{
- return vcpu_info[index].env;
-}
-
static void sig_ipi_handler(int n)
{
}
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 +103,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 +116,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 && 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);
}
@@ -178,18 +158,19 @@
return kvm_arch_try_push_nmi(opaque);
}
-static void post_kvm_run(void *opaque, int vcpu)
+static void post_kvm_run(void *opaque, void *data)
{
+ CPUState *env = (CPUState *)data;
pthread_mutex_lock(&qemu_mutex);
- kvm_arch_post_kvm_run(opaque, vcpu);
+ kvm_arch_post_kvm_run(opaque, env);
}
-static int pre_kvm_run(void *opaque, int vcpu)
+static int pre_kvm_run(void *opaque, void *data)
{
- CPUState *env = qemu_kvm_cpu_env(vcpu);
+ CPUState *env = (CPUState *)data;
- kvm_arch_pre_kvm_run(opaque, vcpu);
+ kvm_arch_pre_kvm_run(opaque, env);
if (env->interrupt_request & CPU_INTERRUPT_EXIT)
return 1;
@@ -227,7 +208,7 @@
{
int r;
- r = kvm_run(kvm_context, env->cpu_index);
+ r = kvm_run(kvm_context, env->cpu_index, env);
if (r < 0) {
printf("kvm_run returned %d\n", r);
exit(1);
@@ -240,7 +221,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 +230,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 +247,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 +273,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,7 +336,7 @@
static void update_regs_for_sipi(CPUState *env)
{
kvm_arch_update_regs_for_sipi(env);
- vcpu_info[env->cpu_index].sipi_needed = 0;
+ env->vcpu_info.sipi_needed = 0;
}
static void update_regs_for_init(CPUState *env)
@@ -361,11 +349,11 @@
#ifdef TARGET_I386
/* restore SIPI vector */
- if(vcpu_info[env->cpu_index].sipi_needed)
+ if(env->vcpu_info.sipi_needed)
env->segs[R_CS] = cs;
-
- vcpu_info[env->cpu_index].init = 0;
#endif
+
+ env->vcpu_info.init = 0;
kvm_arch_load_regs(env);
}
@@ -387,21 +375,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);
@@ -442,9 +432,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);
@@ -452,7 +441,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 */
@@ -466,9 +455,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);
}
@@ -624,10 +613,12 @@
return 0;
}
-static int kvm_debug(void *opaque, int vcpu)
+static int kvm_debug(void *opaque, void *data)
{
+ struct CPUState *env = (struct CPUState *)data;
+
kvm_debug_stop_requested = 1;
- vcpu_info[vcpu].stopped = 1;
+ env->vcpu_info.stopped = 1;
return 1;
}
@@ -721,10 +712,12 @@
return kvm_arch_halt(opaque, vcpu);
}
-static int kvm_shutdown(void *opaque, int vcpu)
+static int kvm_shutdown(void *opaque, void *data)
{
+ struct CPUState *env = (struct CPUState *)data;
+
/* 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/qemu-kvm.h
===================================================================
--- kvm-userspace.git.orig/qemu/qemu-kvm.h
+++ kvm-userspace.git/qemu/qemu-kvm.h
@@ -63,16 +63,14 @@
void kvm_arch_load_regs(CPUState *env);
int kvm_arch_qemu_init_env(CPUState *cenv);
int kvm_arch_halt(void *opaque, int vcpu);
-void kvm_arch_pre_kvm_run(void *opaque, int vcpu);
-void kvm_arch_post_kvm_run(void *opaque, int vcpu);
+void kvm_arch_pre_kvm_run(void *opaque, CPUState *env);
+void kvm_arch_post_kvm_run(void *opaque, CPUState *env);
int kvm_arch_has_work(CPUState *env);
int kvm_arch_try_push_interrupts(void *opaque);
int kvm_arch_try_push_nmi(void *opaque);
void kvm_arch_update_regs_for_sipi(CPUState *env);
void kvm_arch_cpu_reset(CPUState *env);
-CPUState *qemu_kvm_cpu_env(int index);
-
void qemu_kvm_aio_wait_start(void);
void qemu_kvm_aio_wait(void);
void qemu_kvm_aio_wait_end(void);
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 */
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] v4 - fold struct vcpu_info into CPUState
2008-10-28 16:25 ` [patch] v4 - " Jes Sorensen
@ 2008-10-29 13:01 ` Anthony Liguori
2008-10-29 13:04 ` Jes Sorensen
0 siblings, 1 reply; 15+ messages in thread
From: Anthony Liguori @ 2008-10-29 13:01 UTC (permalink / raw)
To: Jes Sorensen; +Cc: Hollis Blanchard, Glauber Costa, kvm, kvm-ia64
Jes Sorensen wrote:
> Hi,
>
> Here's an updated version of the patch. It should fix the problems
> Hollis ran into, and also compile on x86_64 again :-)
>
> I managed to get rid of all the runtime use of qemu_kvm_cpu_env(),
> except for the hotplug code. But I think it's reasonable to do the
> walk of the linked list in that case. However, the more I have looked
> at this, the more obvious to me it becomes that it is right<tm> to
> expose struct CPUState to libkvm, and avoid passing around int vcpu.
>
> Comments and test reports very welcome!
FWIW, vcpu_info seems to have nothing to do with KVM. It's entirely
build around the IO thread. The IO thread really isn't KVM specific.
I would just stick these fields in CPU_COMMON unconditionally if you're
going to move them at all.
Regards,
Anthony Liguori
> Cheers,
> Jes
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] v4 - fold struct vcpu_info into CPUState
2008-10-29 13:01 ` Anthony Liguori
@ 2008-10-29 13:04 ` Jes Sorensen
2008-10-29 13:09 ` Anthony Liguori
0 siblings, 1 reply; 15+ messages in thread
From: Jes Sorensen @ 2008-10-29 13:04 UTC (permalink / raw)
To: Anthony Liguori; +Cc: Hollis Blanchard, Glauber Costa, kvm, kvm-ia64
Anthony Liguori wrote:
> FWIW, vcpu_info seems to have nothing to do with KVM. It's entirely
> build around the IO thread. The IO thread really isn't KVM specific.
>
> I would just stick these fields in CPU_COMMON unconditionally if you're
> going to move them at all.
Hi Anthony,
I am quite happy to do that, my main concern was to get rid of the
static declaration of the vcpu_info array.
Do you prefer we do it all in one go, or rather have this patch, then
another patch afterwards that moves them into CPU_COMMON? I'm good with
both, I just don't want it to get too complicated so it won't get
accepted because of that.
Cheers,
Jes
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch] v4 - fold struct vcpu_info into CPUState
2008-10-29 13:04 ` Jes Sorensen
@ 2008-10-29 13:09 ` Anthony Liguori
0 siblings, 0 replies; 15+ messages in thread
From: Anthony Liguori @ 2008-10-29 13:09 UTC (permalink / raw)
To: Jes Sorensen; +Cc: Hollis Blanchard, Glauber Costa, kvm, kvm-ia64
Jes Sorensen wrote:
> Anthony Liguori wrote:
>> FWIW, vcpu_info seems to have nothing to do with KVM. It's entirely
>> build around the IO thread. The IO thread really isn't KVM specific.
>>
>> I would just stick these fields in CPU_COMMON unconditionally if
>> you're going to move them at all.
>
> Hi Anthony,
>
> I am quite happy to do that, my main concern was to get rid of the
> static declaration of the vcpu_info array.
>
> Do you prefer we do it all in one go, or rather have this patch, then
> another patch afterwards that moves them into CPU_COMMON? I'm good with
> both, I just don't want it to get too complicated so it won't get
> accepted because of that.
I'm indifferent, it's Avi's call.
Regards,
Anthony Liguori
> Cheers,
> Jes
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2008-10-29 13:09 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-09-29 15:24 [patch] fold struct vcpu_info into CPUState Jes Sorensen
2008-10-05 10:02 ` Avi Kivity
2008-10-05 20:48 ` Glauber Costa
2008-10-13 22:24 ` Glauber Costa
2008-10-17 15:28 ` Jes Sorensen
2008-10-17 21:27 ` Glauber Costa
2008-10-24 15:57 ` Jes Sorensen
2008-10-24 19:10 ` Hollis Blanchard
2008-10-27 9:48 ` Jes Sorensen
2008-10-27 16:02 ` Hollis Blanchard
2008-10-28 16:25 ` [patch] v4 - " Jes Sorensen
2008-10-29 13:01 ` Anthony Liguori
2008-10-29 13:04 ` Jes Sorensen
2008-10-29 13:09 ` Anthony Liguori
2008-10-27 16:06 ` [patch] " Jes Sorensen
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).