]> git.openfabrics.org - ~emulex/infiniband.git/commitdiff
KVM: powerpc: Improve DEC handling
authorAlexander Graf <agraf@suse.de>
Mon, 21 Dec 2009 19:21:24 +0000 (20:21 +0100)
committerMarcelo Tosatti <mtosatti@redhat.com>
Mon, 1 Mar 2010 15:35:42 +0000 (12:35 -0300)
We treated the DEC interrupt like an edge based one. This is not true for
Book3s. The DEC keeps firing until mtdec is issued again and thus clears
the interrupt line.

So let's implement this logic in KVM too. This patch moves the line clearing
from the firing of the interrupt to the mtdec emulation.

This makes PPC64 guests work without AGGRESSIVE_DEC defined.

Signed-off-by: Alexander Graf <agraf@suse.de>
Acked-by: Acked-by: Hollis Blanchard <hollis@penguinppc.org>
Signed-off-by: Avi Kivity <avi@redhat.com>
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/kvm/book3s.c
arch/powerpc/kvm/booke.c
arch/powerpc/kvm/emulate.c

index 269ee46ab0285701f84411748a51e6f14c5b1018..abfd0c4d567b9249060fa4c562d6da4a2fffb185 100644 (file)
@@ -82,6 +82,7 @@ extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
 extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
+extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
 extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                        struct kvm_interrupt *irq);
 
index 241795bdf34c4bf3336087cbe8e8fd0a7a586d1d..fd3ad6c7f3551a02fb96fc8535171b32a5544612 100644 (file)
@@ -151,6 +151,13 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
        return prio;
 }
 
+static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
+                                         unsigned int vec)
+{
+       clear_bit(kvmppc_book3s_vec2irqprio(vec),
+                 &vcpu->arch.pending_exceptions);
+}
+
 void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
 {
        vcpu->stat.queue_intr++;
@@ -178,6 +185,11 @@ int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
        return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions);
 }
 
+void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
+{
+       kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER);
+}
+
 void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                 struct kvm_interrupt *irq)
 {
@@ -275,7 +287,9 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
 #endif
        priority = __ffs(*pending);
        while (priority <= (sizeof(unsigned int) * 8)) {
-               if (kvmppc_book3s_irqprio_deliver(vcpu, priority)) {
+               if (kvmppc_book3s_irqprio_deliver(vcpu, priority) &&
+                   (priority != BOOK3S_IRQPRIO_DECREMENTER)) {
+                       /* DEC interrupts get cleared by mtdec */
                        clear_bit(priority, &vcpu->arch.pending_exceptions);
                        break;
                }
index 06f5a9ecc42c9fc950666b44a177b7eadeb668ed..d8b63420acf8f179c836eec967de3d05e6a065ce 100644 (file)
@@ -97,6 +97,11 @@ int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
        return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
 }
 
+void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
+{
+       clear_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
+}
+
 void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
                                 struct kvm_interrupt *irq)
 {
index 4a9ac6640fadb93182d9ade73310f1af1e0c4b93..303457b2f52acd1511cf87f8a68f159c4bbe44b2 100644 (file)
@@ -83,6 +83,9 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
 
        pr_debug("mtDEC: %x\n", vcpu->arch.dec);
 #ifdef CONFIG_PPC64
+       /* mtdec lowers the interrupt line when positive. */
+       kvmppc_core_dequeue_dec(vcpu);
+
        /* POWER4+ triggers a dec interrupt if the value is < 0 */
        if (vcpu->arch.dec & 0x80000000) {
                hrtimer_try_to_cancel(&vcpu->arch.dec_timer);