diff options
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/include/asm/kvm_para.h | 1 | ||||
-rw-r--r-- | arch/powerpc/kvm/book3s.c | 18 | ||||
-rw-r--r-- | arch/powerpc/kvm/booke.c | 15 |
3 files changed, 32 insertions, 2 deletions
diff --git a/arch/powerpc/include/asm/kvm_para.h b/arch/powerpc/include/asm/kvm_para.h index 556fd59ee0f1..4577e7b6dff1 100644 --- a/arch/powerpc/include/asm/kvm_para.h +++ b/arch/powerpc/include/asm/kvm_para.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <linux/of.h> | 24 | #include <linux/of.h> |
25 | 25 | ||
26 | struct kvm_vcpu_arch_shared { | 26 | struct kvm_vcpu_arch_shared { |
27 | __u64 critical; /* Guest may not get interrupts if == r1 */ | ||
27 | __u64 sprg0; | 28 | __u64 sprg0; |
28 | __u64 sprg1; | 29 | __u64 sprg1; |
29 | __u64 sprg2; | 30 | __u64 sprg2; |
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: |
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c index 13e0747178e3..104d0ee8c8aa 100644 --- a/arch/powerpc/kvm/booke.c +++ b/arch/powerpc/kvm/booke.c | |||
@@ -147,6 +147,20 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
147 | int allowed = 0; | 147 | int allowed = 0; |
148 | ulong uninitialized_var(msr_mask); | 148 | ulong uninitialized_var(msr_mask); |
149 | bool update_esr = false, update_dear = false; | 149 | bool update_esr = false, update_dear = false; |
150 | ulong crit_raw = vcpu->arch.shared->critical; | ||
151 | ulong crit_r1 = kvmppc_get_gpr(vcpu, 1); | ||
152 | bool crit; | ||
153 | |||
154 | /* Truncate crit indicators in 32 bit mode */ | ||
155 | if (!(vcpu->arch.shared->msr & MSR_SF)) { | ||
156 | crit_raw &= 0xffffffff; | ||
157 | crit_r1 &= 0xffffffff; | ||
158 | } | ||
159 | |||
160 | /* Critical section when crit == r1 */ | ||
161 | crit = (crit_raw == crit_r1); | ||
162 | /* ... and we're in supervisor mode */ | ||
163 | crit = crit && !(vcpu->arch.shared->msr & MSR_PR); | ||
150 | 164 | ||
151 | switch (priority) { | 165 | switch (priority) { |
152 | case BOOKE_IRQPRIO_DTLB_MISS: | 166 | case BOOKE_IRQPRIO_DTLB_MISS: |
@@ -181,6 +195,7 @@ static int kvmppc_booke_irqprio_deliver(struct kvm_vcpu *vcpu, | |||
181 | case BOOKE_IRQPRIO_DECREMENTER: | 195 | case BOOKE_IRQPRIO_DECREMENTER: |
182 | case BOOKE_IRQPRIO_FIT: | 196 | case BOOKE_IRQPRIO_FIT: |
183 | allowed = vcpu->arch.shared->msr & MSR_EE; | 197 | allowed = vcpu->arch.shared->msr & MSR_EE; |
198 | allowed = allowed && !crit; | ||
184 | msr_mask = MSR_CE|MSR_ME|MSR_DE; | 199 | msr_mask = MSR_CE|MSR_ME|MSR_DE; |
185 | break; | 200 | break; |
186 | case BOOKE_IRQPRIO_DEBUG: | 201 | case BOOKE_IRQPRIO_DEBUG: |