aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2009-12-21 14:21:24 -0500
committerMarcelo Tosatti <mtosatti@redhat.com>2010-03-01 10:35:42 -0500
commit7706664d39a8eb8555408a24b1f17bd2086189c6 (patch)
treec71bde99ac96573e137c29f990e0af4c1854b4df
parent583617b7866cfcc0b3830a4b7ab20f218d180f67 (diff)
KVM: powerpc: Improve DEC handling
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>
-rw-r--r--arch/powerpc/include/asm/kvm_ppc.h1
-rw-r--r--arch/powerpc/kvm/book3s.c16
-rw-r--r--arch/powerpc/kvm/booke.c5
-rw-r--r--arch/powerpc/kvm/emulate.c3
4 files changed, 24 insertions, 1 deletions
diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
index 269ee46ab028..abfd0c4d567b 100644
--- a/arch/powerpc/include/asm/kvm_ppc.h
+++ b/arch/powerpc/include/asm/kvm_ppc.h
@@ -82,6 +82,7 @@ extern void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu);
82extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu); 82extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu);
83extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu); 83extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu);
84extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu); 84extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu);
85extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu);
85extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, 86extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
86 struct kvm_interrupt *irq); 87 struct kvm_interrupt *irq);
87 88
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 241795bdf34c..fd3ad6c7f355 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -151,6 +151,13 @@ static int kvmppc_book3s_vec2irqprio(unsigned int vec)
151 return prio; 151 return prio;
152} 152}
153 153
154static void kvmppc_book3s_dequeue_irqprio(struct kvm_vcpu *vcpu,
155 unsigned int vec)
156{
157 clear_bit(kvmppc_book3s_vec2irqprio(vec),
158 &vcpu->arch.pending_exceptions);
159}
160
154void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) 161void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec)
155{ 162{
156 vcpu->stat.queue_intr++; 163 vcpu->stat.queue_intr++;
@@ -178,6 +185,11 @@ int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
178 return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions); 185 return test_bit(BOOK3S_INTERRUPT_DECREMENTER >> 7, &vcpu->arch.pending_exceptions);
179} 186}
180 187
188void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
189{
190 kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER);
191}
192
181void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, 193void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
182 struct kvm_interrupt *irq) 194 struct kvm_interrupt *irq)
183{ 195{
@@ -275,7 +287,9 @@ void kvmppc_core_deliver_interrupts(struct kvm_vcpu *vcpu)
275#endif 287#endif
276 priority = __ffs(*pending); 288 priority = __ffs(*pending);
277 while (priority <= (sizeof(unsigned int) * 8)) { 289 while (priority <= (sizeof(unsigned int) * 8)) {
278 if (kvmppc_book3s_irqprio_deliver(vcpu, priority)) { 290 if (kvmppc_book3s_irqprio_deliver(vcpu, priority) &&
291 (priority != BOOK3S_IRQPRIO_DECREMENTER)) {
292 /* DEC interrupts get cleared by mtdec */
279 clear_bit(priority, &vcpu->arch.pending_exceptions); 293 clear_bit(priority, &vcpu->arch.pending_exceptions);
280 break; 294 break;
281 } 295 }
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 06f5a9ecc42c..d8b63420acf8 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -97,6 +97,11 @@ int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu)
97 return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions); 97 return test_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
98} 98}
99 99
100void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu)
101{
102 clear_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions);
103}
104
100void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, 105void kvmppc_core_queue_external(struct kvm_vcpu *vcpu,
101 struct kvm_interrupt *irq) 106 struct kvm_interrupt *irq)
102{ 107{
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index 4a9ac6640fad..303457b2f52a 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -83,6 +83,9 @@ void kvmppc_emulate_dec(struct kvm_vcpu *vcpu)
83 83
84 pr_debug("mtDEC: %x\n", vcpu->arch.dec); 84 pr_debug("mtDEC: %x\n", vcpu->arch.dec);
85#ifdef CONFIG_PPC64 85#ifdef CONFIG_PPC64
86 /* mtdec lowers the interrupt line when positive. */
87 kvmppc_core_dequeue_dec(vcpu);
88
86 /* POWER4+ triggers a dec interrupt if the value is < 0 */ 89 /* POWER4+ triggers a dec interrupt if the value is < 0 */
87 if (vcpu->arch.dec & 0x80000000) { 90 if (vcpu->arch.dec & 0x80000000) {
88 hrtimer_try_to_cancel(&vcpu->arch.dec_timer); 91 hrtimer_try_to_cancel(&vcpu->arch.dec_timer);