aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Huth <thuth@redhat.com>2017-04-05 09:58:51 -0400
committerPaul Mackerras <paulus@ozlabs.org>2017-04-19 21:39:32 -0400
commitfeafd13c96d6e2998d3da81bb55db379fcf02499 (patch)
tree6049c97e88caf30912603728ca446d457bfd739f
parent121f80ba68f1a5779a36d7b3247206e60e0a7418 (diff)
KVM: PPC: Book3S PR: Do not fail emulation with mtspr/mfspr for unknown SPRs
According to the PowerISA 2.07, mtspr and mfspr should not always generate an illegal instruction exception when being used with an undefined SPR, but rather treat the instruction as a NOP or inject a privilege exception in some cases, too - depending on the SPR number. Also turn the printk here into a ratelimited print statement, so that the guest can not flood the dmesg log of the host by issueing lots of illegal mtspr/mfspr instruction here. Signed-off-by: Thomas Huth <thuth@redhat.com> Signed-off-by: Paul Mackerras <paulus@ozlabs.org>
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c34
-rw-r--r--arch/powerpc/kvm/emulate.c8
2 files changed, 34 insertions, 8 deletions
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 8359752b3efc..68d68983948e 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -503,10 +503,18 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
503 break; 503 break;
504unprivileged: 504unprivileged:
505 default: 505 default:
506 printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn); 506 pr_info_ratelimited("KVM: invalid SPR write: %d\n", sprn);
507#ifndef DEBUG_SPR 507 if (sprn & 0x10) {
508 emulated = EMULATE_FAIL; 508 if (kvmppc_get_msr(vcpu) & MSR_PR) {
509#endif 509 kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
510 emulated = EMULATE_AGAIN;
511 }
512 } else {
513 if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0) {
514 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
515 emulated = EMULATE_AGAIN;
516 }
517 }
510 break; 518 break;
511 } 519 }
512 520
@@ -648,10 +656,20 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
648 break; 656 break;
649 default: 657 default:
650unprivileged: 658unprivileged:
651 printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn); 659 pr_info_ratelimited("KVM: invalid SPR read: %d\n", sprn);
652#ifndef DEBUG_SPR 660 if (sprn & 0x10) {
653 emulated = EMULATE_FAIL; 661 if (kvmppc_get_msr(vcpu) & MSR_PR) {
654#endif 662 kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
663 emulated = EMULATE_AGAIN;
664 }
665 } else {
666 if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0 ||
667 sprn == 4 || sprn == 5 || sprn == 6) {
668 kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
669 emulated = EMULATE_AGAIN;
670 }
671 }
672
655 break; 673 break;
656 } 674 }
657 675
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index b379146de55b..c873ffe55362 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -259,10 +259,18 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
259 259
260 case OP_31_XOP_MFSPR: 260 case OP_31_XOP_MFSPR:
261 emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt); 261 emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
262 if (emulated == EMULATE_AGAIN) {
263 emulated = EMULATE_DONE;
264 advance = 0;
265 }
262 break; 266 break;
263 267
264 case OP_31_XOP_MTSPR: 268 case OP_31_XOP_MTSPR:
265 emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs); 269 emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
270 if (emulated == EMULATE_AGAIN) {
271 emulated = EMULATE_DONE;
272 advance = 0;
273 }
266 break; 274 break;
267 275
268 case OP_31_XOP_TLBSYNC: 276 case OP_31_XOP_TLBSYNC: