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 | |
parent | fef39ccd567032d3ad520ed80f3576068e6eb2e3 (diff) | |
download | qemu-c25c283df0f08582df29f1d5d7be1516b851532d.zip qemu-c25c283df0f08582df29f1d5d7be1516b851532d.tar.gz qemu-c25c283df0f08582df29f1d5d7be1516b851532d.tar.bz2 |
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>
-rw-r--r-- | accel/tcg/cputlb.c | 43 | ||||
-rw-r--r-- | accel/tcg/user-exec.c | 26 | ||||
-rw-r--r-- | include/exec/exec-all.h | 10 |
3 files changed, 60 insertions, 19 deletions
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index cb969d8..abae796 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 5720bf8..71c4bf6 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(); } diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index a7893ed..81b02eb 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -310,8 +310,14 @@ static inline void tlb_flush_by_mmuidx_all_cpus_synced(CPUState *cpu, { } #endif -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); + +static inline void *probe_write(CPUArchState *env, target_ulong addr, int size, + int mmu_idx, uintptr_t retaddr) +{ + return probe_access(env, addr, size, MMU_DATA_STORE, mmu_idx, retaddr); +} #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */ |