Commit feafd13c authored by Thomas Huth's avatar Thomas Huth Committed by Paul Mackerras

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: default avatarThomas Huth <thuth@redhat.com>
Signed-off-by: default avatarPaul Mackerras <paulus@ozlabs.org>
parent 121f80ba
......@@ -503,10 +503,18 @@ 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);
emulated = EMULATE_AGAIN;
}
} else {
if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0) {
kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
emulated = EMULATE_AGAIN;
}
}
break;
}
......@@ -648,10 +656,20 @@ 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);
emulated = EMULATE_AGAIN;
}
} else {
if ((kvmppc_get_msr(vcpu) & MSR_PR) || sprn == 0 ||
sprn == 4 || sprn == 5 || sprn == 6) {
kvmppc_core_queue_program(vcpu, SRR1_PROGILL);
emulated = EMULATE_AGAIN;
}
}
break;
}
......
......@@ -259,10 +259,18 @@ int kvmppc_emulate_instruction(struct kvm_run *run, struct kvm_vcpu *vcpu)
case OP_31_XOP_MFSPR:
emulated = kvmppc_emulate_mfspr(vcpu, sprn, rt);
if (emulated == EMULATE_AGAIN) {
emulated = EMULATE_DONE;
advance = 0;
}
break;
case OP_31_XOP_MTSPR:
emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
if (emulated == EMULATE_AGAIN) {
emulated = EMULATE_DONE;
advance = 0;
}
break;
case OP_31_XOP_TLBSYNC:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment