Commit b362e5e067835d04ddde5fb1277272d4b498b970
1 parent
d08b2a28
Speed up tlb_flush_page (Daniel Jacobowitz).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2210 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
3 changed files
with
26 additions
and
9 deletions
cpu-defs.h
| @@ -80,6 +80,14 @@ typedef unsigned long ram_addr_t; | @@ -80,6 +80,14 @@ typedef unsigned long ram_addr_t; | ||
| 80 | #define TB_JMP_CACHE_BITS 12 | 80 | #define TB_JMP_CACHE_BITS 12 |
| 81 | #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) | 81 | #define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS) |
| 82 | 82 | ||
| 83 | +/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for | ||
| 84 | + addresses on the same page. The top bits are the same. This allows | ||
| 85 | + TLB invalidation to quickly clear a subset of the hash table. */ | ||
| 86 | +#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2) | ||
| 87 | +#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS) | ||
| 88 | +#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1) | ||
| 89 | +#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE) | ||
| 90 | + | ||
| 83 | #define CPU_TLB_BITS 8 | 91 | #define CPU_TLB_BITS 8 |
| 84 | #define CPU_TLB_SIZE (1 << CPU_TLB_BITS) | 92 | #define CPU_TLB_SIZE (1 << CPU_TLB_BITS) |
| 85 | 93 |
exec-all.h
| @@ -196,9 +196,19 @@ typedef struct TranslationBlock { | @@ -196,9 +196,19 @@ typedef struct TranslationBlock { | ||
| 196 | struct TranslationBlock *jmp_first; | 196 | struct TranslationBlock *jmp_first; |
| 197 | } TranslationBlock; | 197 | } TranslationBlock; |
| 198 | 198 | ||
| 199 | +static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc) | ||
| 200 | +{ | ||
| 201 | + target_ulong tmp; | ||
| 202 | + tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)); | ||
| 203 | + return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK; | ||
| 204 | +} | ||
| 205 | + | ||
| 199 | static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc) | 206 | static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc) |
| 200 | { | 207 | { |
| 201 | - return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1); | 208 | + target_ulong tmp; |
| 209 | + tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS)); | ||
| 210 | + return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) | | ||
| 211 | + (tmp & TB_JMP_ADDR_MASK)); | ||
| 202 | } | 212 | } |
| 203 | 213 | ||
| 204 | static inline unsigned int tb_phys_hash_func(unsigned long pc) | 214 | static inline unsigned int tb_phys_hash_func(unsigned long pc) |
exec.c
| @@ -1288,14 +1288,13 @@ void tlb_flush_page(CPUState *env, target_ulong addr) | @@ -1288,14 +1288,13 @@ void tlb_flush_page(CPUState *env, target_ulong addr) | ||
| 1288 | tlb_flush_entry(&env->tlb_table[0][i], addr); | 1288 | tlb_flush_entry(&env->tlb_table[0][i], addr); |
| 1289 | tlb_flush_entry(&env->tlb_table[1][i], addr); | 1289 | tlb_flush_entry(&env->tlb_table[1][i], addr); |
| 1290 | 1290 | ||
| 1291 | - for(i = 0; i < TB_JMP_CACHE_SIZE; i++) { | ||
| 1292 | - tb = env->tb_jmp_cache[i]; | ||
| 1293 | - if (tb && | ||
| 1294 | - ((tb->pc & TARGET_PAGE_MASK) == addr || | ||
| 1295 | - ((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr)) { | ||
| 1296 | - env->tb_jmp_cache[i] = NULL; | ||
| 1297 | - } | ||
| 1298 | - } | 1291 | + /* Discard jump cache entries for any tb which might potentially |
| 1292 | + overlap the flushed page. */ | ||
| 1293 | + i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE); | ||
| 1294 | + memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb)); | ||
| 1295 | + | ||
| 1296 | + i = tb_jmp_cache_hash_page(addr); | ||
| 1297 | + memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb)); | ||
| 1299 | 1298 | ||
| 1300 | #if !defined(CONFIG_SOFTMMU) | 1299 | #if !defined(CONFIG_SOFTMMU) |
| 1301 | if (addr < MMAP_AREA_END) | 1300 | if (addr < MMAP_AREA_END) |