KVM: PPC: Implement kvmppc_xlate for all targets
We have a nice API to find the translated GPAs of a GVA including protection flags. So far we only use it on Book3S, but there's no reason the same shouldn't be used on BookE as well. Implement a kvmppc_xlate() version for BookE and clean it up to make it more readable in general. Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
63fff5c1e3
commit
7d15c06f1a
|
@ -52,6 +52,16 @@ enum instruction_type {
|
||||||
INST_SC, /* system call */
|
INST_SC, /* system call */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum xlate_instdata {
|
||||||
|
XLATE_INST, /* translate instruction address */
|
||||||
|
XLATE_DATA /* translate data address */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum xlate_readwrite {
|
||||||
|
XLATE_READ, /* check for read permissions */
|
||||||
|
XLATE_WRITE /* check for write permissions */
|
||||||
|
};
|
||||||
|
|
||||||
extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
extern int kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
||||||
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
extern int __kvmppc_vcpu_run(struct kvm_run *kvm_run, struct kvm_vcpu *vcpu);
|
||||||
extern void kvmppc_handler_highmem(void);
|
extern void kvmppc_handler_highmem(void);
|
||||||
|
@ -94,6 +104,9 @@ extern gpa_t kvmppc_mmu_xlate(struct kvm_vcpu *vcpu, unsigned int gtlb_index,
|
||||||
gva_t eaddr);
|
gva_t eaddr);
|
||||||
extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu);
|
extern void kvmppc_mmu_dtlb_miss(struct kvm_vcpu *vcpu);
|
||||||
extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu);
|
extern void kvmppc_mmu_itlb_miss(struct kvm_vcpu *vcpu);
|
||||||
|
extern int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr,
|
||||||
|
enum xlate_instdata xlid, enum xlate_readwrite xlrw,
|
||||||
|
struct kvmppc_pte *pte);
|
||||||
|
|
||||||
extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm,
|
extern struct kvm_vcpu *kvmppc_core_vcpu_create(struct kvm *kvm,
|
||||||
unsigned int id);
|
unsigned int id);
|
||||||
|
|
|
@ -380,9 +380,11 @@ pfn_t kvmppc_gpa_to_pfn(struct kvm_vcpu *vcpu, gpa_t gpa, bool writing,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(kvmppc_gpa_to_pfn);
|
EXPORT_SYMBOL_GPL(kvmppc_gpa_to_pfn);
|
||||||
|
|
||||||
static int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, bool data,
|
int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
|
||||||
bool iswrite, struct kvmppc_pte *pte)
|
enum xlate_readwrite xlrw, struct kvmppc_pte *pte)
|
||||||
{
|
{
|
||||||
|
bool data = (xlid == XLATE_DATA);
|
||||||
|
bool iswrite = (xlrw == XLATE_WRITE);
|
||||||
int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR));
|
int relocated = (kvmppc_get_msr(vcpu) & (data ? MSR_DR : MSR_IR));
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
@ -434,7 +436,8 @@ int kvmppc_st(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
|
||||||
vcpu->stat.st++;
|
vcpu->stat.st++;
|
||||||
|
|
||||||
r = kvmppc_xlate(vcpu, *eaddr, data, true, &pte);
|
r = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
|
||||||
|
XLATE_WRITE, &pte);
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -459,7 +462,8 @@ int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
|
||||||
vcpu->stat.ld++;
|
vcpu->stat.ld++;
|
||||||
|
|
||||||
rc = kvmppc_xlate(vcpu, *eaddr, data, false, &pte);
|
rc = kvmppc_xlate(vcpu, *eaddr, data ? XLATE_DATA : XLATE_INST,
|
||||||
|
XLATE_READ, &pte);
|
||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
|
|
|
@ -1785,6 +1785,57 @@ void kvm_guest_protect_msr(struct kvm_vcpu *vcpu, ulong prot_bitmap, bool set)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int kvmppc_xlate(struct kvm_vcpu *vcpu, ulong eaddr, enum xlate_instdata xlid,
|
||||||
|
enum xlate_readwrite xlrw, struct kvmppc_pte *pte)
|
||||||
|
{
|
||||||
|
int gtlb_index;
|
||||||
|
gpa_t gpaddr;
|
||||||
|
|
||||||
|
#ifdef CONFIG_KVM_E500V2
|
||||||
|
if (!(vcpu->arch.shared->msr & MSR_PR) &&
|
||||||
|
(eaddr & PAGE_MASK) == vcpu->arch.magic_page_ea) {
|
||||||
|
pte->eaddr = eaddr;
|
||||||
|
pte->raddr = (vcpu->arch.magic_page_pa & PAGE_MASK) |
|
||||||
|
(eaddr & ~PAGE_MASK);
|
||||||
|
pte->vpage = eaddr >> PAGE_SHIFT;
|
||||||
|
pte->may_read = true;
|
||||||
|
pte->may_write = true;
|
||||||
|
pte->may_execute = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Check the guest TLB. */
|
||||||
|
switch (xlid) {
|
||||||
|
case XLATE_INST:
|
||||||
|
gtlb_index = kvmppc_mmu_itlb_index(vcpu, eaddr);
|
||||||
|
break;
|
||||||
|
case XLATE_DATA:
|
||||||
|
gtlb_index = kvmppc_mmu_dtlb_index(vcpu, eaddr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Do we have a TLB entry at all? */
|
||||||
|
if (gtlb_index < 0)
|
||||||
|
return -ENOENT;
|
||||||
|
|
||||||
|
gpaddr = kvmppc_mmu_xlate(vcpu, gtlb_index, eaddr);
|
||||||
|
|
||||||
|
pte->eaddr = eaddr;
|
||||||
|
pte->raddr = (gpaddr & PAGE_MASK) | (eaddr & ~PAGE_MASK);
|
||||||
|
pte->vpage = eaddr >> PAGE_SHIFT;
|
||||||
|
|
||||||
|
/* XXX read permissions from the guest TLB */
|
||||||
|
pte->may_read = true;
|
||||||
|
pte->may_write = true;
|
||||||
|
pte->may_execute = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
|
int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
|
||||||
struct kvm_guest_debug *dbg)
|
struct kvm_guest_debug *dbg)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue