tcg: Make probe_write() return a pointer to the host page

... similar to tlb_vaddr_to_host(); however, allow access to the host
page except when TLB_NOTDIRTY or TLB_MMIO is set.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190830100959.26615-2-david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
David Hildenbrand 2019-08-30 12:09:58 +02:00 committed by Richard Henderson
parent 9cd9cdaefc
commit fef39ccd56
3 changed files with 22 additions and 9 deletions

View File

@ -1078,11 +1078,11 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
/* Probe for whether the specified guest write access is permitted. /* Probe for whether the specified guest write access is permitted.
* If it is not permitted then an exception will be taken in the same * If it is not permitted then an exception will be taken in the same
* way as if this were a real write access (and we will not return). * way as if this were a real write access (and we will not return).
* Otherwise the function will return, and there will be a valid * If the size is 0 or the page requires I/O access, returns NULL; otherwise,
* entry in the TLB for this access. * returns the address of the host page similar to tlb_vaddr_to_host().
*/ */
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx, void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
uintptr_t retaddr) 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);
@ -1101,12 +1101,23 @@ void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
tlb_addr = tlb_addr_write(entry); tlb_addr = tlb_addr_write(entry);
} }
if (!size) {
return NULL;
}
/* Handle watchpoints. */ /* Handle watchpoints. */
if ((tlb_addr & TLB_WATCHPOINT) && size > 0) { if (tlb_addr & TLB_WATCHPOINT) {
cpu_check_watchpoint(env_cpu(env), addr, size, cpu_check_watchpoint(env_cpu(env), addr, size,
env_tlb(env)->d[mmu_idx].iotlb[index].attrs, env_tlb(env)->d[mmu_idx].iotlb[index].attrs,
BP_MEM_WRITE, retaddr); BP_MEM_WRITE, retaddr);
} }
if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO)) {
/* I/O access */
return NULL;
}
return (void *)((uintptr_t)addr + entry->addend);
} }
void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr,

View File

@ -188,8 +188,8 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info,
g_assert_not_reached(); g_assert_not_reached();
} }
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx, void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
uintptr_t retaddr) uintptr_t retaddr)
{ {
g_assert(-(addr | TARGET_PAGE_MASK) >= size); g_assert(-(addr | TARGET_PAGE_MASK) >= size);
@ -202,6 +202,8 @@ void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
retaddr); retaddr);
g_assert_not_reached(); g_assert_not_reached();
} }
return size ? g2h(addr) : NULL;
} }
#if defined(__i386__) #if defined(__i386__)

View File

@ -310,8 +310,8 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu,
{ {
} }
#endif #endif
void probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx, void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
uintptr_t retaddr); uintptr_t retaddr);
#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 */