aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm/book3s.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/kvm/book3s.c')
-rw-r--r--arch/powerpc/kvm/book3s.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 5cb5f0d9381f..d6227ff0ceae 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -251,14 +251,28 @@ int kvmppc_book3s_irqprio_deliver(struct kvm_vcpu *vcpu, unsigned int priority)
251 int deliver = 1; 251 int deliver = 1;
252 int vec = 0; 252 int vec = 0;
253 ulong flags = 0ULL; 253 ulong flags = 0ULL;
254 ulong crit_raw = vcpu->arch.shared->critical;
255 ulong crit_r1 = kvmppc_get_gpr(vcpu, 1);
256 bool crit;
257
258 /* Truncate crit indicators in 32 bit mode */
259 if (!(vcpu->arch.shared->msr & MSR_SF)) {
260 crit_raw &= 0xffffffff;
261 crit_r1 &= 0xffffffff;
262 }
263
264 /* Critical section when crit == r1 */
265 crit = (crit_raw == crit_r1);
266 /* ... and we're in supervisor mode */
267 crit = crit && !(vcpu->arch.shared->msr & MSR_PR);
254 268
255 switch (priority) { 269 switch (priority) {
256 case BOOK3S_IRQPRIO_DECREMENTER: 270 case BOOK3S_IRQPRIO_DECREMENTER:
257 deliver = vcpu->arch.shared->msr & MSR_EE; 271 deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
258 vec = BOOK3S_INTERRUPT_DECREMENTER; 272 vec = BOOK3S_INTERRUPT_DECREMENTER;
259 break; 273 break;
260 case BOOK3S_IRQPRIO_EXTERNAL: 274 case BOOK3S_IRQPRIO_EXTERNAL:
261 deliver = vcpu->arch.shared->msr & MSR_EE; 275 deliver = (vcpu->arch.shared->msr & MSR_EE) && !crit;
262 vec = BOOK3S_INTERRUPT_EXTERNAL; 276 vec = BOOK3S_INTERRUPT_EXTERNAL;
263 break; 277 break;
264 case BOOK3S_IRQPRIO_SYSTEM_RESET: 278 case BOOK3S_IRQPRIO_SYSTEM_RESET: