summaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kvm
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2014-06-20 14:43:36 +0200
committerAlexander Graf <agraf@suse.de>2014-07-28 16:35:53 +0200
commitc12fb43c2f6d6a57a4e21afe74ff56485d699ee7 (patch)
tree4e5b0697bebd43348fa15f116b1c746ef561a9cb /arch/powerpc/kvm
parentKVM: PPC: Use kvm_read_guest in kvmppc_ld (diff)
downloadlinux-c12fb43c2f6d6a57a4e21afe74ff56485d699ee7.tar.xz
linux-c12fb43c2f6d6a57a4e21afe74ff56485d699ee7.zip
KVM: PPC: Handle magic page in kvmppc_ld/st
We use kvmppc_ld and kvmppc_st to emulate load/store instructions that may as well access the magic page. Special case it out so that we can properly access it. Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'arch/powerpc/kvm')
-rw-r--r--arch/powerpc/kvm/powerpc.c22
1 files changed, 22 insertions, 0 deletions
diff --git a/arch/powerpc/kvm/powerpc.c b/arch/powerpc/kvm/powerpc.c
index be40886e8f0a..544d1d30c8cc 100644
--- a/arch/powerpc/kvm/powerpc.c
+++ b/arch/powerpc/kvm/powerpc.c
@@ -312,6 +312,7 @@ EXPORT_SYMBOL_GPL(kvmppc_emulate_mmio);
int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
bool data)
{
+ ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
struct kvmppc_pte pte;
int r;
@@ -327,6 +328,16 @@ int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
if (!pte.may_write)
return -EPERM;
+ /* Magic page override */
+ if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
+ ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
+ !(kvmppc_get_msr(vcpu) & MSR_PR)) {
+ void *magic = vcpu->arch.shared;
+ magic += pte.eaddr & 0xfff;
+ memcpy(magic, ptr, size);
+ return EMULATE_DONE;
+ }
+
if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
return EMULATE_DO_MMIO;
@@ -337,6 +348,7 @@ EXPORT_SYMBOL_GPL(kvmppc_st);
int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
bool data)
{
+ ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
struct kvmppc_pte pte;
int rc;
@@ -355,6 +367,16 @@ int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
if (!data && !pte.may_execute)
return -ENOEXEC;
+ /* Magic page override */
+ if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
+ ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
+ !(kvmppc_get_msr(vcpu) & MSR_PR)) {
+ void *magic = vcpu->arch.shared;
+ magic += pte.eaddr & 0xfff;
+ memcpy(ptr, magic, size);
+ return EMULATE_DONE;
+ }
+
if (kvm_read_guest(vcpu->kvm, pte.raddr, ptr, size))
return EMULATE_DO_MMIO;