diff mbox

KVM: PPC: Book3S PR: Do not fail emulation with mtspr/mfspr for unknown SPRs

Message ID 1491218595-10943-1-git-send-email-thuth@redhat.com (mailing list archive)
State New, archived
Headers show

Commit Message

Thomas Huth April 3, 2017, 11:23 a.m. UTC
According to the PowerISA 2.07, mtspr and mfspr should not generate
an illegal instruction exception when being used with an undefined SPR,
but rather treat the instruction as a NOP, inject a privilege exception
or an emulation assistance exception - 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>
---
 arch/powerpc/kvm/book3s.c         |  1 +
 arch/powerpc/kvm/book3s_emulate.c | 30 ++++++++++++++++++++++--------
 2 files changed, 23 insertions(+), 8 deletions(-)

Comments

Paul Mackerras April 4, 2017, 6:25 a.m. UTC | #1
On Mon, Apr 03, 2017 at 01:23:15PM +0200, Thomas Huth wrote:
> According to the PowerISA 2.07, mtspr and mfspr should not generate
> an illegal instruction exception when being used with an undefined SPR,
> but rather treat the instruction as a NOP, inject a privilege exception
> or an emulation assistance exception - depending on the SPR number.

The emulation assist interrupt is a hypervisor interrupt, so the guest
would not be expecting to receive it.  On a real machine, the
hypervisor would synthesize an illegal instruction type program
interrupt as described in the last programming note in section 6.5.9
of Book III of Power ISA v2.07B.  Since we are the hypervisor here, we
should synthesize a program interrupt rather than an emulation assist
interrupt.

> 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.

Good idea.

Paul.
Thomas Huth April 4, 2017, 8 a.m. UTC | #2
On 04.04.2017 08:25, Paul Mackerras wrote:
> On Mon, Apr 03, 2017 at 01:23:15PM +0200, Thomas Huth wrote:
>> According to the PowerISA 2.07, mtspr and mfspr should not generate
>> an illegal instruction exception when being used with an undefined SPR,
>> but rather treat the instruction as a NOP, inject a privilege exception
>> or an emulation assistance exception - depending on the SPR number.
> 
> The emulation assist interrupt is a hypervisor interrupt, so the guest
> would not be expecting to receive it.  On a real machine, the
> hypervisor would synthesize an illegal instruction type program
> interrupt as described in the last programming note in section 6.5.9
> of Book III of Power ISA v2.07B.  Since we are the hypervisor here, we
> should synthesize a program interrupt rather than an emulation assist
> interrupt.

Ah, right, we're doing this in other spots, too, so a PROGILL is indeed
more consistent here. I'll send a v2 ...

 Thomas
diff mbox

Patch

diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index b6b5c18..9b007f9 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -137,6 +137,7 @@  void kvmppc_inject_interrupt(struct kvm_vcpu *vcpu, int vec, u64 flags)
 	kvmppc_set_pc(vcpu, kvmppc_interrupt_offset(vcpu) + vec);
 	vcpu->arch.mmu.reset_msr(vcpu);
 }
+EXPORT_SYMBOL_GPL(kvmppc_inject_interrupt);
 
 static int kvmppc_book3s_vec2irqprio(unsigned int vec)
 {
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 8359752..9c31e23 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -503,10 +503,16 @@  int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val)
 		break;
 unprivileged:
 	default:
-		printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
-#ifndef DEBUG_SPR
-		emulated = EMULATE_FAIL;
-#endif
+		pr_info_ratelimited("KVM: invalid SPR write: %d\n", sprn);
+		if (sprn & 0x10) {
+			if (kvmppc_get_msr(vcpu) & MSR_PR)
+				kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
+		} else {
+			if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0)
+				kvmppc_inject_interrupt(vcpu,
+						BOOK3S_INTERRUPT_H_EMUL_ASSIST,
+						0);
+		}
 		break;
 	}
 
@@ -648,10 +654,18 @@  int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val
 		break;
 	default:
 unprivileged:
-		printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
-#ifndef DEBUG_SPR
-		emulated = EMULATE_FAIL;
-#endif
+		pr_info_ratelimited("KVM: invalid SPR read: %d\n", sprn);
+		if (sprn & 0x10) {
+			if (kvmppc_get_msr(vcpu) & MSR_PR)
+				kvmppc_core_queue_program(vcpu, SRR1_PROGPRIV);
+		} else {
+			if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0 ||
+			    sprn == 4 || sprn == 5 || sprn == 6)
+				kvmppc_inject_interrupt(vcpu,
+						BOOK3S_INTERRUPT_H_EMUL_ASSIST,
+						0);
+		}
+
 		break;
 	}