aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/kvm_para.h1
-rw-r--r--arch/powerpc/kvm/book3s.c18
-rw-r--r--arch/powerpc/kvm/booke.c15
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
26struct kvm_vcpu_arch_shared { 26struct 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: