From da6bbf8513e621a8fc2fd315d77318f36547474d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 2 Apr 2019 14:37:51 +0700 Subject: tcg: Add CPUClass::tlb_fill MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This hook will replace the (user-only mode specific) handle_mmu_fault hook, and the (system mode specific) tlb_fill function. The handle_mmu_fault hook was written as if there was a valid way to recover from an mmu fault, and had 3 possible return states. In reality, the only valid action is to raise an exception, return to the main loop, and deliver the SIGSEGV to the guest. Note that all of the current implementations of handle_mmu_fault for guests which support linux-user do in fact only ever return 1, which is the signal to return to the main loop. Using the hook for system mode requires that all targets be converted, so for now the hook is (optionally) used only from user-only mode. Reviewed-by: Alistair Francis Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/qom/cpu.h | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'include') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index 08abcbd..c1f267b 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -118,6 +118,12 @@ struct TranslationBlock; * will need to do more. If this hook is not implemented then the * default is to call @set_pc(tb->pc). * @handle_mmu_fault: Callback for handling an MMU fault. + * @tlb_fill: Callback for handling a softmmu tlb miss or user-only + * address fault. For system mode, if the access is valid, call + * tlb_set_page and return true; if the access is invalid, and + * probe is true, return false; otherwise raise an exception and + * do not return. For user-only mode, always raise an exception + * and do not return. * @get_phys_page_debug: Callback for obtaining a physical address. * @get_phys_page_attrs_debug: Callback for obtaining a physical address and the * associated memory transaction attributes to use for the access. @@ -191,6 +197,9 @@ typedef struct CPUClass { void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb); int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int size, int rw, int mmu_index); + bool (*tlb_fill)(CPUState *cpu, vaddr address, int size, + MMUAccessType access_type, int mmu_idx, + bool probe, uintptr_t retaddr); hwaddr (*get_phys_page_debug)(CPUState *cpu, vaddr addr); hwaddr (*get_phys_page_attrs_debug)(CPUState *cpu, vaddr addr, MemTxAttrs *attrs); -- cgit v1.1 From c319dc13579a92937bffe02ad2c9f1a550e73973 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 09:07:11 +0700 Subject: tcg: Use CPUClass::tlb_fill in cputlb.c MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We can now use the CPUClass hook instead of a named function. Create a static tlb_fill function to avoid other changes within cputlb.c. This also isolates the asserts within. Remove the named tlb_fill function from all of the targets. Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/exec/exec-all.h | 9 --------- 1 file changed, 9 deletions(-) (limited to 'include') diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index 58e988b..31f0ecc 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -474,15 +474,6 @@ static inline void assert_no_pages_locked(void) */ struct MemoryRegionSection *iotlb_to_section(CPUState *cpu, hwaddr index, MemTxAttrs attrs); - -/* - * Note: tlb_fill() can trigger a resize of the TLB. This means that all of the - * caller's prior references to the TLB table (e.g. CPUTLBEntry pointers) must - * be discarded and looked up again (e.g. via tlb_entry()). - */ -void tlb_fill(CPUState *cpu, target_ulong addr, int size, - MMUAccessType access_type, int mmu_idx, uintptr_t retaddr); - #endif #if defined(CONFIG_USER_ONLY) -- cgit v1.1 From 69963f5709a0645934c169784820d0bee22208ba Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 10:37:13 +0700 Subject: tcg: Remove CPUClass::handle_mmu_fault MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This hook is now completely replaced by tlb_fill. Reviewed-by: Peter Maydell Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- include/qom/cpu.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include') diff --git a/include/qom/cpu.h b/include/qom/cpu.h index c1f267b..32983f2 100644 --- a/include/qom/cpu.h +++ b/include/qom/cpu.h @@ -117,7 +117,6 @@ struct TranslationBlock; * This always includes at least the program counter; some targets * will need to do more. If this hook is not implemented then the * default is to call @set_pc(tb->pc). - * @handle_mmu_fault: Callback for handling an MMU fault. * @tlb_fill: Callback for handling a softmmu tlb miss or user-only * address fault. For system mode, if the access is valid, call * tlb_set_page and return true; if the access is invalid, and @@ -195,8 +194,6 @@ typedef struct CPUClass { Error **errp); void (*set_pc)(CPUState *cpu, vaddr value); void (*synchronize_from_tb)(CPUState *cpu, struct TranslationBlock *tb); - int (*handle_mmu_fault)(CPUState *cpu, vaddr address, int size, int rw, - int mmu_index); bool (*tlb_fill)(CPUState *cpu, vaddr address, int size, MMUAccessType access_type, int mmu_idx, bool probe, uintptr_t retaddr); -- cgit v1.1 From 4811e9095c0491bc6f5450e5012c9c4796b9e59d Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 3 Apr 2019 10:16:56 +0700 Subject: tcg: Use tlb_fill probe from tlb_vaddr_to_host MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Most of the existing users would continue around a loop which would fault the tlb entry in via a normal load/store. But for AArch64 SVE we have an existing emulation bug wherein we would mark the first element of a no-fault vector load as faulted (within the FFR, not via exception) just because we did not have its address in the TLB. Now we can properly only mark it as faulted if there really is no valid, readable translation, while still not raising an exception. (Note that beyond the first element of the vector, the hardware may report a fault for any reason whatsoever; with at least one element loaded, forward progress is guaranteed.) Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Peter Maydell Signed-off-by: Richard Henderson --- include/exec/cpu_ldst.h | 50 ++++++++++--------------------------------------- 1 file changed, 10 insertions(+), 40 deletions(-) (limited to 'include') diff --git a/include/exec/cpu_ldst.h b/include/exec/cpu_ldst.h index d78041d..7b28a83 100644 --- a/include/exec/cpu_ldst.h +++ b/include/exec/cpu_ldst.h @@ -433,50 +433,20 @@ static inline CPUTLBEntry *tlb_entry(CPUArchState *env, uintptr_t mmu_idx, * @mmu_idx: MMU index to use for lookup * * Look up the specified guest virtual index in the TCG softmmu TLB. - * If the TLB contains a host virtual address suitable for direct RAM - * access, then return it. Otherwise (TLB miss, TLB entry is for an - * I/O access, etc) return NULL. - * - * This is the equivalent of the initial fast-path code used by - * TCG backends for guest load and store accesses. + * If we can translate a host virtual address suitable for direct RAM + * access, without causing a guest exception, then return it. + * Otherwise (TLB entry is for an I/O access, guest software + * TLB fill required, etc) return NULL. */ +#ifdef CONFIG_USER_ONLY static inline void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, - int access_type, int mmu_idx) + MMUAccessType access_type, int mmu_idx) { -#if defined(CONFIG_USER_ONLY) return g2h(addr); -#else - CPUTLBEntry *tlbentry = tlb_entry(env, mmu_idx, addr); - abi_ptr tlb_addr; - uintptr_t haddr; - - switch (access_type) { - case 0: - tlb_addr = tlbentry->addr_read; - break; - case 1: - tlb_addr = tlb_addr_write(tlbentry); - break; - case 2: - tlb_addr = tlbentry->addr_code; - break; - default: - g_assert_not_reached(); - } - - if (!tlb_hit(tlb_addr, addr)) { - /* TLB entry is for a different page */ - return NULL; - } - - if (tlb_addr & ~TARGET_PAGE_MASK) { - /* IO access */ - return NULL; - } - - haddr = addr + tlbentry->addend; - return (void *)haddr; -#endif /* defined(CONFIG_USER_ONLY) */ } +#else +void *tlb_vaddr_to_host(CPUArchState *env, abi_ptr addr, + MMUAccessType access_type, int mmu_idx); +#endif #endif /* CPU_LDST_H */ -- cgit v1.1