aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2011-08-08 10:07:16 -0400
committerAvi Kivity <avi@redhat.com>2011-09-25 12:52:20 -0400
commit317a8fa304f8ba3cd8b67b0f5f38e366e8c3cf1d (patch)
tree874c27833a8dbaddce52f5313c7c6af41143369d /arch/powerpc
parent9432ba6015371f186926cd62e2395718217a17a1 (diff)
KVM: PPC: Check privilege level on SPRs
We have 3 privilege levels: problem state, supervisor state and hypervisor state. Each of them can access different SPRs, so we need to check on every SPR if it's accessible in the respective mode. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kvm/book3s_emulate.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/book3s_emulate.c b/arch/powerpc/kvm/book3s_emulate.c
index 466846557089..bf0ddcd98bcc 100644
--- a/arch/powerpc/kvm/book3s_emulate.c
+++ b/arch/powerpc/kvm/book3s_emulate.c
@@ -63,6 +63,25 @@
63 * function pointers, so let's just disable the define. */ 63 * function pointers, so let's just disable the define. */
64#undef mfsrin 64#undef mfsrin
65 65
66enum priv_level {
67 PRIV_PROBLEM = 0,
68 PRIV_SUPER = 1,
69 PRIV_HYPER = 2,
70};
71
72static bool spr_allowed(struct kvm_vcpu *vcpu, enum priv_level level)
73{
74 /* PAPR VMs only access supervisor SPRs */
75 if (vcpu->arch.papr_enabled && (level > PRIV_SUPER))
76 return false;
77
78 /* Limit user space to its own small SPR set */
79 if ((vcpu->arch.shared->msr & MSR_PR) && level > PRIV_PROBLEM)
80 return false;
81
82 return true;
83}
84
66int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu, 85int kvmppc_core_emulate_op(struct kvm_run *run, struct kvm_vcpu *vcpu,
67 unsigned int inst, int *advance) 86 unsigned int inst, int *advance)
68{ 87{
@@ -296,6 +315,8 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
296 315
297 switch (sprn) { 316 switch (sprn) {
298 case SPRN_SDR1: 317 case SPRN_SDR1:
318 if (!spr_allowed(vcpu, PRIV_HYPER))
319 goto unprivileged;
299 to_book3s(vcpu)->sdr1 = spr_val; 320 to_book3s(vcpu)->sdr1 = spr_val;
300 break; 321 break;
301 case SPRN_DSISR: 322 case SPRN_DSISR:
@@ -390,6 +411,7 @@ int kvmppc_core_emulate_mtspr(struct kvm_vcpu *vcpu, int sprn, int rs)
390 case SPRN_PMC4_GEKKO: 411 case SPRN_PMC4_GEKKO:
391 case SPRN_WPAR_GEKKO: 412 case SPRN_WPAR_GEKKO:
392 break; 413 break;
414unprivileged:
393 default: 415 default:
394 printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn); 416 printk(KERN_INFO "KVM: invalid SPR write: %d\n", sprn);
395#ifndef DEBUG_SPR 417#ifndef DEBUG_SPR
@@ -421,6 +443,8 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
421 break; 443 break;
422 } 444 }
423 case SPRN_SDR1: 445 case SPRN_SDR1:
446 if (!spr_allowed(vcpu, PRIV_HYPER))
447 goto unprivileged;
424 kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1); 448 kvmppc_set_gpr(vcpu, rt, to_book3s(vcpu)->sdr1);
425 break; 449 break;
426 case SPRN_DSISR: 450 case SPRN_DSISR:
@@ -476,6 +500,7 @@ int kvmppc_core_emulate_mfspr(struct kvm_vcpu *vcpu, int sprn, int rt)
476 kvmppc_set_gpr(vcpu, rt, 0); 500 kvmppc_set_gpr(vcpu, rt, 0);
477 break; 501 break;
478 default: 502 default:
503unprivileged:
479 printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn); 504 printk(KERN_INFO "KVM: invalid SPR read: %d\n", sprn);
480#ifndef DEBUG_SPR 505#ifndef DEBUG_SPR
481 emulated = EMULATE_FAIL; 506 emulated = EMULATE_FAIL;