There is still a minor issue with the in-kernel APIC (even in v8) w.r.t. informing QEMU about irq-windows. As a result, QEMU thinks there are more windows than there actually are, and pushes another round of interrupts down into the kernel. Since PICs can generally only queue 1-2 interrupts, this results in an occasional interrupt being "lost".
Despite this, the system operates functionally correct, but slower than optimal. Even so, the in-kernel APIC offers an 11% speed-up over kvm-trunk. But the potential speedup is much more due to the many conversions of many common exits to light-exits. This patch is a workaround to the lost interrupt problem that can be applied to reveal another 12% performance improvement. It is an interim solution while I fix the real lost interrupts problem (hopefully in the next day or so) in case you want to test "full speed". I find the combination of v8 + backlog.patch to offer the best performance I have seen to date. Signed-off-by: Gregory Haskins <[EMAIL PROTECTED]> --- drivers/kvm/lapic.c | 36 ++++++++++++++++-------------------- 1 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/kvm/lapic.c b/drivers/kvm/lapic.c index 602e94c..1b5f001 100644 --- a/drivers/kvm/lapic.c +++ b/drivers/kvm/lapic.c @@ -39,6 +39,8 @@ /* #define apic_debug(fmt,arg...) printk(KERN_WARNING fmt,##arg) */ #define apic_debug(fmt,arg...) +#define MAX_APIC_INT_VECTOR 256 + struct kvm_kern_apic { spinlock_t lock; atomic_t ref_count; @@ -49,11 +51,11 @@ struct kvm_kern_apic { unsigned long base_address; struct kvm_io_device mmio_dev; struct { - unsigned long pending; u32 divide_count; ktime_t last_update; struct hrtimer dev; } timer; + u64 backlog[MAX_APIC_INT_VECTOR]; u32 err_status; u32 err_write_count; struct kvm_vcpu *vcpu; @@ -82,7 +84,6 @@ static __inline__ int find_highest_bit(unsigned long *data, int nr_bits) #define APIC_GLOB_DISABLE_MASK 0x1 #define APIC_SOFTWARE_DISABLE_MASK 0x2 #define _APIC_BSP_ACCEPT_PIC 0x3 -#define MAX_APIC_INT_VECTOR 256 #define inject_gp(vcpu) kvm_arch_ops->inject_gp(vcpu, 0); @@ -384,6 +385,8 @@ static int __apic_accept_irq(struct kvm_kern_apic *apic, set_bit(vector, apic->regs + APIC_TMR); } + ++apic->backlog[vector]; + apic_debug("FIXED/LOWEST interrupt for vector %d\n", vector); pin = kvm_irqpin_localint; break; @@ -465,7 +468,7 @@ static void apic_set_eoi(struct kvm_kern_apic *apic) __clear_bit(vector, apic->regs + APIC_ISR); forward = apic_update_ppr(apic); - __clear_bit(vector, apic->regs + APIC_TMR); + //__clear_bit(vector, apic->regs + APIC_TMR); if (forward) { spin_unlock_bh(&apic->lock); @@ -1118,9 +1121,10 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu) apic->base_address = apic->base_msr & MSR_IA32_APICBASE_BASE; apic->timer.divide_count = 0; - apic->timer.pending = 0; apic->status = 0; + memset(apic->backlog, 0, sizeof(apic->backlog)); + #ifdef APIC_NO_BIOS /* * XXX According to mp specification, BIOS will enable LVT0/1, @@ -1182,7 +1186,6 @@ static int __apic_timer_fn(struct kvm_kern_apic *apic) vector = apic_lvt_vector(apic, APIC_LVTT); now = apic->timer.dev.base->get_time(); apic->timer.last_update = now; - apic->timer.pending++; __apic_accept_irq(apic, APIC_DM_FIXED, vector, 1, 0); @@ -1254,24 +1257,17 @@ static int apic_irqdev_ack(struct kvm_irqdevice *this, int flags, irq = apic_find_highest_irr(apic); if ((irq & 0xf0) > apic_get_reg(apic, APIC_PROCPRI)) { BUG_ON (irq < 0x10); + BUG_ON (irq > 0xff); __set_bit(irq, apic->regs + APIC_ISR); - __clear_bit(irq, apic->regs + APIC_IRR); - apic_update_ppr(apic); - /* - * We have to special case the timer interrupt - * because we want the vector to stay pending - * for each tick of the clock, even for a backlog. - * Therefore, if this was a timer vector and we - * still have ticks pending, keep IRR set - */ - if (irq == apic_lvt_vector(apic, APIC_LVTT)) { - BUG_ON(!apic->timer.pending); - apic->timer.pending--; - if (apic->timer.pending) - __set_bit(irq, apic->regs + APIC_IRR); - } + if (apic->backlog[irq]) + --apic->backlog[irq]; + + if (!apic->backlog[irq]) + __clear_bit(irq, apic->regs + APIC_IRR); + + apic_update_ppr(apic); data->flags |= KVM_IRQACKDATA_VECTOR_VALID; data->vector = irq; ------------------------------------------------------------------------- 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