Speed up tlb_flush_page (Daniel Jacobowitz).
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2210 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
d08b2a28e6
commit
b362e5e067
@ -80,6 +80,14 @@ typedef unsigned long ram_addr_t;
|
||||
#define TB_JMP_CACHE_BITS 12
|
||||
#define TB_JMP_CACHE_SIZE (1 << TB_JMP_CACHE_BITS)
|
||||
|
||||
/* Only the bottom TB_JMP_PAGE_BITS of the jump cache hash bits vary for
|
||||
addresses on the same page. The top bits are the same. This allows
|
||||
TLB invalidation to quickly clear a subset of the hash table. */
|
||||
#define TB_JMP_PAGE_BITS (TB_JMP_CACHE_BITS / 2)
|
||||
#define TB_JMP_PAGE_SIZE (1 << TB_JMP_PAGE_BITS)
|
||||
#define TB_JMP_ADDR_MASK (TB_JMP_PAGE_SIZE - 1)
|
||||
#define TB_JMP_PAGE_MASK (TB_JMP_CACHE_SIZE - TB_JMP_PAGE_SIZE)
|
||||
|
||||
#define CPU_TLB_BITS 8
|
||||
#define CPU_TLB_SIZE (1 << CPU_TLB_BITS)
|
||||
|
||||
|
12
exec-all.h
12
exec-all.h
@ -196,9 +196,19 @@ typedef struct TranslationBlock {
|
||||
struct TranslationBlock *jmp_first;
|
||||
} TranslationBlock;
|
||||
|
||||
static inline unsigned int tb_jmp_cache_hash_page(target_ulong pc)
|
||||
{
|
||||
target_ulong tmp;
|
||||
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
||||
return (tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK;
|
||||
}
|
||||
|
||||
static inline unsigned int tb_jmp_cache_hash_func(target_ulong pc)
|
||||
{
|
||||
return (pc ^ (pc >> TB_JMP_CACHE_BITS)) & (TB_JMP_CACHE_SIZE - 1);
|
||||
target_ulong tmp;
|
||||
tmp = pc ^ (pc >> (TARGET_PAGE_BITS - TB_JMP_PAGE_BITS));
|
||||
return (((tmp >> TB_JMP_PAGE_BITS) & TB_JMP_PAGE_MASK) |
|
||||
(tmp & TB_JMP_ADDR_MASK));
|
||||
}
|
||||
|
||||
static inline unsigned int tb_phys_hash_func(unsigned long pc)
|
||||
|
15
exec.c
15
exec.c
@ -1288,14 +1288,13 @@ void tlb_flush_page(CPUState *env, target_ulong addr)
|
||||
tlb_flush_entry(&env->tlb_table[0][i], addr);
|
||||
tlb_flush_entry(&env->tlb_table[1][i], addr);
|
||||
|
||||
for(i = 0; i < TB_JMP_CACHE_SIZE; i++) {
|
||||
tb = env->tb_jmp_cache[i];
|
||||
if (tb &&
|
||||
((tb->pc & TARGET_PAGE_MASK) == addr ||
|
||||
((tb->pc + tb->size - 1) & TARGET_PAGE_MASK) == addr)) {
|
||||
env->tb_jmp_cache[i] = NULL;
|
||||
}
|
||||
}
|
||||
/* Discard jump cache entries for any tb which might potentially
|
||||
overlap the flushed page. */
|
||||
i = tb_jmp_cache_hash_page(addr - TARGET_PAGE_SIZE);
|
||||
memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
|
||||
|
||||
i = tb_jmp_cache_hash_page(addr);
|
||||
memset (&env->tb_jmp_cache[i], 0, TB_JMP_PAGE_SIZE * sizeof(tb));
|
||||
|
||||
#if !defined(CONFIG_SOFTMMU)
|
||||
if (addr < MMAP_AREA_END)
|
||||
|
Loading…
Reference in New Issue
Block a user