diff options
author | Alexander Graf <agraf@suse.de> | 2014-06-20 08:43:36 -0400 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-07-28 10:35:53 -0400 |
commit | c12fb43c2f6d6a57a4e21afe74ff56485d699ee7 (patch) | |
tree | 4e5b0697bebd43348fa15f116b1c746ef561a9cb | |
parent | c45c551403f0a7b152e56c53735b954faa36c54c (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.h | 7 | ||||
-rw-r--r-- | arch/powerpc/include/asm/kvm_booke.h | 10 | ||||
-rw-r--r-- | arch/powerpc/kvm/powerpc.c | 22 |
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 | ||
289 | static inline bool is_kvmppc_hv_enabled(struct kvm *kvm); | ||
290 | static 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 | |||
107 | static 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); | |||
312 | int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | 312 | int 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); | |||
337 | int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr, | 348 | int 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 | ||