Signed-off-by: Gregory Haskins <[EMAIL PROTECTED]>
---

 qemu/hw/apic.c  |   25 +++++++++++++++++--------
 qemu/hw/pc.c    |   35 ++++++++++++++++++++++++-----------
 qemu/qemu-kvm.c |   53 +++++++++++++++++++++++++++++++++++++++++++----------
 qemu/qemu-kvm.h |    3 +++
 qemu/vl.h       |   15 ++++++++++++++-
 user/kvmctl.c   |   35 ++++++++++++++++++++++++++++++++++-
 user/kvmctl.h   |   31 ++++++++++++++++++++++++++++++-
 user/main.c     |    2 +-
 8 files changed, 166 insertions(+), 33 deletions(-)

diff --git a/qemu/hw/apic.c b/qemu/hw/apic.c
index 5704224..9fbeba2 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;
 
@@ -866,7 +868,7 @@ int apic_init(CPUState *env)
     return 0;
 }
 
-static void ioapic_service(IOAPICState *s)
+void ioapic_service(IOAPICState *s)
 {
     uint8_t i;
     uint8_t trig_mode;
@@ -895,10 +897,16 @@ 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 (use_kernel_apic())
+                   ext_apic_bus_deliver(dest, trig_mode, dest_mode,
+                                        delivery_mode, vector);
+               else {
+                   apic_get_delivery_bitmask(deliver_bitmask, dest,
+                                             dest_mode);
+                   apic_bus_deliver(deliver_bitmask, delivery_mode, 
+                                    vector, polarity, trig_mode);
+               }
             }
         }
     }
@@ -916,7 +924,7 @@ void ioapic_set_irq(void *opaque, int vector, int level)
             /* level triggered */
             if (level) {
                 s->irr |= mask;
-                ioapic_service(s);
+               ioapic_service(s);
             } else {
                 s->irr &= ~mask;
             }
@@ -924,7 +932,7 @@ void ioapic_set_irq(void *opaque, int vector, int level)
             /* edge triggered */
             if (level) {
                 s->irr |= mask;
-                ioapic_service(s);
+               ioapic_service(s);
             }
         }
     }
@@ -1052,7 +1060,7 @@ static CPUWriteMemoryFunc *ioapic_mem_write[3] = {
     ioapic_mem_writel,
 };
 
-IOAPICState *ioapic_init(void)
+IOAPICState *ioapic_init(CPUState *env)
 {
     IOAPICState *s;
     int io_memory;
@@ -1061,6 +1069,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..f50909f 100644
--- a/qemu/hw/pc.c
+++ b/qemu/hw/pc.c
@@ -91,16 +91,19 @@ int cpu_get_pic_interrupt(CPUState *env)
 {
     int intno;
 
+    if (use_kernel_apic())
+       return -1;
+
     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;
+       /* 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;
+       return -1;
 
     intno = pic_read_irq(isa_pic);
     return intno;
@@ -115,6 +118,13 @@ static void pic_irq_request(void *opaque, int level)
         cpu_reset_interrupt(env, CPU_INTERRUPT_HARD);
 }
 
+static void kernel_pic_irq_request(void *opaque, int level)
+{
+    int intno = pic_read_irq(isa_pic);
+    if (intno > 0)
+       ext_set_isa_irq(intno);
+}
+
 /* PC cmos mappings */
 
 #define REG_EQUIPMENT_BYTE          0x14
@@ -483,9 +493,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,13 +681,16 @@ 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);
+    if (use_kernel_apic())
+       isa_pic = pic_init(kernel_pic_irq_request, first_cpu);
+    else
+       isa_pic = pic_init(pic_irq_request, first_cpu);
     pit = pit_init(0x40, 0);
     pcspk_init(pit);
     if (pci_enabled) {
-        pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
+       pic_set_alt_irq_func(isa_pic, ioapic_set_irq, ioapic);
     }
 
     for(i = 0; i < MAX_SERIAL_PORTS; i++) {
diff --git a/qemu/qemu-kvm.c b/qemu/qemu-kvm.c
index 106772b..c9b1497 100644
--- a/qemu/qemu-kvm.c
+++ b/qemu/qemu-kvm.c
@@ -245,9 +245,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);
 
@@ -339,10 +346,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 | \
@@ -425,12 +434,19 @@ static int try_push_interrupts(void *opaque)
     CPUState **envs = opaque, *env;
     env = envs[0];
 
+    if (kvm_apic.level)
+       return 0;
+
     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)
+               // 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;
@@ -445,8 +461,11 @@ static void post_kvm_run(void *opaque, int vcpu)
        ? env->eflags | IF_MASK : env->eflags & ~IF_MASK;
     env->ready_for_interrupt_injection
        = kvm_is_ready_for_interrupt_injection(kvm_context, vcpu);
-    //cpu_set_apic_tpr(env, kvm_run->cr8);
-    cpu_set_apic_base(env, kvm_get_apic_base(kvm_context, vcpu));
+
+    if (!kvm_apic.level) {
+       //cpu_set_apic_tpr(env, kvm_run->cr8);
+       cpu_set_apic_base(env, kvm_get_apic_base(kvm_context, vcpu));
+    }
 }
 
 static void pre_kvm_run(void *opaque, int vcpu)
@@ -454,7 +473,20 @@ static void pre_kvm_run(void *opaque, int vcpu)
     CPUState **envs = opaque, *env;
     env = envs[0];
 
-    kvm_set_cr8(kvm_context, vcpu, cpu_get_apic_tpr(env));
+    if (!kvm_apic.level)
+       kvm_set_cr8(kvm_context, vcpu, 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);
+}
+
+int ext_set_isa_irq(int vector)
+{
+       return kvm_inject_isa_irq(kvm_context, vector);
 }
 
 void kvm_load_registers(CPUState *env)
@@ -679,7 +711,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 c4cb34e..09f9e55 100644
--- a/qemu/qemu-kvm.h
+++ b/qemu/qemu-kvm.h
@@ -8,6 +8,9 @@
 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);
+int ext_set_isa_irq(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.h b/qemu/vl.h
index 4e93a81..6e573f1 100644
--- a/qemu/vl.h
+++ b/qemu/vl.h
@@ -167,6 +167,19 @@ extern int semihosting_enabled;
 extern int autostart;
 extern int time_drift_fix;
 
+#ifdef USE_KVM
+extern int kvm_qemu_get_apic_level(void);
+#endif
+
+static inline int use_kernel_apic()
+{
+#ifdef USE_KVM
+    return kvm_allowed && kvm_qemu_get_apic_level();
+#else
+    return 0;
+#endif
+}
+
 #define MAX_OPTION_ROMS 16
 extern const char *option_rom[MAX_OPTION_ROMS];
 extern int nb_option_roms;
@@ -1060,7 +1073,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 82d1926..c471947 100644
--- a/user/kvmctl.c
+++ b/user/kvmctl.c
@@ -202,7 +202,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;
@@ -259,6 +260,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");
@@ -999,6 +1008,30 @@ 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;
+
+       memset(&msg, 0, sizeof(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 b14cb45..9aab269 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);
 
 /*!
@@ -280,11 +282,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 c5da89c..88ae9f4 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/
_______________________________________________
kvm-devel mailing list
kvm-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/kvm-devel

Reply via email to