X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/baea4fae7b6d75ce0d1aeb2be0a223c7be8f4161..a678508e46ac806d81bd401a483aef1b98734ae4:/cputlb.c diff --git a/cputlb.c b/cputlb.c index 343ede2bbb..38f2151166 100644 --- a/cputlb.c +++ b/cputlb.c @@ -22,11 +22,13 @@ #include "exec/exec-all.h" #include "exec/memory.h" #include "exec/address-spaces.h" +#include "exec/cpu_ldst.h" #include "exec/cputlb.h" #include "exec/memory-internal.h" #include "exec/ram_addr.h" +#include "tcg/tcg.h" //#define DEBUG_TLB //#define DEBUG_TLB_CHECK @@ -46,9 +48,9 @@ int tlb_flush_count; * entries from the TLB at any time, so flushing more entries than * required is only an efficiency issue, not a correctness issue. */ -void tlb_flush(CPUArchState *env, int flush_global) +void tlb_flush(CPUState *cpu, int flush_global) { - CPUState *cpu = ENV_GET_CPU(env); + CPUArchState *env = cpu->env_ptr; #if defined(DEBUG_TLB) printf("tlb_flush:\n"); @@ -58,8 +60,10 @@ void tlb_flush(CPUArchState *env, int flush_global) cpu->current_tb = NULL; memset(env->tlb_table, -1, sizeof(env->tlb_table)); + memset(env->tlb_v_table, -1, sizeof(env->tlb_v_table)); memset(cpu->tb_jmp_cache, 0, sizeof(cpu->tb_jmp_cache)); + env->vtlb_index = 0; env->tlb_flush_addr = -1; env->tlb_flush_mask = 0; tlb_flush_count++; @@ -77,9 +81,9 @@ static inline void tlb_flush_entry(CPUTLBEntry *tlb_entry, target_ulong addr) } } -void tlb_flush_page(CPUArchState *env, target_ulong addr) +void tlb_flush_page(CPUState *cpu, target_ulong addr) { - CPUState *cpu = ENV_GET_CPU(env); + CPUArchState *env = cpu->env_ptr; int i; int mmu_idx; @@ -93,7 +97,7 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr) TARGET_FMT_lx "/" TARGET_FMT_lx ")\n", env->tlb_flush_addr, env->tlb_flush_mask); #endif - tlb_flush(env, 1); + tlb_flush(cpu, 1); return; } /* must reset current TB so that interrupts cannot modify the @@ -106,6 +110,14 @@ void tlb_flush_page(CPUArchState *env, target_ulong addr) tlb_flush_entry(&env->tlb_table[mmu_idx][i], addr); } + /* check whether there are entries that need to be flushed in the vtlb */ + for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { + int k; + for (k = 0; k < CPU_VTLB_SIZE; k++) { + tlb_flush_entry(&env->tlb_v_table[mmu_idx][k], addr); + } + } + tb_flush_jmp_cache(cpu, addr); } @@ -170,6 +182,11 @@ void cpu_tlb_reset_dirty_all(ram_addr_t start1, ram_addr_t length) tlb_reset_dirty_range(&env->tlb_table[mmu_idx][i], start1, length); } + + for (i = 0; i < CPU_VTLB_SIZE; i++) { + tlb_reset_dirty_range(&env->tlb_v_table[mmu_idx][i], + start1, length); + } } } } @@ -193,6 +210,13 @@ void tlb_set_dirty(CPUArchState *env, target_ulong vaddr) for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { tlb_set_dirty1(&env->tlb_table[mmu_idx][i], vaddr); } + + for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) { + int k; + for (k = 0; k < CPU_VTLB_SIZE; k++) { + tlb_set_dirty1(&env->tlb_v_table[mmu_idx][k], vaddr); + } + } } /* Our TLB does not support large pages, so remember the area covered by @@ -219,12 +243,17 @@ static void tlb_add_large_page(CPUArchState *env, target_ulong vaddr, } /* Add a new TLB entry. At most one entry for a given virtual address - is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the - supplied size is only used by tlb_flush_page. */ -void tlb_set_page(CPUArchState *env, target_ulong vaddr, + * is permitted. Only a single TARGET_PAGE_SIZE region is mapped, the + * supplied size is only used by tlb_flush_page. + * + * Called from TCG-generated code, which is under an RCU read-side + * critical section. + */ +void tlb_set_page(CPUState *cpu, target_ulong vaddr, hwaddr paddr, int prot, int mmu_idx, target_ulong size) { + CPUArchState *env = cpu->env_ptr; MemoryRegionSection *section; unsigned int index; target_ulong address; @@ -232,7 +261,7 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, uintptr_t addend; CPUTLBEntry *te; hwaddr iotlb, xlat, sz; - CPUState *cpu = ENV_GET_CPU(env); + unsigned vidx = env->vtlb_index++ % CPU_VTLB_SIZE; assert(size >= TARGET_PAGE_SIZE); if (size != TARGET_PAGE_SIZE) { @@ -240,12 +269,12 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, } sz = size; - section = address_space_translate_for_iotlb(cpu->as, paddr, - &xlat, &sz); + section = address_space_translate_for_iotlb(cpu, paddr, &xlat, &sz); assert(sz >= TARGET_PAGE_SIZE); #if defined(DEBUG_TLB) - printf("tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx + qemu_log_mask(CPU_LOG_MMU, + "tlb_set_page: vaddr=" TARGET_FMT_lx " paddr=0x" TARGET_FMT_plx " prot=%x idx=%d\n", vaddr, paddr, prot, mmu_idx); #endif @@ -261,12 +290,18 @@ void tlb_set_page(CPUArchState *env, target_ulong vaddr, } code_address = address; - iotlb = memory_region_section_get_iotlb(env, section, vaddr, paddr, xlat, + iotlb = memory_region_section_get_iotlb(cpu, section, vaddr, paddr, xlat, prot, &address); index = (vaddr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1); - env->iotlb[mmu_idx][index] = iotlb - vaddr; te = &env->tlb_table[mmu_idx][index]; + + /* do not discard the translation in te, evict it into a victim tlb */ + env->tlb_v_table[mmu_idx][vidx] = *te; + env->iotlb_v[mmu_idx][vidx] = env->iotlb[mmu_idx][index]; + + /* refill the tlb */ + env->iotlb[mmu_idx][index] = iotlb - vaddr; te->addend = addend - vaddr; if (prot & PAGE_READ) { te->addr_read = address; @@ -315,14 +350,14 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) cpu_ldub_code(env1, addr); } pd = env1->iotlb[mmu_idx][page_index] & ~TARGET_PAGE_MASK; - mr = iotlb_to_region(cpu->as, pd); + mr = iotlb_to_region(cpu, pd); if (memory_region_is_unassigned(mr)) { CPUClass *cc = CPU_GET_CLASS(cpu); if (cc->do_unassigned_access) { cc->do_unassigned_access(cpu, addr, false, true, 0, 4); } else { - cpu_abort(env1, "Trying to execute code outside RAM or ROM at 0x" + cpu_abort(cpu, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); } } @@ -330,21 +365,36 @@ tb_page_addr_t get_page_addr_code(CPUArchState *env1, target_ulong addr) return qemu_ram_addr_from_host_nofail(p); } +#define MMUSUFFIX _mmu + +#define SHIFT 0 +#include "softmmu_template.h" + +#define SHIFT 1 +#include "softmmu_template.h" + +#define SHIFT 2 +#include "softmmu_template.h" + +#define SHIFT 3 +#include "softmmu_template.h" +#undef MMUSUFFIX + #define MMUSUFFIX _cmmu -#undef GETPC -#define GETPC() ((uintptr_t)0) +#undef GETPC_ADJ +#define GETPC_ADJ 0 +#undef GETRA +#define GETRA() ((uintptr_t)0) #define SOFTMMU_CODE_ACCESS #define SHIFT 0 -#include "exec/softmmu_template.h" +#include "softmmu_template.h" #define SHIFT 1 -#include "exec/softmmu_template.h" +#include "softmmu_template.h" #define SHIFT 2 -#include "exec/softmmu_template.h" +#include "softmmu_template.h" #define SHIFT 3 -#include "exec/softmmu_template.h" - -#undef env +#include "softmmu_template.h"