On Thu, 12 Mar 2020 at 04:34, Richard Henderson <richard.hender...@linaro.org> wrote: > > This new interface will allow targets to probe for a page > and then handle watchpoints themselves. This will be most > useful for vector predicated memory operations, where one > page lookup can be used for many operations, and one test > can avoid many watchpoint checks. > > Signed-off-by: Richard Henderson <richard.hender...@linaro.org> > --- > v2: Fix return of host pointer in softmmu probe_access_flags. > ---
> diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c > index e3b5750c3b..bbe265ce28 100644 > --- a/accel/tcg/cputlb.c > +++ b/accel/tcg/cputlb.c > @@ -1231,86 +1231,16 @@ static void notdirty_write(CPUState *cpu, vaddr > mem_vaddr, unsigned size, > } > } > > -/* > - * 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_access(CPUArchState *env, target_ulong addr, int size, > - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) > +static int probe_access_internal(CPUArchState *env, target_ulong addr, > + int fault_size, MMUAccessType access_type, > + int mmu_idx, bool nonfault, > + void **phost, uintptr_t retaddr) > { > uintptr_t index = tlb_index(env, mmu_idx, addr); > CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr); > - 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(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_read_ofs(entry, elt_ofs); > - } All of the code above seems to have disappeared in this refactoring -- it's not in probe_access_internal() but it hasn't moved to the new probe_access(). > diff --git a/accel/tcg/user-exec.c b/accel/tcg/user-exec.c > index 4be78eb9b3..c52dd8a95a 100644 > --- a/accel/tcg/user-exec.c > +++ b/accel/tcg/user-exec.c > @@ -190,13 +190,12 @@ static inline int handle_cpu_signal(uintptr_t pc, > siginfo_t *info, > g_assert_not_reached(); > } > > -void *probe_access(CPUArchState *env, target_ulong addr, int size, > - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) > +int probe_access_flags(CPUArchState *env, target_ulong addr, > + MMUAccessType access_type, int mmu_idx, > + bool nonfault, void **phost, uintptr_t retaddr) > { > int flags; > > - g_assert(-(addr | TARGET_PAGE_MASK) >= size); > - > switch (access_type) { > case MMU_DATA_STORE: > flags = PAGE_WRITE; > @@ -211,15 +210,30 @@ void *probe_access(CPUArchState *env, target_ulong > addr, int size, > 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, access_type, MMU_USER_IDX, false, > - retaddr); > - g_assert_not_reached(); > + if (!guest_addr_valid(addr) || page_check_range(addr, 1, flags) < 0) { > + if (nonfault) { > + *phost = NULL; > + return TLB_INVALID_MASK; > + } else { > + CPUState *cpu = env_cpu(env); > + CPUClass *cc = CPU_GET_CLASS(cpu); > + cc->tlb_fill(cpu, addr, 0, access_type, MMU_USER_IDX, false, > retaddr); > + g_assert_not_reached(); > + } > } > > - return size ? g2h(addr) : NULL; > + *phost = g2h(addr); > + return 0; > +} > + > +void *probe_access(CPUArchState *env, target_ulong addr, int size, > + MMUAccessType access_type, int mmu_idx, uintptr_t retaddr) > +{ > + void *host; > + > + g_assert(-(addr | TARGET_PAGE_MASK) >= size); > + probe_access_flags(env, addr, access_type, mmu_idx, false, &host, > retaddr); > + return host; > } probe_access() used to pass the 'size' argument through to page_check_range() and cc->tlb_fill(); after this refactoring it no longer does that. thanks -- PMM