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
[email protected]
https://lists.sourceforge.net/lists/listinfo/kvm-devel