[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [PATCH v2 02/16] accel/tcg: Add probe_access_flags
|
From: |
Peter Maydell |
|
Subject: |
Re: [PATCH v2 02/16] accel/tcg: Add probe_access_flags |
|
Date: |
Thu, 16 Apr 2020 12:54:51 +0100 |
On Thu, 12 Mar 2020 at 04:34, Richard Henderson
<address@hidden> 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 <address@hidden>
> ---
> 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
- Re: [PATCH v2 02/16] accel/tcg: Add probe_access_flags,
Peter Maydell <=