aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexander Graf <agraf@suse.de>2014-06-20 08:43:36 -0400
committerAlexander Graf <agraf@suse.de>2014-07-28 10:35:53 -0400
commitc12fb43c2f6d6a57a4e21afe74ff56485d699ee7 (patch)
tree4e5b0697bebd43348fa15f116b1c746ef561a9cb
parentc45c551403f0a7b152e56c53735b954faa36c54c (diff)
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>
-rw-r--r--arch/powerpc/include/asm/kvm_book3s.h7
-rw-r--r--arch/powerpc/include/asm/kvm_booke.h10
-rw-r--r--arch/powerpc/kvm/powerpc.c22
3 files changed, 39 insertions, 0 deletions
diff --git a/arch/powerpc/include/asm/kvm_book3s.h b/arch/powerpc/include/asm/kvm_book3s.h
index 172fd6dd2821..61667913ec98 100644
--- a/arch/powerpc/include/asm/kvm_book3s.h
+++ b/arch/powerpc/include/asm/kvm_book3s.h
@@ -286,6 +286,13 @@ static inline bool is_kvmppc_resume_guest(int r)
286 return (r == RESUME_GUEST || r == RESUME_GUEST_NV); 286 return (r == RESUME_GUEST || r == RESUME_GUEST_NV);
287} 287}
288 288
289static inline bool is_kvmppc_hv_enabled(struct kvm *kvm);
290static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
291{
292 /* Only PR KVM supports the magic page */
293 return !is_kvmppc_hv_enabled(vcpu->kvm);
294}
295
289/* Magic register values loaded into r3 and r4 before the 'sc' assembly 296/* Magic register values loaded into r3 and r4 before the 'sc' assembly
290 * instruction for the OSI hypercalls */ 297 * instruction for the OSI hypercalls */
291#define OSI_SC_MAGIC_R3 0x113724FA 298#define OSI_SC_MAGIC_R3 0x113724FA
diff --git a/arch/powerpc/include/asm/kvm_booke.h b/arch/powerpc/include/asm/kvm_booke.h
index cbb19906ca36..f7aa5cc395c4 100644
--- a/arch/powerpc/include/asm/kvm_booke.h
+++ b/arch/powerpc/include/asm/kvm_booke.h
@@ -103,4 +103,14 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
103{ 103{
104 return vcpu->arch.fault_dear; 104 return vcpu->arch.fault_dear;
105} 105}
106
107static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
108{
109 /* Magic page is only supported on e500v2 */
110#ifdef CONFIG_KVM_E500V2
111 return true;
112#else
113 return false;
114#endif
115}
106#endif /* __ASM_KVM_BOOKE_H__ */ 116#endif /* __ASM_KVM_BOOKE_H__ */
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);
312int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, 312int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
313 bool data) 313 bool data)
314{ 314{
315 ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
315 struct kvmppc_pte pte; 316 struct kvmppc_pte pte;
316 int r; 317 int r;
317 318
@@ -327,6 +328,16 @@ int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
327 if (!pte.may_write) 328 if (!pte.may_write)
328 return -EPERM; 329 return -EPERM;
329 330
331 /* Magic page override */
332 if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
333 ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
334 !(kvmppc_get_msr(vcpu) & MSR_PR)) {
335 void *magic = vcpu->arch.shared;
336 magic += pte.eaddr & 0xfff;
337 memcpy(magic, ptr, size);
338 return EMULATE_DONE;
339 }
340
330 if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size)) 341 if (kvm_write_guest(vcpu->kvm, pte.raddr, ptr, size))
331 return EMULATE_DO_MMIO; 342 return EMULATE_DO_MMIO;
332 343
@@ -337,6 +348,7 @@ EXPORT_SYMBOL_GPL(kvmppc_st);
337int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, 348int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
338 bool data) 349 bool data)
339{ 350{
351 ulong mp_pa = vcpu->arch.magic_page_pa & KVM_PAM & PAGE_MASK;
340 struct kvmppc_pte pte; 352 struct kvmppc_pte pte;
341 int rc; 353 int rc;
342 354
@@ -355,6 +367,16 @@ int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
355 if (!data && !pte.may_execute) 367 if (!data && !pte.may_execute)
356 return -ENOEXEC; 368 return -ENOEXEC;
357 369
370 /* Magic page override */
371 if (kvmppc_supports_magic_page(vcpu) && mp_pa &&
372 ((pte.raddr & KVM_PAM & PAGE_MASK) == mp_pa) &&
373 !(kvmppc_get_msr(vcpu) & MSR_PR)) {
374 void *magic = vcpu->arch.shared;
375 magic += pte.eaddr & 0xfff;
376 memcpy(ptr, magic, size);
377 return EMULATE_DONE;
378 }
379
358 if (kvm_read_guest(vcpu->kvm, pte.raddr, ptr, size)) 380 if (kvm_read_guest(vcpu->kvm, pte.raddr, ptr, size))
359 return EMULATE_DO_MMIO; 381 return EMULATE_DO_MMIO;
360 382