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>
This commit is contained in:
parent
c45c551403
commit
c12fb43c2f
|
@ -286,6 +286,13 @@ static inline bool is_kvmppc_resume_guest(int r)
|
|||
return (r == RESUME_GUEST || r == RESUME_GUEST_NV);
|
||||
}
|
||||
|
||||
static inline bool is_kvmppc_hv_enabled(struct kvm *kvm);
|
||||
static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/* Only PR KVM supports the magic page */
|
||||
return !is_kvmppc_hv_enabled(vcpu->kvm);
|
||||
}
|
||||
|
||||
/* Magic register values loaded into r3 and r4 before the 'sc' assembly
|
||||
* instruction for the OSI hypercalls */
|
||||
#define OSI_SC_MAGIC_R3 0x113724FA
|
||||
|
|
|
@ -103,4 +103,14 @@ static inline ulong kvmppc_get_fault_dar(struct kvm_vcpu *vcpu)
|
|||
{
|
||||
return vcpu->arch.fault_dear;
|
||||
}
|
||||
|
||||
static inline bool kvmppc_supports_magic_page(struct kvm_vcpu *vcpu)
|
||||
{
|
||||
/* Magic page is only supported on e500v2 */
|
||||
#ifdef CONFIG_KVM_E500V2
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
#endif /* __ASM_KVM_BOOKE_H__ */
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue