diff options
author | Paul Mackerras <paulus@samba.org> | 2014-04-14 19:52:26 +1000 |
---|---|---|
committer | Wang Sen <wangsen@linux.vnet.ibm.com> | 2014-04-16 11:15:21 +0800 |
commit | a758d7ee38f23bfb828f7e0abf470ca68191fe5c (patch) | |
tree | 0fb3eb03e532caeff1530478d30fd57df22bb6e1 | |
parent | 6c71c41f52f9b763f52c333b781d939e9fbdba5f (diff) | |
download | powerkvm-a758d7ee38f23bfb828f7e0abf470ca68191fe5c.tar.gz |
KVM: PPC: Book3S PR: Unimplemented SPRs in supervisor mode don't cause trap
The Power ISA states that an mtspr or mfspr to/from an unimplemented
SPR should be a no-op in privileged mode, rather than causing an
program interrupt (0x700 vector), with the exception of mtspr to SPR 0
and mfspr from SPRs 0, 4, 5 or 6.
Currently our SPR emulation code doesn't follow this rule. This
modifies the code in kvmppc_core_emulate_m[ft]spr_pr() to check
the PR bit in the MSR when we detect an unknown SPR number, and
only return EMULATE_FAIL (which results in a program interrupt)
if PR is 0 or the SPR number is one of the ones which are specifically
defined to cause a program interrupt.
Signed-off-by: Paul Mackerras <paulus@samba.org>
-rw-r--r-- | arch/powerpc/kvm/book3s_emulate.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c index f2f63c2304ff8..1829c0da44538 100644 --- a/arch/powerpc/kvm/book3s_emulate.c +++ b/arch/powerpc/kvm/book3s_emulate.c @@ -455,16 +455,18 @@ int kvmppc_core_emulate_mtspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong spr_val) case SPRN_WPAR_GEKKO: case SPRN_MSSSR0: break; -unprivileged: default: - printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn); -#ifndef DEBUG_SPR - emulated = EMULATE_FAIL; -#endif + if ((vcpu->arch.shared->msr & MSR_PR) || !sprn) + goto unprivileged; break; } return emulated; + +unprivileged: + /* really want to do priv vs. illegal program interrupt */ + printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn); + return EMULATE_FAIL; } int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val) @@ -554,15 +556,18 @@ int kvmppc_core_emulate_mfspr_pr(struct kvm_vcpu *vcpu, int sprn, ulong *spr_val *spr_val = 0; break; default: -unprivileged: - printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn); -#ifndef DEBUG_SPR - emulated = EMULATE_FAIL; -#endif + if ((vcpu->arch.shared->msr & MSR_PR) || sprn == 0 || + sprn == 4 || sprn == 5 || sprn == 6) + goto unprivileged; break; } return emulated; + +unprivileged: + /* really want to do priv vs. illegal program interrupt */ + printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn); + return EMULATE_FAIL; } u32 kvmppc_alignment_dsisr(struct kvm_vcpu *vcpu, unsigned int inst) |