Skip to content

Commit

Permalink
target/i386: Use probe_access_full for final stage2 translation
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
rth7680 authored and bonzini committed Oct 18, 2022
1 parent 4a1e9d4 commit 8629e77
Showing 1 changed file with 28 additions and 14 deletions.
42 changes: 28 additions & 14 deletions target/i386/tcg/sysemu/excp_helper.c
Expand Up @@ -143,7 +143,7 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
.err = err,
.ptw_idx = in->ptw_idx,
};
hwaddr pte_addr;
hwaddr pte_addr, paddr;
uint32_t pkr;
int page_size;

Expand Down Expand Up @@ -420,33 +420,47 @@ static bool mmu_translate(CPUX86State *env, const TranslateParams *in,
}

/* align to page_size */
out->paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
| (addr & (page_size - 1));
paddr = (pte & a20_mask & PG_ADDRESS_MASK & ~(page_size - 1))
| (addr & (page_size - 1));

if (in->ptw_idx == MMU_NESTED_IDX) {
TranslateParams nested_in = {
.addr = out->paddr,
.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)) {
CPUTLBEntryFull *full;
int flags, nested_page_size;

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;
return false;
}

/* Merge stage1 & stage2 protection bits. */
prot &= out->prot;
prot &= full->prot;

/* Re-verify resulting protection. */
if ((prot & (1 << access_type)) == 0) {
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->page_size = page_size;
return true;
Expand Down

0 comments on commit 8629e77

Please sign in to comment.