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 80 #define TB_JMP_CACHE_BITS 12
81 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 91 #define CPU_TLB_BITS 8
84 92 #define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
85 93  
... ...
exec-all.h
... ... @@ -196,9 +196,19 @@ typedef struct TranslationBlock {
196 196 struct TranslationBlock *jmp_first;
197 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 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 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 1288 tlb_flush_entry(&env->tlb_table[0][i], addr);
1289 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 1299 #if !defined(CONFIG_SOFTMMU)
1301 1300 if (addr < MMAP_AREA_END)
... ...