KVM: PPC: Book3S: Make kvmppc_ld return a more accurate error indication
At present, kvmppc_ld calls kvmppc_xlate, and if kvmppc_xlate returns any error indication, it returns -ENOENT, which is taken to mean an HPTE not found error. However, the error could have been a segment found (no SLB entry) or a permission error. Similarly, kvmppc_pte_to_hva currently does permission checking, but any error from it is taken by kvmppc_ld to mean that the access is an emulated MMIO access. Also, kvmppc_ld does no execute permission checking. This fixes these problems by (a) returning any error from kvmppc_xlate directly, (b) moving the permission check from kvmppc_pte_to_hva into kvmppc_ld, and (c) adding an execute permission check to kvmppc_ld. This is similar to what was done for kvmppc_st() by commit 82ff911317c3 ("KVM: PPC: Deflect page write faults properly in kvmppc_st"). Signed-off-by: Paul Mackerras <paulus@samba.org> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
ef1af2e296
commit
1b2e33b071
|
@ -413,17 +413,10 @@ static hva_t kvmppc_bad_hva(void)
|
||||||
return PAGE_OFFSET;
|
return PAGE_OFFSET;
|
||||||
}
|
}
|
||||||
|
|
||||||
static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte,
|
static hva_t kvmppc_pte_to_hva(struct kvm_vcpu *vcpu, struct kvmppc_pte *pte)
|
||||||
bool read)
|
|
||||||
{
|
{
|
||||||
hva_t hpage;
|
hva_t hpage;
|
||||||
|
|
||||||
if (read && !pte->may_read)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
if (!read && !pte->may_write)
|
|
||||||
goto err;
|
|
||||||
|
|
||||||
hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
|
hpage = gfn_to_hva(vcpu->kvm, pte->raddr >> PAGE_SHIFT);
|
||||||
if (kvm_is_error_hva(hpage))
|
if (kvm_is_error_hva(hpage))
|
||||||
goto err;
|
goto err;
|
||||||
|
@ -462,15 +455,23 @@ int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
{
|
{
|
||||||
struct kvmppc_pte pte;
|
struct kvmppc_pte pte;
|
||||||
hva_t hva = *eaddr;
|
hva_t hva = *eaddr;
|
||||||
|
int rc;
|
||||||
|
|
||||||
vcpu->stat.ld++;
|
vcpu->stat.ld++;
|
||||||
|
|
||||||
if (kvmppc_xlate(vcpu, *eaddr, data, false, &pte))
|
rc = kvmppc_xlate(vcpu, *eaddr, data, false, &pte);
|
||||||
goto nopte;
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
*eaddr = pte.raddr;
|
*eaddr = pte.raddr;
|
||||||
|
|
||||||
hva = kvmppc_pte_to_hva(vcpu, &pte, true);
|
if (!pte.may_read)
|
||||||
|
return -EPERM;
|
||||||
|
|
||||||
|
if (!data && !pte.may_execute)
|
||||||
|
return -ENOEXEC;
|
||||||
|
|
||||||
|
hva = kvmppc_pte_to_hva(vcpu, &pte);
|
||||||
if (kvm_is_error_hva(hva))
|
if (kvm_is_error_hva(hva))
|
||||||
goto mmio;
|
goto mmio;
|
||||||
|
|
||||||
|
@ -481,8 +482,6 @@ int kvmppc_ld(struct kvm_vcpu *vcpu, ulong *eaddr, int size, void *ptr,
|
||||||
|
|
||||||
return EMULATE_DONE;
|
return EMULATE_DONE;
|
||||||
|
|
||||||
nopte:
|
|
||||||
return -ENOENT;
|
|
||||||
mmio:
|
mmio:
|
||||||
return EMULATE_DO_MMIO;
|
return EMULATE_DO_MMIO;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue