Commit b362e5e067835d04ddde5fb1277272d4b498b970

Authored by pbrook
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
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)
@@ -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)