diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/kvm_ppc.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 16 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 5 | ||||
-rw-r--r-- | arch/powerpc/kvm/emulate.c | 3 |
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); | |||
82 | extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu); | 82 | extern int kvmppc_core_pending_dec(struct kvm_vcpu *vcpu); |
83 | extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu); | 83 | extern void kvmppc_core_queue_program(struct kvm_vcpu *vcpu); |
84 | extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu); | 84 | extern void kvmppc_core_queue_dec(struct kvm_vcpu *vcpu); |
85 | extern void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu); | ||
85 | extern void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 86 | extern 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 | ||
154 | static 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 | |||
154 | void kvmppc_book3s_queue_irqprio(struct kvm_vcpu *vcpu, unsigned int vec) | 161 | void 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 | ||
188 | void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) | ||
189 | { | ||
190 | kvmppc_book3s_dequeue_irqprio(vcpu, BOOK3S_INTERRUPT_DECREMENTER); | ||
191 | } | ||
192 | |||
181 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 193 | void 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 | ||
100 | void kvmppc_core_dequeue_dec(struct kvm_vcpu *vcpu) | ||
101 | { | ||
102 | clear_bit(BOOKE_IRQPRIO_DECREMENTER, &vcpu->arch.pending_exceptions); | ||
103 | } | ||
104 | |||
100 | void kvmppc_core_queue_external(struct kvm_vcpu *vcpu, | 105 | void 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); |