Commit fef39ccd authored by David Hildenbrand's avatar David Hildenbrand Committed by Richard Henderson
Browse files

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: default avatarRichard Henderson <richard.henderson@linaro.org>
Signed-off-by: default avatarDavid Hildenbrand <david@redhat.com>
Message-Id: <20190830100959.26615-2-david@redhat.com>
Signed-off-by: default avatarRichard Henderson <richard.henderson@linaro.org>
parent 9cd9cdae
Loading
Loading
Loading
Loading
+16 −5
Original line number Diff line number Diff line
@@ -1078,10 +1078,10 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env, target_ulong addr)
/* 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).
 * Otherwise the function will return, and there will be a valid
 * entry in the TLB for this access.
 * 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,
void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
                  uintptr_t retaddr)
{
    uintptr_t index = tlb_index(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);
    }

    if (!size) {
        return NULL;
    }

    /* Handle watchpoints.  */
    if ((tlb_addr & TLB_WATCHPOINT) && size > 0) {
    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);
    }

    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,
+4 −2
Original line number Diff line number Diff line
@@ -188,7 +188,7 @@ 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,
void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
                  uintptr_t retaddr)
{
    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);
        g_assert_not_reached();
    }

    return size ? g2h(addr) : NULL;
}

#if defined(__i386__)
+2 −2
Original line number Diff line number Diff line
@@ -310,7 +310,7 @@ 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,
void *probe_write(CPUArchState *env, target_ulong addr, int size, int mmu_idx,
                  uintptr_t retaddr);

#define CODE_GEN_ALIGN           16 /* must be >= of the size of a icache line */