mirror of https://github.com/xemu-project/xemu.git
target/i386: Use probe_access_full for final stage2 translation
Rather than recurse directly on mmu_translate, go through the same softmmu lookup that we did for the page table walk. This centralizes all knowledge of MMU_NESTED_IDX, with respect to setup of TranslationParams, to get_physical_address. Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20221002172956.265735-10-richard.henderson@linaro.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
4a1e9d4d11
commit
8629e77be5
|
@ -143,7 +143,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
|
||||||
.err = err,
|
.err = err,
|
||||||
.ptw_idx = in->ptw_idx,
|
.ptw_idx = in->ptw_idx,
|
||||||
};
|
};
|
||||||
hwaddr pte_addr;
|
hwaddr pte_addr, paddr;
|
||||||
uint32_t pkr;
|
uint32_t pkr;
|
||||||
int page_size;
|
int page_size;
|
||||||
|
|
||||||
|
@ -420,33 +420,47 @@ do_check_protect_pse36:
|
||||||
}
|
}
|
||||||
|
|
||||||
/* align to page_size */
|
/* align to page_size */
|
||||||
out->paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
|
paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
|
||||||
| (addr & (page_size - 1));
|
| (addr & (page_size - 1));
|
||||||
|
|
||||||
if (in->ptw_idx == MMU_NESTED_IDX) {
|
if (in->ptw_idx == MMU_NESTED_IDX) {
|
||||||
TranslateParams nested_in = {
|
CPUTLBEntryFull *full;
|
||||||
.addr = out->paddr,
|
int flags, nested_page_size;
|
||||||
.access_type = access_type,
|
|
||||||
.cr3 = env->nested_cr3,
|
|
||||||
.pg_mode = env->nested_pg_mode,
|
|
||||||
.mmu_idx = MMU_USER_IDX,
|
|
||||||
.ptw_idx = MMU_PHYS_IDX,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (!mmu_translate(env, &nested_in, out, err)) {
|
flags = probe_access_full(env, paddr, access_type,
|
||||||
|
MMU_NESTED_IDX, true,
|
||||||
|
&pte_trans.haddr, &full, 0);
|
||||||
|
if (unlikely(flags & TLB_INVALID_MASK)) {
|
||||||
|
err->exception_index = 0; /* unused */
|
||||||
|
err->error_code = env->error_code;
|
||||||
|
err->cr2 = paddr;
|
||||||
err->stage2 = S2_GPA;
|
err->stage2 = S2_GPA;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Merge stage1 & stage2 protection bits. */
|
/* Merge stage1 & stage2 protection bits. */
|
||||||
prot &= out->prot;
|
prot &= full->prot;
|
||||||
|
|
||||||
/* Re-verify resulting protection. */
|
/* Re-verify resulting protection. */
|
||||||
if ((prot & (1 << access_type)) == 0) {
|
if ((prot & (1 << access_type)) == 0) {
|
||||||
goto do_fault_protect;
|
goto do_fault_protect;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Merge stage1 & stage2 addresses to final physical address. */
|
||||||
|
nested_page_size = 1 << full->lg_page_size;
|
||||||
|
paddr = (full->phys_addr & ~(nested_page_size - 1))
|
||||||
|
| (paddr & (nested_page_size - 1));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Use the larger of stage1 & stage2 page sizes, so that
|
||||||
|
* invalidation works.
|
||||||
|
*/
|
||||||
|
if (nested_page_size > page_size) {
|
||||||
|
page_size = nested_page_size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out->paddr = paddr;
|
||||||
out->prot = prot;
|
out->prot = prot;
|
||||||
out->page_size = page_size;
|
out->page_size = page_size;
|
||||||
return true;
|
return true;
|
||||||
|
|
Loading…
Reference in New Issue