accel/tcg: Introduce probe_access_full
Add an interface to return the CPUTLBEntryFull struct that goes with the lookup. The result is not intended to be valid across multiple lookups, so the user must use the results immediately. Reviewed-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
c3c8bf579b
commit
af803a4fcb
@ -1510,7 +1510,8 @@ static void notdirty_write(CPUState *cpu, vaddr mem_vaddr, unsigned size,
|
|||||||
static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
||||||
int fault_size, MMUAccessType access_type,
|
int fault_size, MMUAccessType access_type,
|
||||||
int mmu_idx, bool nonfault,
|
int mmu_idx, bool nonfault,
|
||||||
void **phost, uintptr_t retaddr)
|
void **phost, CPUTLBEntryFull **pfull,
|
||||||
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
||||||
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
|
CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
|
||||||
@ -1543,10 +1544,12 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
|||||||
mmu_idx, nonfault, retaddr)) {
|
mmu_idx, nonfault, retaddr)) {
|
||||||
/* Non-faulting page table read failed. */
|
/* Non-faulting page table read failed. */
|
||||||
*phost = NULL;
|
*phost = NULL;
|
||||||
|
*pfull = NULL;
|
||||||
return TLB_INVALID_MASK;
|
return TLB_INVALID_MASK;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* TLB resize via tlb_fill may have moved the entry. */
|
/* TLB resize via tlb_fill may have moved the entry. */
|
||||||
|
index = tlb_index(env, mmu_idx, addr);
|
||||||
entry = tlb_entry(env, mmu_idx, addr);
|
entry = tlb_entry(env, mmu_idx, addr);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1560,6 +1563,8 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
|||||||
}
|
}
|
||||||
flags &= tlb_addr;
|
flags &= tlb_addr;
|
||||||
|
|
||||||
|
*pfull = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
||||||
|
|
||||||
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
|
/* Fold all "mmio-like" bits into TLB_MMIO. This is not RAM. */
|
||||||
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) {
|
if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY))) {
|
||||||
*phost = NULL;
|
*phost = NULL;
|
||||||
@ -1571,37 +1576,44 @@ static int probe_access_internal(CPUArchState *env, target_ulong addr,
|
|||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
int probe_access_flags(CPUArchState *env, target_ulong addr,
|
int probe_access_full(CPUArchState *env, target_ulong addr,
|
||||||
MMUAccessType access_type, int mmu_idx,
|
MMUAccessType access_type, int mmu_idx,
|
||||||
bool nonfault, void **phost, uintptr_t retaddr)
|
bool nonfault, void **phost, CPUTLBEntryFull **pfull,
|
||||||
|
uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
int flags;
|
int flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
|
||||||
|
nonfault, phost, pfull, retaddr);
|
||||||
flags = probe_access_internal(env, addr, 0, access_type, mmu_idx,
|
|
||||||
nonfault, phost, retaddr);
|
|
||||||
|
|
||||||
/* Handle clean RAM pages. */
|
/* Handle clean RAM pages. */
|
||||||
if (unlikely(flags & TLB_NOTDIRTY)) {
|
if (unlikely(flags & TLB_NOTDIRTY)) {
|
||||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
notdirty_write(env_cpu(env), addr, 1, *pfull, retaddr);
|
||||||
CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
|
||||||
|
|
||||||
notdirty_write(env_cpu(env), addr, 1, full, retaddr);
|
|
||||||
flags &= ~TLB_NOTDIRTY;
|
flags &= ~TLB_NOTDIRTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
return flags;
|
return flags;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int probe_access_flags(CPUArchState *env, target_ulong addr,
|
||||||
|
MMUAccessType access_type, int mmu_idx,
|
||||||
|
bool nonfault, void **phost, uintptr_t retaddr)
|
||||||
|
{
|
||||||
|
CPUTLBEntryFull *full;
|
||||||
|
|
||||||
|
return probe_access_full(env, addr, access_type, mmu_idx,
|
||||||
|
nonfault, phost, &full, retaddr);
|
||||||
|
}
|
||||||
|
|
||||||
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
||||||
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
MMUAccessType access_type, int mmu_idx, uintptr_t retaddr)
|
||||||
{
|
{
|
||||||
|
CPUTLBEntryFull *full;
|
||||||
void *host;
|
void *host;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
g_assert(-(addr | TARGET_PAGE_MASK) >= size);
|
g_assert(-(addr | TARGET_PAGE_MASK) >= size);
|
||||||
|
|
||||||
flags = probe_access_internal(env, addr, size, access_type, mmu_idx,
|
flags = probe_access_internal(env, addr, size, access_type, mmu_idx,
|
||||||
false, &host, retaddr);
|
false, &host, &full, retaddr);
|
||||||
|
|
||||||
/* Per the interface, size == 0 merely faults the access. */
|
/* Per the interface, size == 0 merely faults the access. */
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
@ -1609,9 +1621,6 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
|
if (unlikely(flags & (TLB_NOTDIRTY | TLB_WATCHPOINT))) {
|
||||||
uintptr_t index = tlb_index(env, mmu_idx, addr);
|
|
||||||
CPUTLBEntryFull *full = &env_tlb(env)->d[mmu_idx].fulltlb[index];
|
|
||||||
|
|
||||||
/* Handle watchpoints. */
|
/* Handle watchpoints. */
|
||||||
if (flags & TLB_WATCHPOINT) {
|
if (flags & TLB_WATCHPOINT) {
|
||||||
int wp_access = (access_type == MMU_DATA_STORE
|
int wp_access = (access_type == MMU_DATA_STORE
|
||||||
@ -1632,11 +1641,12 @@ void *probe_access(CPUArchState *env, target_ulong addr, int size,
|
|||||||
void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
|
void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
|
||||||
MMUAccessType access_type, int mmu_idx)
|
MMUAccessType access_type, int mmu_idx)
|
||||||
{
|
{
|
||||||
|
CPUTLBEntryFull *full;
|
||||||
void *host;
|
void *host;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
flags = probe_access_internal(env, addr, 0, access_type,
|
flags = probe_access_internal(env, addr, 0, access_type,
|
||||||
mmu_idx, true, &host, 0);
|
mmu_idx, true, &host, &full, 0);
|
||||||
|
|
||||||
/* No combination of flags are expected by the caller. */
|
/* No combination of flags are expected by the caller. */
|
||||||
return flags ? NULL : host;
|
return flags ? NULL : host;
|
||||||
@ -1655,10 +1665,11 @@ void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,
|
|||||||
tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
|
tb_page_addr_t get_page_addr_code_hostp(CPUArchState *env, target_ulong addr,
|
||||||
void **hostp)
|
void **hostp)
|
||||||
{
|
{
|
||||||
|
CPUTLBEntryFull *full;
|
||||||
void *p;
|
void *p;
|
||||||
|
|
||||||
(void)probe_access_internal(env, addr, 1, MMU_INST_FETCH,
|
(void)probe_access_internal(env, addr, 1, MMU_INST_FETCH,
|
||||||
cpu_mmu_index(env, true), false, &p, 0);
|
cpu_mmu_index(env, true), false, &p, &full, 0);
|
||||||
if (p == NULL) {
|
if (p == NULL) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -434,6 +434,21 @@ int probe_access_flags(CPUArchState *env, target_ulong addr,
|
|||||||
MMUAccessType access_type, int mmu_idx,
|
MMUAccessType access_type, int mmu_idx,
|
||||||
bool nonfault, void **phost, uintptr_t retaddr);
|
bool nonfault, void **phost, uintptr_t retaddr);
|
||||||
|
|
||||||
|
#ifndef CONFIG_USER_ONLY
|
||||||
|
/**
|
||||||
|
* probe_access_full:
|
||||||
|
* Like probe_access_flags, except also return into @pfull.
|
||||||
|
*
|
||||||
|
* The CPUTLBEntryFull structure returned via @pfull is transient
|
||||||
|
* and must be consumed or copied immediately, before any further
|
||||||
|
* access or changes to TLB @mmu_idx.
|
||||||
|
*/
|
||||||
|
int probe_access_full(CPUArchState *env, target_ulong addr,
|
||||||
|
MMUAccessType access_type, int mmu_idx,
|
||||||
|
bool nonfault, void **phost,
|
||||||
|
CPUTLBEntryFull **pfull, uintptr_t retaddr);
|
||||||
|
#endif
|
||||||
|
|
||||||
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
#define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
|
||||||
|
|
||||||
/* Estimated block size for TB allocation. */
|
/* Estimated block size for TB allocation. */
|
||||||
|
@ -42,6 +42,7 @@ typedef struct ConfidentialGuestSupport ConfidentialGuestSupport;
|
|||||||
typedef struct CPUAddressSpace CPUAddressSpace;
|
typedef struct CPUAddressSpace CPUAddressSpace;
|
||||||
typedef struct CPUArchState CPUArchState;
|
typedef struct CPUArchState CPUArchState;
|
||||||
typedef struct CPUState CPUState;
|
typedef struct CPUState CPUState;
|
||||||
|
typedef struct CPUTLBEntryFull CPUTLBEntryFull;
|
||||||
typedef struct DeviceListener DeviceListener;
|
typedef struct DeviceListener DeviceListener;
|
||||||
typedef struct DeviceState DeviceState;
|
typedef struct DeviceState DeviceState;
|
||||||
typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
|
typedef struct DirtyBitmapSnapshot DirtyBitmapSnapshot;
|
||||||
|
Loading…
Reference in New Issue
Block a user