diff options
author | David Hildenbrand <david@redhat.com> | 2019-08-30 12:09:59 +0200 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2019-09-03 08:34:18 -0700 |
commit | c25c283df0f08582df29f1d5d7be1516b851532d (patch) | |
tree | a97749340e002d6831e6a56051f399c95f85410d /accel | |
parent | fef39ccd567032d3ad520ed80f3576068e6eb2e3 (diff) |
tcg: Factor out probe_write() logic into probe_access()
Let's also allow to probe other access types.
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Hildenbrand <david@redhat.com>
Message-Id: <20190830100959.26615-3-david@redhat.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'accel')
-rw-r--r-- | accel/tcg/cputlb.c | 43 | ||||
-rw-r--r-- | accel/tcg/user-exec.c | 26 |
2 files changed, 52 insertions, 17 deletions
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index cb969d8372..abae79650c 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1075,30 +1075,51 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr) return qemu_ram_addr_from_host_nofail(p); } -/* Probe for whether the specified guest write access is permitted. - * 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). +/* + * Probe for whether the specified guest access is permitted. If it is not + * permitted then an exception will be taken in the same way as if this + * were a real access (and we will not return). * If the size is 0 or the page requires I/O access, returns NULL; otherwise, * 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, - uintptr_t retaddr) +void *probe_access(CPUArchState *env, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { uintptr_t index = tlb_index(env, mmu_idx, addr); CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); - target_ulong tlb_addr = tlb_addr_write(entry); + target_ulong tlb_addr; + size_t elt_ofs; + int wp_access; g_assert(-(addr | TARGET_PAGE_MASK) >= size); + switch (access_type) { + case MMU_DATA_LOAD: + elt_ofs = offsetof(CPUTLBEntry, addr_read); + wp_access = BP_MEM_READ; + break; + case MMU_DATA_STORE: + elt_ofs = offsetof(CPUTLBEntry, addr_write); + wp_access = BP_MEM_WRITE; + break; + case MMU_INST_FETCH: + elt_ofs = offsetof(CPUTLBEntry, addr_code); + wp_access = BP_MEM_READ; + break; + default: + g_assert_not_reached(); + } + tlb_addr = tlb_read_ofs(entry, elt_ofs); + if (unlikely(!tlb_hit(tlb_addr, addr))) { - if (!VICTIM_TLB_HIT(addr_write, addr)) { - tlb_fill(env_cpu(env), addr, size, MMU_DATA_STORE, - mmu_idx, retaddr); + if (!victim_tlb_hit(env, mmu_idx, index, elt_ofs, + addr & TARGET_PAGE_MASK)) { + tlb_fill(env_cpu(env), addr, size, access_type, mmu_idx, retaddr); /* TLB resize via tlb_fill may have moved the entry. */ index = tlb_index(env, mmu_idx, addr); entry = tlb_entry(env, mmu_idx, addr); } - tlb_addr = tlb_addr_write(entry); + tlb_addr = tlb_read_ofs(entry, elt_ofs); } if (!size) { @@ -1109,7 +1130,7 @@ void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx, if (tlb_addr & TLB_WATCHPOINT) { cpu_check_watchpoint(env_cpu(env), addr, size, env_tlb(env)->d[mmu_idx].iotlb[index].attrs, - BP_MEM_WRITE, retaddr); + wp_access, retaddr); } if (tlb_addr & (TLB_NOTDIRTY | TLB_MMIO)) { diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c index 5720bf8056..71c4bf6477 100644 --- a/accel/tcg/user-exec.c +++ b/accel/tcg/user-exec.c @@ -188,17 +188,31 @@ static inline int handle_cpu_signal(uintptr_t pc, siginfo_t *info, g_assert_not_reached(); } -void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx, - uintptr_t retaddr) +void *probe_access(CPUArchState *env, target_ulong addr, int size, + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) { + int flags; + g_assert(-(addr | TARGET_PAGE_MASK) >= size); - if (!guest_addr_valid(addr) || - page_check_range(addr, size, PAGE_WRITE) < 0) { + switch (access_type) { + case MMU_DATA_STORE: + flags = PAGE_WRITE; + break; + case MMU_DATA_LOAD: + flags = PAGE_READ; + break; + case MMU_INST_FETCH: + flags = PAGE_EXEC; + break; + default: + g_assert_not_reached(); + } + + if (!guest_addr_valid(addr) || page_check_range(addr, size, flags) < 0) { CPUState *cpu = env_cpu(env); CPUClass *cc = CPU_GET_CLASS(cpu); - - cc->tlb_fill(cpu, addr, size, MMU_DATA_STORE, MMU_USER_IDX, false, + cc->tlb_fill(cpu, addr, size, access_type, MMU_USER_IDX, false, retaddr); g_assert_not_reached(); } |