Skip to contentSkip to conversation

remove vcpu_info array v5

PATCH In review Jes Sorensen 4 participants 26 messages Oct 30, 2008 – Nov 18, 2008 KVM

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 remove vcpu_info array v5

Hi,

So here we go, trying to catch up on the PCI passthrough patch revision number, here's v5 of the struct vcpu_info patch.

In the end I decided to merge the contents of struct vcpu_info directly into CPU_COMMON as it was silly to create new files just to remove them in the next patch again.

This boots for me on ia64 and builds on x86_64, obviously it is 100% perfect <tm>!

Comments, bug reports, or upstream merge, welcome :-)

Cheers,
Jes

Merge vcpu_info into CPUState.

Move contents of struct vcpu_info directly into CPU_COMMON. Rename struct qemu_kvm_work_item to qemu_work_item as it really isn't KVM specific.

This eliminates the ugly static sized array of struct vcpu_info.

---
 libkvm/kvm-common.h     |    8 +-
 libkvm/libkvm.c         |   28 +++----
 libkvm/libkvm.h         |   10 +-
 qemu/cpu-defs.h         |   15 +++-
 qemu/hw/acpi.c          |   18 ++++
 qemu/qemu-common.h      |    8 ++
 qemu/qemu-kvm-ia64.c    |    4 -
 qemu/qemu-kvm-powerpc.c |    5 -
 qemu/qemu-kvm-x86.c     |   11 +--
 qemu/qemu-kvm.c         |  175 ++++++++++++++++++++++--------------------------
 qemu/qemu-kvm.h         |    6 -
 qemu/target-ia64/cpu.h  |    1 
 12 files changed, 156 insertions(+), 133 deletions(-)
libkvm/kvm-common.h +4 -4
Index: 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
libkvm/libkvm.c +14 -14
Index: 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:
libkvm/libkvm.h +5 -5
Index: 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
qemu/cpu-defs.h +14 -1
Index: kvm-userspace.git/qemu/cpu-defs.h
===================================================================
@@ -27,6 +27,7 @@
 #include "config.h"
 #include <setjmp.h>
 #include <inttypes.h>
+#include <pthread.h>
 #include "osdep.h"
 
 #ifndef TARGET_LONG_BITS
@@ -142,6 +143,9 @@
 } icount_decr_u16;
 #endif
 
+/* forward decleration */
+struct qemu_work_item;
+
 #define CPU_TEMP_BUF_NLONGS 128
 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
@@ -200,6 +204,15 @@
     /* user data */                                                     \
     void *opaque;                                                       \
                                                                         \
-    const char *cpu_model_str;
+    const char *cpu_model_str;                                          \
+                                                                        \
+    int sipi_needed;                                                    \
+    int init;                                                           \
+    pthread_t thread;                                                   \
+    int signalled;                                                      \
+    int stop;                                                           \
+    int stopped;                                                        \
+    int created;                                                        \
+    struct qemu_work_item *queued_work_first, *queued_work_last;
 
 #endif
qemu/hw/acpi.c +18 -0
Index: 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;
qemu/qemu-common.h +8 -0
Index: kvm-userspace.git/qemu/qemu-common.h
===================================================================
@@ -143,4 +143,12 @@
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
+/* work queue */
+struct qemu_work_item {
+    struct qemu_kvm_work_item *next;
+    void (*func)(void *data);
+    void *data;
+    int done;
+};
+
 #endif
qemu/qemu-kvm-ia64.c +2 -2
Index: 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)
 {
 }
 
qemu/qemu-kvm-powerpc.c +2 -3
Index: 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;
 }
 
qemu/qemu-kvm-x86.c +5 -6
Index: 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)
qemu/qemu-kvm.c +81 -94

387 lines not on this page · raw message

qemu/qemu-kvm.h +2 -4
Index: 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);
qemu/target-ia64/cpu.h +1 -0
Index: kvm-userspace.git/qemu/target-ia64/cpu.h
===================================================================
@@ -40,6 +40,7 @@
 #include "cpu-defs.h"
 
 #include "softfloat.h"
+
 typedef struct CPUIA64State {
     CPU_COMMON;
     uint32_t hflags;
#1 lore raw
Quoted 11 lines · Jes Sorensen

So here we go, trying to catch up on the PCI passthrough patch revision number, here's v5 of the struct vcpu_info patch.

In the end I decided to merge the contents of struct vcpu_info directly into CPU_COMMON as it was silly to create new files just to remove them in the next patch again.

This boots for me on ia64 and builds on x86_64, obviously it is 100% perfect <tm>!

Quoted 8 lines

Comments, bug reports, or upstream merge, welcome :-) Merge vcpu_info into CPUState.

Move contents of struct vcpu_info directly into CPU_COMMON. Rename struct qemu_kvm_work_item to qemu_work_item as it really isn't KVM specific.

Well, it is actually kvm specific, since qemu doesn't have vccpu threads.

libkvm/libkvm.c line 875

Quoted 3 lines
libkvm/libkvm.c +1 -1
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)

That's a little ugly -- passing two arguments which describe the vcpu. How about passing env to kvm_create_vcpu() instead?

Quoted 9 lines

#define CPU_TEMP_BUF_NLONGS 128

 #define CPU_COMMON                                                      \
     struct TranslationBlock *current_tb; /* currently executing TB  */  \
qemu/cpu-defs.h +1 -1
@@ -200,6 +204,15 @@
     /* user data */                                                     \
     void *opaque;                                                       \
                                                                         \
-    const char *cpu_model_str;
+    const char *cpu_model_str;                                          \

qemu/cpu-defs.h line 217

Quoted 10 lines
qemu/cpu-defs.h +9 -0
+                                                                        \
+    int sipi_needed;                                                    \
+    int init;                                                           \
+    pthread_t thread;                                                   \
+    int signalled;                                                      \
+    int stop;                                                           \
+    int stopped;                                                        \
+    int created;                                                        \
+    struct qemu_work_item *queued_work_first, *queued_work_last;
 

struct kvm_stuff { ... } and put that in as a member, so it's easier to remember this is a kvm addition.

Quoted 9 lines
qemu/hw/acpi.c +6 -0
 #if defined(TARGET_I386) || defined(TARGET_X86_64)
+#ifdef USE_KVM
+static CPUState *qemu_kvm_cpu_env(int index)
+{
+    CPUState *penv;
+
+    penv = first_cpu;

qemu/hw/acpi.c line 740

Quoted 10 lines
qemu/hw/acpi.c +10 -0
+
+    while (penv) {
+        if (penv->cpu_index = index)
+            return penv;
+        penv = (CPUState *)penv->next_cpu;
+    }
+
+    return NULL;
+}
+#endif

This can't be the best way of determining the env pointer from a cpu number.

qemu/qemu-common.h line 149

Quoted 8 lines
qemu/qemu-common.h +3 -0
@@ -143,4 +143,12 @@
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 
+/* work queue */
+struct qemu_work_item {
+    struct qemu_kvm_work_item *next;
 

Missed rename here.

qemu/qemu-common.h line 153

Quoted 6 lines
qemu/qemu-common.h +5 -0
+    void (*func)(void *data);
+    void *data;
+    int done;
+};
+

Please keep this in kvm specific files.

qemu/qemu-kvm.c line 31

Quoted 6 lines
qemu/qemu-kvm.c +0 -1
@@ -28,7 +28,6 @@
 #include <sys/syscall.h>
 #include <sys/mman.h>
 
-#define bool _Bool
 

why?

Please separate into a patch that does the kvm_run int vcpu -> void *vcpu conversion, and then the vcpu_info -> env conversion.

Signature · 1 line
error compiling committee.c: too many arguments to function
#2 lore raw
Quoted 65 lines · Avi Kivity
Quoted 11 lines · Jes Sorensen

So here we go, trying to catch up on the PCI passthrough patch revision number, here's v5 of the struct vcpu_info patch.

In the end I decided to merge the contents of struct vcpu_info directly into CPU_COMMON as it was silly to create new files just to remove them in the next patch again.

This boots for me on ia64 and builds on x86_64, obviously it is 100% perfect <tm>!

Quoted 8 lines

Comments, bug reports, or upstream merge, welcome :-) Merge vcpu_info into CPUState.

Move contents of struct vcpu_info directly into CPU_COMMON. Rename struct qemu_kvm_work_item to qemu_work_item as it really isn't KVM specific.

Well, it is actually kvm specific, since qemu doesn't have vccpu threads.

libkvm/libkvm.c line 875

Quoted 3 lines
libkvm/libkvm.c +1 -1
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)

That's a little ugly -- passing two arguments which describe the vcpu. How about passing env to kvm_create_vcpu() instead?

Quoted 9 lines

#define CPU_TEMP_BUF_NLONGS 128

 #define CPU_COMMON                                                      \
    struct TranslationBlock *current_tb; /* currently executing TB  */  \
qemu/cpu-defs.h +1 -1
@@ -200,6 +204,15 @@
    /* user data */                                                     \
    void *opaque;                                                       \
                                                                        \
-    const char *cpu_model_str;
+    const char *cpu_model_str;                                          \

qemu/cpu-defs.h line 217

Quoted 10 lines
qemu/cpu-defs.h +9 -0
+                                                                        \
+    int sipi_needed;                                                    \
+    int init;                                                           \
+    pthread_t thread;                                                   \
+    int signalled;                                                      \
+    int stop;                                                           \
+    int stopped;                                                        \
+    int created;                                                        \
+    struct qemu_work_item *queued_work_first, *queued_work_last;
 

struct kvm_stuff { ... } and put that in as a member, so it's easier to remember this is a kvm addition.

Quoted 12 lines
qemu/hw/acpi.c +11 -0
  #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;
Quoted 8 lines

qemu/hw/acpi.c line 740

Quoted 6 lines
qemu/hw/acpi.c +5 -0
+    }
+
+    return NULL;
+}
+#endif

This can't be the best way of determining the env pointer from a cpu number.

By far it is not. But at least it does not depend on any kvm-specific data, and works
for both qemu and kvm. So it's better to be this way.

If we change this scheme to a better one, like a hash table, then it'll improve both qemu and kvm.

Quoted 35 lines

qemu/qemu-common.h line 148

Quoted 7 lines
qemu/qemu-common.h +2 -0
@@ -143,4 +143,12 @@
 void cpu_save(QEMUFile *f, void *opaque);
 int cpu_load(QEMUFile *f, void *opaque, int version_id);
 +/* work queue */
+struct qemu_work_item {
+    struct qemu_kvm_work_item *next;
 

Missed rename here.

qemu/qemu-common.h line 153

Quoted 6 lines
qemu/qemu-common.h +5 -0
+    void (*func)(void *data);
+    void *data;
+    int done;
+};
+

Please keep this in kvm specific files.

qemu/qemu-kvm.c line 31

Quoted 5 lines
qemu/qemu-kvm.c +0 -0
@@ -28,7 +28,6 @@
 #include <sys/syscall.h>
 #include <sys/mman.h>
 -#define bool _Bool
 

why?

Please separate into a patch that does the kvm_run int vcpu -> void *vcpu conversion, and then the vcpu_info -> env conversion.

--
error compiling committee.c: too many arguments to function

Signature · 5 lines
Glauber  Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."
#3 lore raw
Quoted 10 lines · Glauber Costa
Quoted 2 lines

This can't be the best way of determining the env pointer from a cpu number.

By far it is not. But at least it does not depend on any kvm-specific data, and works
for both qemu and kvm. So it's better to be this way.

If we change this scheme to a better one, like a hash table, then it'll improve both qemu and kvm.

There are simpler data structures. An example is an array. Since we have an upper limit on the number of cpus (->max_cpus) there are no issues with scaling (unlike with the algorithm above).

Signature · 1 line
error compiling committee.c: too many arguments to function
#4 lore raw
Quoted 10 lines · Avi Kivity
Quoted 9 lines · Glauber Costa
Quoted 4 lines

This can't be the best way of determining the env pointer from a cpu number.

By far it is not. But at least it does not depend on any kvm-specific data, and works
for both qemu and kvm. So it's better to be this way.

Quoted 8 lines
Quoted 4 lines

If we change this scheme to a better one, like a hash table, then it'll improve both qemu and kvm.

There are simpler data structures. An example is an array. Since we have an upper limit on the number of cpus (->max_cpus) there are no issues with scaling (unlike with the algorithm above).

Yes, but I believe the whole point of jes patches is to remove those limits.

Signature · 5 lines
Glauber  Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."
#5 lore raw
Quoted 7 lines · Glauber Costa
Quoted 4 lines

There are simpler data structures. An example is an array. Since we have an upper limit on the number of cpus (->max_cpus) there are no issues with scaling (unlike with the algorithm above).

Yes, but I believe the whole point of jes patches is to remove those limits.

So we could linear search huge lists? Or code hashes where arrays would do? No, sir.

An array of pointers statically sized at MAX_CPUS is fine. If you insist, you can realloc() it on demand.

Signature · 1 line
error compiling committee.c: too many arguments to function
#6 lore raw
Quoted 13 lines · Avi Kivity
Quoted 11 lines · Glauber Costa
Quoted 7 lines

There are simpler data structures. An example is an array. Since we have
an upper limit on the number of cpus (->max_cpus) there are no issues with
scaling (unlike with the algorithm above).

Yes, but I believe the whole point of jes patches is to remove those limits.

Quoted 5 lines

So we could linear search huge lists? Or code hashes where arrays would do?
No, sir.

An array of pointers statically sized at MAX_CPUS is fine. If you insist, you can realloc() it on demand.

Yes, I agree. having MAX_CPUS is fine, and if we need to, we can increase that. but again: then the direction of the flow is better be have qemu to use a env array,
and then we can use the same method for kvm.

Quoted 4 lines

--
error compiling committee.c: too many arguments to function

Signature · 5 lines
Glauber  Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."
#7 lore raw
Quoted 7 lines · Glauber Costa
Quoted 7 lines
Quoted 4 lines

Yes, but I believe the whole point of jes patches is to remove those limits.

So we could linear search huge lists? Or code hashes where arrays would do?
No, sir.

Quoted 9 lines
Quoted 3 lines

An array of pointers statically sized at MAX_CPUS is fine. If you insist, you can realloc() it on demand.

Yes, I agree. having MAX_CPUS is fine, and if we need to, we can increase that. but again: then the direction of the flow is better be have qemu to use a env array,
and then we can use the same method for kvm.

I only object to the linear search; not to the folding of vcpu_info into CPUState.

Signature · 1 line
error compiling committee.c: too many arguments to function
#20 lore raw
In reply to Avi Kivity
Quoted 11 lines · Avi Kivity
Quoted 6 lines · Glauber Costa

By far it is not. But at least it does not depend on any kvm-specific data, and works
for both qemu and kvm. So it's better to be this way.

If we change this scheme to a better one, like a hash table, then it'll improve both qemu and kvm.

There are simpler data structures. An example is an array. Since we have an upper limit on the number of cpus (->max_cpus) there are no issues with scaling (unlike with the algorithm above).

Well one of the goals with my patch was to get rid of that nasty limit, so that we can scale. Static sized arrays are bad.

Jes

#21 lore raw
In reply to Avi Kivity
Quoted 6 lines · Avi Kivity
Quoted 3 lines · Jes Sorensen

Move contents of struct vcpu_info directly into CPU_COMMON. Rename struct qemu_kvm_work_item to qemu_work_item as it really isn't KVM specific.

Well, it is actually kvm specific, since qemu doesn't have vccpu threads.

Hi Avi,

Anthony suggested I moved things directly in there, after my previous patch kept it as a struct.

Quoted 6 lines

libkvm/libkvm.c line 875

Quoted 3 lines
libkvm/libkvm.c +1 -1
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)

That's a little ugly -- passing two arguments which describe the vcpu. How about passing env to kvm_create_vcpu() instead?

I am all in favor of doing this, but in order to do so, we have to teach libkvm about CPUState - are you ok with that?

Quoted 3 lines

struct kvm_stuff { ... } and put that in as a member, so it's easier to remember this is a kvm addition.

If we can agree, I really don't care too much. There's already plenty of stuff in CPU_COMMON that isn't used by specific users, so I didn't think this was an issue.

Quoted 14 lines
Quoted 14 lines

#if defined(TARGET_I386) || defined(TARGET_X86_64)

qemu/hw/acpi.c +12 -0
+#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;
+    }
Quoted 8 lines

qemu/hw/acpi.c line 740

Quoted 5 lines
qemu/hw/acpi.c +4 -0
+
+    return NULL;
+}
+#endif

This can't be the best way of determining the env pointer from a cpu number.

It's not pretty, but this is only used in the ACPU hotplug code now, so it's less performance critical.

Quoted 7 lines

qemu/qemu-common.h line 148

Quoted 4 lines
qemu/qemu-common.h +3 -0
+/* work queue */
+struct qemu_work_item {
+    struct qemu_kvm_work_item *next;

Missed rename here.

Quoted 8 lines

qemu/qemu-common.h line 153

Quoted 6 lines
qemu/qemu-common.h +5 -0
+    void (*func)(void *data);
+    void *data;
+    int done;
+};
+

Please keep this in kvm specific files.

Why? There really isn't anything specific about a work queue list like this. Making it an available functionality for QEMU shouldn't hurt.

Quoted 4 lines
Quoted 2 lines

-#define bool _Bool

why?

It was unused and didn't add any value.

Quoted 2 lines

Please separate into a patch that does the kvm_run int vcpu -> void *vcpu conversion, and then the vcpu_info -> env conversion.

As mentioned above, if I am going to go that way, we need to teach libkvm about 'env'. I am all in favor, but I am not going to do that unless I can get an ack that it's acceptable to do so.

Cheers,
Jes

#8 lore raw
In reply to Avi Kivity
Quoted 9 lines · Avi Kivity
Quoted 3 lines

Yes, but I believe the whole point of jes patches is to remove those limits.

So we could linear search huge lists? Or code hashes where arrays would do? No, sir.

An array of pointers statically sized at MAX_CPUS is fine. If you insist, you can realloc() it on demand.

Sorry, but this is riciculous. Please try and take a look at where the search is performed. It's *solely* in the ACPI hot plug code.

realloc() is not an option, unless of course you are in favor of putting a big lock around all access to such an array.

My patch gets rid of the pointless MAX_CPUS sized array, which doesn't buy us anything. In fact, most of the changes in my patch makes the code simpler, because it removes a stack of silly cases where qemu uses env->cpu_index to get into the array, just to hide CPUState from libkvm, just to have the callback in QEMU go from int vcpu back to CPUState.

Lets just do it right and get rid of this silliness.

Jes

#9 lore raw
Quoted 4 lines · Jes Sorensen

Sorry, but this is riciculous. Please try and take a look at where the search is performed. It's *solely* in the ACPI hot plug code.

There are other places we want a cpu from a cpu_index. Like the apic code (admittedly that's only using the userspace apic, which is non-default, but still).

Quoted 3 lines

realloc() is not an option, unless of course you are in favor of putting a big lock around all access to such an array.

Right now qemu is single-threaded anyway. The only parallelism is when executing guest code.

Of course we'll want to change that.

Quoted 7 lines

My patch gets rid of the pointless MAX_CPUS sized array, which doesn't buy us anything. In fact, most of the changes in my patch makes the code simpler, because it removes a stack of silly cases where qemu uses env->cpu_index to get into the array, just to hide CPUState from libkvm, just to have the callback in QEMU go from int vcpu back to CPUState.

Lets just do it right and get rid of this silliness.

I agree that vcpu_info should die. But we should still have a fast way of getting a cpu from a cpu_index. I don't see a problem with a static array of pointers, make it 16K in size if you want. Our real scaling limits are much lower; they involve the big qemu lock and the single iothread which will both limit scaling far below any static vcpu array.

Signature · 1 line
error compiling committee.c: too many arguments to function
#22 lore raw
In reply to Jes Sorensen
Quoted 6 lines · Jes Sorensen
Quoted 5 lines · Avi Kivity
Quoted 3 lines · Jes Sorensen

Move contents of struct vcpu_info directly into CPU_COMMON. Rename struct qemu_kvm_work_item to qemu_work_item as it really isn't KVM specific.

Quoted 8 lines
Quoted 2 lines

Well, it is actually kvm specific, since qemu doesn't have vccpu threads.

Hi Avi,

Anthony suggested I moved things directly in there, after my previous patch kept it as a struct.

The movement is fine, just keep it named kvm so we know it is kvm specific.

Quoted 9 lines
Quoted 6 lines

libkvm/libkvm.c line 875

Quoted 3 lines
libkvm/libkvm.c +1 -1
-int kvm_run(kvm_context_t kvm, int vcpu)
+int kvm_run(kvm_context_t kvm, int vcpu, void *env)

That's a little ugly -- passing two arguments which describe the vcpu. How about passing env to kvm_create_vcpu() instead?

I am all in favor of doing this, but in order to do so, we have to teach libkvm about CPUState - are you ok with that?

No, libkvm is independent of qemu.

We can make kvm_create_vcpu(kvm_context_t kvm, int vcpu, void *env), and pass 'env' as the opaque to all the callbacks, instead of the vcpu number.

Quoted 9 lines
Quoted 4 lines

struct kvm_stuff { ... } and put that in as a member, so it's easier to remember this is a kvm addition.

If we can agree, I really don't care too much. There's already plenty of stuff in CPU_COMMON that isn't used by specific users, so I didn't think this was an issue.

It's more of a maintenance issue so that I can keep track of what is in qemu upstream and what is local. Merges are already painful enough.

Quoted 8 lines
Quoted 3 lines
Quoted 1 line

Please keep this in kvm specific files.

Why? There really isn't anything specific about a work queue list like this. Making it an available functionality for QEMU shouldn't hurt.

It's only relevant if you have per-vcpu threads, which qemu doesn't have.

Quoted 7 lines
Quoted 4 lines
Quoted 2 lines

-#define bool _Bool

why?

It was unused and didn't add any value.

So separate patch.

Quoted 6 lines
Quoted 2 lines

Please separate into a patch that does the kvm_run int vcpu -> void *vcpu conversion, and then the vcpu_info -> env conversion.

As mentioned above, if I am going to go that way, we need to teach libkvm about 'env'. I am all in favor, but I am not going to do that unless I can get an ack that it's acceptable to do so.

How's my suggestion above?

Signature · 1 line
error compiling committee.c: too many arguments to function
#10 lore raw
In reply to Avi Kivity
Quoted 7 lines · Avi Kivity
Quoted 7 lines

My patch gets rid of the pointless MAX_CPUS sized array, which doesn't buy us anything. In fact, most of the changes in my patch makes the code simpler, because it removes a stack of silly cases where qemu uses env->cpu_index to get into the array, just to hide CPUState from libkvm, just to have the callback in QEMU go from int vcpu back to CPUState.

Quoted 8 lines
Quoted 1 line

Lets just do it right and get rid of this silliness.

I agree that vcpu_info should die. But we should still have a fast way of getting a cpu from a cpu_index. I don't see a problem with a static array of pointers, make it 16K in size if you want. Our real scaling limits are much lower; they involve the big qemu lock and the single iothread which will both limit scaling far below any static vcpu array.

Just do a linear search of the CPUState list and be done with it. This smells of premature optimization greatly. I would be amazed if walking the CPUState list is ever on the fast path or will ever be. Really, if you need to go from cpu_index => CPUState, it suggests you're doing something wrong.

Regards,

Anthony Liguori

#11 lore raw
Quoted 7 lines · Anthony Liguori

Just do a linear search of the CPUState list and be done with it. This smells of premature optimization greatly. I would be amazed if walking the CPUState list is ever on the fast path or will ever be. Really, if you need to go from cpu_index => CPUState, it suggests you're doing something wrong.

apic_bus_deliver() in hw/apic.c (it uses a static array of local apics, but under you proposal it would need to be converted to a list as well).

happens once per interrupt. With external interrupts you might precompute it, but IPIs definitely need fast int->ptr conversion.

Signature · 1 line
error compiling committee.c: too many arguments to function
#12 lore raw
In reply to Avi Kivity
Quoted 8 lines · Avi Kivity
Quoted 3 lines · Jes Sorensen

Sorry, but this is riciculous. Please try and take a look at where the search is performed. It's *solely* in the ACPI hot plug code.

There are other places we want a cpu from a cpu_index. Like the apic code (admittedly that's only using the userspace apic, which is non-default, but still).

Hi Avi,

Well this was based on what I ran into building the code. I didn't hit any issues where the apic code tried to do this.

Quoted 6 lines
Quoted 6 lines

My patch gets rid of the pointless MAX_CPUS sized array, which doesn't buy us anything. In fact, most of the changes in my patch makes the code simpler, because it removes a stack of silly cases where qemu uses env->cpu_index to get into the array, just to hide CPUState from libkvm, just to have the callback in QEMU go from int vcpu back to CPUState.

Quoted 7 lines
Quoted 1 line

Lets just do it right and get rid of this silliness.

I agree that vcpu_info should die. But we should still have a fast way of getting a cpu from a cpu_index. I don't see a problem with a static array of pointers, make it 16K in size if you want. Our real scaling limits are much lower; they involve the big qemu lock and the single iothread which will both limit scaling far below any static vcpu array.

If we have reasons where we actually rely on the cpu number, and thats not counting end-user pretty-number-print concerns, then I found that we practically never use the cpu number. If we really use it a lot, I agree we need a fast way, I just didn't hit it in my builds. What did I miss?

Jes

#13 lore raw
Quoted 6 lines · Jes Sorensen

If we have reasons where we actually rely on the cpu number, and thats not counting end-user pretty-number-print concerns, then I found that we practically never use the cpu number. If we really use it a lot, I agree we need a fast way, I just didn't hit it in my builds. What did I miss?

The code I mentioned only runs if the -no-kvm-irqchip option is passed. It's not the highest performing option...

So this isn't used a lot. But cpus definitely use cpu numbers (as apic ids), so qemu needs to be prepared to handle this. As to scalability, that takes will take a lot more work than removing/changing arbitrary limits. Look at qemu_mutex and weep.

Signature · 1 line
error compiling committee.c: too many arguments to function
#14 lore raw
Quoted 2 lines · Avi Kivity

The code I mentioned only runs if the -no-kvm-irqchip option is passed. It's not the highest performing option...

What I meant was that I was able to compile the code, and there was only one piece left that needed that function, which is why I moved it and made it static in the acpi code.

Quoted 4 lines

So this isn't used a lot. But cpus definitely use cpu numbers (as apic ids), so qemu needs to be prepared to handle this. As to scalability, that takes will take a lot more work than removing/changing arbitrary limits. Look at qemu_mutex and weep.

Well we have to start somewhere. Just because there's limits in other areas too, doesn't mean we should discard valid improvements elsewhere. I'll get to some of that at some point, but there's soo many cards used to build this house....

Cheers,
Jes

PS: I'll look at your other suggestions to my patch tomorrow.

#15 lore raw
Quoted 8 lines · Jes Sorensen
Quoted 2 lines · Avi Kivity

The code I mentioned only runs if the -no-kvm-irqchip option is passed. It's not the highest performing option...

What I meant was that I was able to compile the code, and there was only one piece left that needed that function, which is why I moved it and made it static in the acpi code.

That's because there is another static array in acpi.c...

Quoted 9 lines
Quoted 4 lines

So this isn't used a lot. But cpus definitely use cpu numbers (as apic ids), so qemu needs to be prepared to handle this. As to scalability, that takes will take a lot more work than removing/changing arbitrary limits. Look at qemu_mutex and weep.

Well we have to start somewhere. Just because there's limits in other areas too, doesn't mean we should discard valid improvements elsewhere. I'll get to some of that at some point, but there's soo many cards used to build this house....

Your patch builds the 16383rd floor while ignoring the 15th. Qemu scaling issues are much, much more painful than what you were addressing.

Signature · 1 line
error compiling committee.c: too many arguments to function
#16 lore raw
Quoted 7 lines · Avi Kivity
Quoted 4 lines · Jes Sorensen

What I meant was that I was able to compile the code, and there was only one piece left that needed that function, which is why I moved it and made it static in the acpi code.

That's because there is another static array in acpi.c...

Which array are you talking about? ACPI has it's own limitations, like we need ACPI 3.0 to go beyond 256 processors :-(

Quoted 7 lines
Quoted 4 lines

Well we have to start somewhere. Just because there's limits in other areas too, doesn't mean we should discard valid improvements elsewhere. I'll get to some of that at some point, but there's soo many cards used to build this house....

Your patch builds the 16383rd floor while ignoring the 15th. Qemu scaling issues are much, much more painful than what you were addressing.

Well I am not ignoring the 15th floor, I am just putting in expandable rails that can go all the way to the 16383rd. Next I'll get to look at putting in the button to make the elevator stop at the 15th+ floors :)

Cheers,
Jes

#17 lore raw
Quoted 22 lines · Jes Sorensen
Quoted 9 lines · Avi Kivity
Quoted 5 lines · Jes Sorensen

What I meant was that I was able to compile the code, and there was only one piece left that needed that function, which is why I moved it and made it static in the acpi code.

That's because there is another static array in acpi.c...

Which array are you talking about? ACPI has it's own limitations, like we need ACPI 3.0 to go beyond 256 processors :-(

Quoted 7 lines
Quoted 4 lines

Well we have to start somewhere. Just because there's limits in other areas too, doesn't mean we should discard valid improvements elsewhere. I'll get to some of that at some point, but there's soo many cards used to build this house....

Your patch builds the 16383rd floor while ignoring the 15th. Qemu scaling issues are much, much more painful than what you were addressing.

Quoted 7 lines

Well I am not ignoring the 15th floor, I am just putting in expandable rails that can go all the way to the 16383rd. Next I'll get to look at putting in the button to make the elevator stop at the 15th+ floors :)

Cheers,
Jes

I think the main point here is that currently, one of the showstopers for scalability,
is the lack of fine grained locking. And we don't really know how the code will look like
after that. It can very well change completely, rendering this work as totally void.

Signature · 5 lines
Glauber  Costa.
"Free as in Freedom"
http://glommer.net

"The less confident you are, the more serious you have to act."
#19 lore raw
In reply to Jes Sorensen
Quoted 8 lines · Jes Sorensen
Quoted 7 lines · Avi Kivity
Quoted 5 lines · Jes Sorensen

What I meant was that I was able to compile the code, and there was only
one piece left that needed that function, which is why I moved it and made it static in the acpi code.

Quoted 5 lines
Quoted 1 line

That's because there is another static array in acpi.c...

Which array are you talking about? ACPI has it's own limitations, like we need ACPI 3.0 to go beyond 256 processors :-(

Sorry. apic.c:

   static APICState *local_apics[MAX_APICS + 1];

A lucky typo, though, since it brought the acpi issue into the discussion.

Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

Well we have to start somewhere. Just because there's limits in other areas too, doesn't mean we should discard valid improvements elsewhere. I'll get to some of that at some point, but there's soo many cards used to build this house....

Quoted 7 lines
Quoted 3 lines

Your patch builds the 16383rd floor while ignoring the 15th. Qemu scaling issues are much, much more painful than what you were addressing.

Well I am not ignoring the 15th floor, I am just putting in expandable rails that can go all the way to the 16383rd. Next I'll get to look at putting in the button to make the elevator stop at the 15th+ floors :)

Well I want 16384 buttons in the elevator, not one button you need to press 16383 times to get to your floor :)

Signature · 1 line
error compiling committee.c: too many arguments to function
#18 lore raw
In reply to Glauber Costa
Quoted 7 lines · Glauber Costa

I think the main point here is that currently, one of the showstopers for scalability,
is the lack of fine grained locking. And we don't really know how the code will look like
after that. It can very well change completely, rendering this work as totally void.

I don't think it will be that bad. Fine-graining locks is an art that is well known, and it's usually not too painful except to those who have to divine the locking rules from the code afterwards.

Signature · 1 line
error compiling committee.c: too many arguments to function
#23 lore raw

PATCH 1/1 pass opague CPUState through libkvm instead of int vcpu

In reply to Avi Kivity
Quoted 9 lines · Avi Kivity
Quoted 4 lines · Jes Sorensen
Quoted 1 line

That's a little ugly -- passing two arguments which describe the vcpu. How about passing env to kvm_create_vcpu() instead?

I am all in favor of doing this, but in order to do so, we have to teach libkvm about CPUState - are you ok with that?

No, libkvm is independent of qemu.

We can make kvm_create_vcpu(kvm_context_t kvm, int vcpu, void *env), and pass 'env' as the opaque to all the callbacks, instead of the vcpu number.

Hi,

I pulled out the part of the patch that does the opague 'env' pointer. It should be pretty straight forward - the vcpu_info patch will go on top of this, but I'll work on that tomorrow.

Let me know what you think - this is about as small I can make this patch :-)

Tested on ia64.

Cheers,
Jes

Change code to pass around opague pointer to CPUState through libkvm, avoiding conversion from CPUState to int vcpu and back in the callbacks into qemu.

---

 libkvm/kvm-common.h     |    8 ++++----
 libkvm/libkvm.c         |   28 ++++++++++++++--------------
 libkvm/libkvm.h         |   10 +++++-----
 qemu/qemu-kvm-ia64.c    |    4 ++--
 qemu/qemu-kvm-powerpc.c |    5 ++---
 qemu/qemu-kvm-x86.c     |   11 +++++------
 qemu/qemu-kvm.c         |   21 ++++++++++++---------
 qemu/qemu-kvm.h         |    4 ++--
 8 files changed, 46 insertions(+), 45 deletions(-)
libkvm/kvm-common.h +4 -4
Index: 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
libkvm/libkvm.c +14 -14
Index: 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:
libkvm/libkvm.h +5 -5
Index: 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
qemu/qemu-kvm-ia64.c +2 -2
Index: 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)
 {
 }
 
qemu/qemu-kvm-powerpc.c +2 -3
Index: 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;
 }
 
qemu/qemu-kvm-x86.c +5 -6
Index: kvm-userspace.git/qemu/qemu-kvm-x86.c
===================================================================
@@ -619,17 +619,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)
qemu/qemu-kvm.c +12 -9
Index: kvm-userspace.git/qemu/qemu-kvm.c
===================================================================
@@ -181,18 +181,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;
@@ -230,7 +231,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);
@@ -635,10 +636,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;
+    vcpu_info[env->cpu_index].stopped = 1;
     return 1;
 }
 
@@ -732,7 +735,7 @@
     return kvm_arch_halt(opaque, vcpu);
 }
 
-static int kvm_shutdown(void *opaque, int vcpu)
+static int kvm_shutdown(void *opaque, void *data)
 {
     /* stop the current vcpu from going back to guest mode */
     vcpu_info[cpu_single_env->cpu_index].stopped = 1;
qemu/qemu-kvm.h +2 -2
Index: kvm-userspace.git/qemu/qemu-kvm.h
===================================================================
@@ -62,8 +62,8 @@
 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);
#24 lore raw

Re: [patch] pass opague CPUState through libkvm instead of int vcpu

Quoted 6 lines · Jes Sorensen

I pulled out the part of the patch that does the opague 'env' pointer. It should be pretty straight forward - the vcpu_info patch will go on top of this, but I'll work on that tomorrow.

Let me know what you think - this is about as small I can make this patch :-)

It's good; applied, thanks.

There's a slight redundancy in that some callbacks are passed two opaques (per-cpu and per-vm), but it won't kill anyone.

(btw, this could have been done much more simply: declare a thread local variable to hold the current env)

Signature · 1 line
error compiling committee.c: too many arguments to function
#25 lore raw

Re: [patch] pass opague CPUState through libkvm instead of int vcpu

Quoted 8 lines · Avi Kivity

Jes Sorensen wrote:
It's good; applied, thanks.

There's a slight redundancy in that some callbacks are passed two opaques (per-cpu and per-vm), but it won't kill anyone.

(btw, this could have been done much more simply: declare a thread local variable to hold the current env)

The thread local current env is coming in the vcpu_info merge patch :-)

Cheers,
Jes