public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] in-kernel APIC v3a (usermode side)
@ 2007-05-11 20:41 Gregory Haskins
       [not found] ` <20070511203316.22062.4417.stgit-sLgBBP33vUGnsjUZhwzVf9HuzzzSOjJt@public.gmane.org>
  0 siblings, 1 reply; 9+ messages in thread
From: Gregory Haskins @ 2007-05-11 20:41 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

I re-worked the QEMU patches based on feedback from Dor and Anthony.  Here is
the changelog:

1) Got rid of the "extern kvm_context" from qemu/pc/apic.c.  This function is
   now wrapped by qemu-kvm which assigns proper kvm_context on behalf of the
   caller.  

2) Added support for a command line option: "--kvm_apic [0 | 1 | 2]".  The
   system defaults to "level-1" mode (KVM based LAPIC).  Level-0 (QEMU based
   LAPIC) is also supported.  Level-2 is not supported yet, TBD.

3) Added the idea that Anthony proposed to have "kvm_allowed=0" defined, even
    if USE_KVM is not.

4) Cleaned up indentation

5) Cleaned up support for level-0 mode.

I have tested this code (in conjunction with the v3 kernel-patch) against

A) 32 bit XP w/ACPI
B) 64 bit SLED-10 (2.6.16 based)

Any everything seems to be working great.

Note that the current git-HEAD of the userspace code seems to break pretty
badly for linux right now.  I am testing exclusively on Intel chips (5130
Woodcrest and T7600 Merom), so YMMV.  As such, these patches apply to git      
7b9ee2382b07e955cc62a564406e3d9c4a08de6c.

Any feedback at all would be appreciated (particularly news of succesfull
testing :).  Thanks!

Regards,
-Greg

-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

^ permalink raw reply	[flat|nested] 9+ messages in thread
* [PATCH 4/4] KVM: in-kernel-apic modification to QEMU
@ 2007-05-11 21:20 Gregory Haskins
  0 siblings, 0 replies; 9+ messages in thread
From: Gregory Haskins @ 2007-05-11 21:20 UTC (permalink / raw)
  To: kvm-devel-5NWGOfrQmneRv+LV9MX5uipxlwaOVQ5f

This has the latest feedback from Anthony incorporated

Signed-off-by: Gregory Haskins <ghaskins-Et1tbQHTxzrQT0dZR+AlfA@public.gmane.org>
---

 qemu/hw/apic.c  |   20 +++++++++++++++-----
 qemu/hw/pc.c    |   29 ++++++++++++++++-------------
 qemu/qemu-kvm.c |   49 +++++++++++++++++++++++++++++++++++++++----------
 qemu/qemu-kvm.h |    2 ++
 qemu/vl.c       |    2 +-
 qemu/vl.h       |    7 ++++++-
 user/kvmctl.c   |   33 ++++++++++++++++++++++++++++++++-
 user/kvmctl.h   |   31 ++++++++++++++++++++++++++++++-
 user/main.c     |    2 +-
 9 files changed, 142 insertions(+), 33 deletions(-)

diff --git a/qemu/hw/apic.c b/qemu/hw/apic.c
index 0b73233..5665057 100644
--- a/qemu/hw/apic.c
+++ b/qemu/hw/apic.c
@@ -18,6 +18,7 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 #include "vl.h"
+#include "qemu-kvm.h"
 
 //#define DEBUG_APIC
 //#define DEBUG_IOAPIC
@@ -87,6 +88,7 @@ typedef struct APICState {
 } APICState;
 
 struct IOAPICState {
+    CPUState *cpu_env;
     uint8_t id;
     uint8_t ioregsel;
 
@@ -888,10 +890,17 @@ static void ioapic_service(IOAPICState *s)
                     vector = pic_read_irq(isa_pic);
                 else
                     vector = entry & 0xff;
-                
-                apic_get_delivery_bitmask(deliver_bitmask, dest, dest_mode);
-                apic_bus_deliver(deliver_bitmask, delivery_mode, 
-                                 vector, polarity, trig_mode);
+             
+		if (kvm_allowed && kvm_apic_level) {
+		    ext_apic_bus_deliver(dest, trig_mode, dest_mode,
+					 delivery_mode, vector);
+		    cpu_interrupt(s->cpu_env, CPU_INTERRUPT_HARD);
+		} else {
+		    apic_get_delivery_bitmask(deliver_bitmask, dest,
+					      dest_mode);
+		    apic_bus_deliver(deliver_bitmask, delivery_mode, 
+				     vector, polarity, trig_mode);
+		}
             }
         }
     }
@@ -1045,7 +1054,7 @@ static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
     ioapic_mem_writel,
 };
 
-IOAPICState *ioapic_init(void)
+IOAPICState *ioapic_init(CPUState *env)
 {
     IOAPICState *s;
     int io_memory;
@@ -1054,6 +1063,7 @@ IOAPICState *ioapic_init(void)
     if (!s)
         return NULL;
     ioapic_reset(s);
+    s->cpu_env = env;
     s->id = last_apic_id++;
 
     io_memory = cpu_register_io_memory(0, ioapic_mem_read, 
diff --git a/qemu/hw/pc.c b/qemu/hw/pc.c
index eda49cf..618cc32 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -91,16 +91,19 @@ int cpu_get_pic_interrupt(CPUState *env)
 {
     int intno;
 
-    intno = apic_get_interrupt(env);
-    if (intno >= 0) {
-        /* set irq request if a PIC irq is still pending */
-        /* XXX: improve that */
-        pic_update_irq(isa_pic); 
-        return intno;
+    if (!use_kernel_apic()) {
+	intno = apic_get_interrupt(env);
+	if (intno >= 0) {
+	    /* set irq request if a PIC irq is still pending */
+	    /* XXX: improve that */
+	    pic_update_irq(isa_pic); 
+	    return intno;
+	}
+	
+	/* read the irq from the PIC */
+	if (!apic_accept_pic_intr(env))
+	    return -1;
     }
-    /* read the irq from the PIC */
-    if (!apic_accept_pic_intr(env))
-        return -1;
 
     intno = pic_read_irq(isa_pic);
     return intno;
@@ -483,9 +486,9 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
         }
         register_savevm("cpu", i, 4, cpu_save, cpu_load, env);
         qemu_register_reset(main_cpu_reset, env);
-        if (pci_enabled) {
-            apic_init(env);
-        }
+	if (!use_kernel_apic() && pci_enabled) {
+		apic_init(env);
+	    }
     }
 
     /* allocate RAM */
@@ -671,7 +674,7 @@ static void pc_init1(int ram_size, int vga_ram_size, int boot_device,
     register_ioport_write(0x92, 1, 1, ioport92_write, NULL);
 
     if (pci_enabled) {
-        ioapic = ioapic_init();
+        ioapic = ioapic_init(env);
     }
     isa_pic = pic_init(pic_irq_request, first_cpu);
     pit = pit_init(0x40, 0);
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index faa4684..59e79bf 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -235,9 +235,16 @@ static void load_regs(CPUState *env)
     sregs.cr3 = env->cr[3];
     sregs.cr4 = env->cr[4];
 
-    sregs.apic_base = cpu_get_apic_base(env);
+    if (!kvm_apic_level) {
+	/* These two are no longer used once the in-kernel APIC is enabled */
+	sregs.apic_base = 0;
+	sregs.cr8 = 0;
+    } else {
+	sregs.apic_base = cpu_get_apic_base(env);
+	sregs.cr8 = cpu_get_apic_tpr(env);
+    }
+
     sregs.efer = env->efer;
-    sregs.cr8 = cpu_get_apic_tpr(env);
 
     kvm_set_sregs(kvm_context, 0, &sregs);
 
@@ -329,10 +336,12 @@ static void save_regs(CPUState *env)
     env->cr[3] = sregs.cr3;
     env->cr[4] = sregs.cr4;
 
-    cpu_set_apic_base(env, sregs.apic_base);
+    if (!kvm_apic_level) {
+	cpu_set_apic_base(env, sregs.apic_base);
+	//cpu_set_apic_tpr(env, sregs.cr8);
+    }
 
     env->efer = sregs.efer;
-    //cpu_set_apic_tpr(env, sregs.cr8);
 
 #define HFLAG_COPY_MASK ~( \
 			HF_CPL_MASK | HF_PE_MASK | HF_MP_MASK | HF_EM_MASK | \
@@ -418,9 +427,17 @@ static int try_push_interrupts(void *opaque)
     if (env->ready_for_interrupt_injection &&
         (env->interrupt_request & CPU_INTERRUPT_HARD) &&
         (env->eflags & IF_MASK)) {
+	    int irq = cpu_get_pic_interrupt(env);
+
+	    if (irq != -1) {
+		if (kvm_apic_level)
+		    kvm_inject_isa_irq(kvm_context, irq);
+		else
+		    // for now using cpu 0
+		    kvm_inject_irq(kvm_context, 0, irq);
+	    }
+	    
             env->interrupt_request &= ~CPU_INTERRUPT_HARD;
-            // for now using cpu 0
-            kvm_inject_irq(kvm_context, 0, cpu_get_pic_interrupt(env));
     }
 
     return (env->interrupt_request & CPU_INTERRUPT_HARD) != 0;
@@ -433,8 +450,11 @@ static void post_kvm_run(void *opaque, struct kvm_run *kvm_run)
 
     env->eflags = (kvm_run->if_flag) ? env->eflags | IF_MASK:env->eflags & ~IF_MASK;
     env->ready_for_interrupt_injection = kvm_run->ready_for_interrupt_injection;
-    //cpu_set_apic_tpr(env, kvm_run->cr8);
-    cpu_set_apic_base(env, kvm_run->apic_base);
+
+    if (!kvm_apic_level) {
+	//cpu_set_apic_tpr(env, kvm_run->cr8);
+	cpu_set_apic_base(env, kvm_run->apic_base);
+    }
 }
 
 static void pre_kvm_run(void *opaque, struct kvm_run *kvm_run)
@@ -442,7 +462,15 @@ static void pre_kvm_run(void *opaque, struct kvm_run *kvm_run)
     CPUState **envs = opaque, *env;
     env = envs[0];
 
-    kvm_run->cr8 = cpu_get_apic_tpr(env);
+    if (!kvm_apic_level)
+	kvm_run->cr8 = cpu_get_apic_tpr(env);
+}
+
+int ext_apic_bus_deliver(int dest, int trig_mode, int dest_mode,
+			 int delivery_mode, int vector)
+{
+	return kvm_apic_bus_deliver(kvm_context, dest, trig_mode, dest_mode,
+				    delivery_mode, vector);
 }
 
 void kvm_load_registers(CPUState *env)
@@ -670,7 +698,8 @@ int kvm_qemu_create_context(void)
 {
     int i;
 
-    if (kvm_create(kvm_context, phys_ram_size, (void**)&phys_ram_base) < 0) {
+    if (kvm_create(kvm_context, phys_ram_size, kvm_apic_level,
+		   (void**)&phys_ram_base) < 0) {
 	kvm_qemu_destroy();
 	return -1;
     }
diff --git a/qemu/qemu-kvm.h b/qemu/qemu-kvm.h
index 8a1c25d..7bfdf62 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -6,6 +6,8 @@
 int kvm_qemu_init(void);
 int kvm_qemu_create_context(void);
 void kvm_qemu_destroy(void);
+int ext_apic_bus_deliver(int dest, int trig_mode, int dest_mode,
+			 int delivery_mode, int vector);
 void kvm_load_registers(CPUState *env);
 void kvm_save_registers(CPUState *env);
 int kvm_cpu_exec(CPUState *env);
diff --git a/qemu/vl.c b/qemu/vl.c
index 88e650e..986cea4 100644
--- a/qemu/vl.c
+++ b/qemu/vl.c
@@ -7312,7 +7312,7 @@ int main(int argc, char **argv)
 		kvm_allowed = 0;
 		break;
 	    case QEMU_OPTION_kvm_apic:
-		kvm_apic_level = optarg;
+		kvm_apic_level = atoi(optarg);
 		break;
 #endif
             case QEMU_OPTION_usb:
diff --git a/qemu/vl.h b/qemu/vl.h
index dec410e..d532117 100644
--- a/qemu/vl.h
+++ b/qemu/vl.h
@@ -167,6 +167,11 @@ extern int semihosting_enabled;
 extern int autostart;
 extern int time_drift_fix;
 
+static inline int use_kernel_apic()
+{
+    return kvm_allowed && kvm_apic_level;
+}
+
 #define MAX_OPTION_ROMS 16
 extern const char *option_rom[MAX_OPTION_ROMS];
 extern int nb_option_roms;
@@ -1060,7 +1065,7 @@ typedef struct IOAPICState IOAPICState;
 int apic_init(CPUState *env);
 int apic_get_interrupt(CPUState *env);
 int apic_accept_pic_intr(CPUState *env);
-IOAPICState *ioapic_init(void);
+IOAPICState *ioapic_init(CPUState *env);
 void ioapic_set_irq(void *opaque, int vector, int level);
 
 /* i8254.c */
diff --git a/user/kvmctl.c b/user/kvmctl.c
index dcdffbf..bc6e238 100644
--- a/user/kvmctl.c
+++ b/user/kvmctl.c
@@ -225,7 +225,8 @@ void kvm_finalize(kvm_context_t kvm)
 	free(kvm);
 }
 
-int kvm_create(kvm_context_t kvm, unsigned long memory, void **vm_mem)
+int kvm_create(kvm_context_t kvm, unsigned long memory, int apic_level,
+	       void **vm_mem)
 {
 	unsigned long dosmem = 0xa0000;
 	unsigned long exmem = 0xc0000;
@@ -282,6 +283,14 @@ int kvm_create(kvm_context_t kvm, unsigned long memory, void **vm_mem)
 	     MAP_PRIVATE|MAP_FIXED, zfd, 0);
 	close(zfd);
 
+	if (apic_level) {
+		r = ioctl(fd, KVM_ENABLE_KERNEL_PIC, &apic_level);
+		if (r == -1) {
+			fprintf(stderr, "kvm_enable_kernel_pic: %m\n");
+			return -1;
+		}
+	}
+
 	r = ioctl(fd, KVM_CREATE_VCPU, 0);
 	if (r == -1) {
 		fprintf(stderr, "kvm_create_vcpu: %m\n");
@@ -780,6 +789,28 @@ int kvm_inject_irq(kvm_context_t kvm, int vcpu, unsigned irq)
 	return ioctl(kvm->vcpu_fd[vcpu], KVM_INTERRUPT, &intr);
 }
 
+int kvm_inject_isa_irq(kvm_context_t kvm, unsigned irq)
+{
+	struct kvm_interrupt intr;
+
+	intr.irq = irq;
+	return ioctl(kvm->vm_fd, KVM_ISA_INTERRUPT, &intr);
+}
+
+int kvm_apic_bus_deliver(kvm_context_t kvm, int dest, int trig_mode,
+			 int dest_mode, int delivery_mode, int vector)
+{
+	struct kvm_apic_msg msg;
+
+	msg.dest          = dest;
+	msg.trig_mode     = trig_mode;
+	msg.dest_mode     = dest_mode;
+	msg.delivery_mode = delivery_mode;
+	msg.vector        = vector;
+
+	return ioctl(kvm->vm_fd, KVM_APIC_MSG, &msg);
+}
+
 int kvm_guest_debug(kvm_context_t kvm, int vcpu, struct kvm_debug_guest *dbg)
 {
 	return ioctl(kvm->vcpu_fd[vcpu], KVM_DEBUG_GUEST, dbg);
diff --git a/user/kvmctl.h b/user/kvmctl.h
index 27c010c..b775347 100644
--- a/user/kvmctl.h
+++ b/user/kvmctl.h
@@ -100,12 +100,14 @@ void kvm_finalize(kvm_context_t kvm);
  *
  * \param kvm Pointer to the current kvm_context
  * \param phys_mem_bytes The amount of physical ram you want the VM to have
+ * \param apic_level The APIC emulation level (0=QEMU, 1=KVM)
  * \param phys_mem This pointer will be set to point to the memory that
  * kvm_create allocates for physical RAM
  * \return 0 on success
  */
 int kvm_create(kvm_context_t kvm,
 	       unsigned long phys_mem_bytes,
+	       int apic_level,
 	       void **phys_mem);
 
 /*!
@@ -236,11 +238,38 @@ int kvm_set_msrs(kvm_context_t, int vcpu, struct kvm_msr_entry *msrs, int n);
  * This allows you to simulate an external vectored interrupt.
  *
  * \param kvm Pointer to the current kvm_context
- * \param vcpu Which virtual CPU should get dumped
+ * \param vcpu Which virtual CPU should handle interrupt
  * \param irq Vector number
  * \return 0 on success
  */
 int kvm_inject_irq(kvm_context_t kvm, int vcpu, unsigned irq);
+
+/*!
+ * \brief Simulate an external vectored interrupt to the ISA bus
+ *
+ * This allows you to simulate an external vectored interrupt.
+ *
+ * \param kvm Pointer to the current kvm_context
+ * \param irq Vector number
+ * \return 0 on success
+ */
+int kvm_inject_isa_irq(kvm_context_t kvm, unsigned irq);
+
+/*!
+ * \brief Simulate an external vectored interrupt to the APIC bus
+ *
+ * This allows you to simulate a vectored interrupt via the LAPIC mechanism.
+ *
+ * \param kvm Pointer to the current kvm_context
+ * \param dest Encoded destination
+ * \param trig_mode 0=edge-trigger, 1=level-trigger
+ * \param dest_mode Destination mode encoding
+ * \param delivery_mode Delivery_mode encoding
+ * \param vector The vector number
+ * \return 0 on success
+ */
+int kvm_apic_bus_deliver(kvm_context_t kvm, int dest, int trig_mode,
+			 int dest_mode, int delivery_mode, int vector);
 int kvm_guest_debug(kvm_context_t, int vcpu, struct kvm_debug_guest *dbg);
 
 /*!
diff --git a/user/main.c b/user/main.c
index 83fd752..add5eef 100644
--- a/user/main.c
+++ b/user/main.c
@@ -180,7 +180,7 @@ int main(int ac, char **av)
 	    fprintf(stderr, "kvm_init failed\n");
 	    return 1;
 	}
-	if (kvm_create(kvm, 128 * 1024 * 1024, &vm_mem) < 0) {
+	if (kvm_create(kvm, 128 * 1024 * 1024, 1, &vm_mem) < 0) {
 	    kvm_finalize(kvm);
 	    fprintf(stderr, "kvm_create failed\n");
 	    return 1;


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/

^ permalink raw reply related	[flat|nested] 9+ messages in thread

end of thread, other threads:[~2007-05-14 12:09 UTC | newest]

Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-05-11 20:41 [PATCH 0/4] in-kernel APIC v3a (usermode side) Gregory Haskins
     [not found] ` <20070511203316.22062.4417.stgit-sLgBBP33vUGnsjUZhwzVf9HuzzzSOjJt@public.gmane.org>
2007-05-11 20:42   ` [PATCH 1/4] KVM: Updates for compiling in-kernel APIC support with external-modules Gregory Haskins
2007-05-11 20:42   ` [PATCH 2/4] KVM-USER: Make the kvm_allowed flag always defined so we dont need #ifdefs Gregory Haskins
     [not found]     ` <20070511204206.22062.7570.stgit-sLgBBP33vUGnsjUZhwzVf9HuzzzSOjJt@public.gmane.org>
2007-05-14 12:09       ` Avi Kivity
2007-05-11 20:42   ` [PATCH 3/4] KVM-USER: Add ability to specify APIC emulation type from the command-line Gregory Haskins
2007-05-11 20:42   ` [PATCH 4/4] KVM: in-kernel-apic modification to QEMU Gregory Haskins
     [not found]     ` <20070511204216.22062.97272.stgit-sLgBBP33vUGnsjUZhwzVf9HuzzzSOjJt@public.gmane.org>
2007-05-11 20:52       ` Anthony Liguori
     [not found]         ` <4644D7AB.5040309-r/Jw6+rmf7HQT0dZR+AlfA@public.gmane.org>
2007-05-11 21:20           ` Gregory Haskins
  -- strict thread matches above, loose matches on Subject: below --
2007-05-11 21:20 Gregory Haskins

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox