Commit 4390df510788b6e19cce96db48a94ab2e519e469

Authored by bellard
1 parent ecd854fd

added support for direct patching on i386 host (faster emulation) - increased tr…

…anslation buffer size - added new TLB support


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@517 c046a42c-6fe2-441c-8c8c-71466251a162
Showing 1 changed file with 120 additions and 17 deletions
exec-all.h
... ... @@ -28,6 +28,11 @@
28 28 #define tostring(s) #s
29 29 #endif
30 30  
  31 +#ifndef THUNK_H
  32 +/* horrible */
  33 +typedef uint32_t target_ulong;
  34 +#endif
  35 +
31 36 #if GCC_MAJOR < 3
32 37 #define __builtin_expect(x, n) (x)
33 38 #endif
... ... @@ -77,10 +82,12 @@ int cpu_restore_state(struct TranslationBlock *tb,
77 82 CPUState *env, unsigned long searched_pc);
78 83 void cpu_exec_init(void);
79 84 int page_unprotect(unsigned long address);
80   -void tb_invalidate_page(unsigned long address);
  85 +void tb_invalidate_page_range(target_ulong start, target_ulong end);
81 86 void tlb_flush_page(CPUState *env, uint32_t addr);
82 87 void tlb_flush_page_write(CPUState *env, uint32_t addr);
83 88 void tlb_flush(CPUState *env);
  89 +int tlb_set_page(CPUState *env, uint32_t vaddr, uint32_t paddr, int prot,
  90 + int is_user, int is_softmmu);
84 91  
85 92 #define CODE_GEN_MAX_SIZE 65536
86 93 #define CODE_GEN_ALIGN 16 /* must be >= of the size of a icache line */
... ... @@ -88,11 +95,47 @@ void tlb_flush(CPUState *env);
88 95 #define CODE_GEN_HASH_BITS 15
89 96 #define CODE_GEN_HASH_SIZE (1 << CODE_GEN_HASH_BITS)
90 97  
  98 +#define CODE_GEN_PHYS_HASH_BITS 15
  99 +#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
  100 +
91 101 /* maximum total translate dcode allocated */
92   -#define CODE_GEN_BUFFER_SIZE (2048 * 1024)
  102 +
  103 +/* NOTE: the translated code area cannot be too big because on some
  104 + archs the range of "fast" function calls are limited. Here is a
  105 + summary of the ranges:
  106 +
  107 + i386 : signed 32 bits
  108 + arm : signed 26 bits
  109 + ppc : signed 24 bits
  110 + sparc : signed 32 bits
  111 + alpha : signed 23 bits
  112 +*/
  113 +
  114 +#if defined(__alpha__)
  115 +#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
  116 +#elif defined(__powerpc__)
  117 +#define CODE_GEN_BUFFER_SIZE (6 * 1024)
  118 +#else
  119 +#define CODE_GEN_BUFFER_SIZE (8 * 1024 * 1024)
  120 +#endif
  121 +
93 122 //#define CODE_GEN_BUFFER_SIZE (128 * 1024)
94 123  
95   -#if defined(__powerpc__)
  124 +/* estimated block size for TB allocation */
  125 +/* XXX: use a per code average code fragment size and modulate it
  126 + according to the host CPU */
  127 +#if defined(CONFIG_SOFTMMU)
  128 +#define CODE_GEN_AVG_BLOCK_SIZE 128
  129 +#else
  130 +#define CODE_GEN_AVG_BLOCK_SIZE 64
  131 +#endif
  132 +
  133 +#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
  134 +
  135 +#if defined(__powerpc__)
  136 +#define USE_DIRECT_JUMP
  137 +#endif
  138 +#if defined(__i386__)
96 139 #define USE_DIRECT_JUMP
97 140 #endif
98 141  
... ... @@ -103,8 +146,14 @@ typedef struct TranslationBlock {
103 146 uint16_t size; /* size of target code for this block (1 <=
104 147 size <= TARGET_PAGE_SIZE) */
105 148 uint8_t *tc_ptr; /* pointer to the translated code */
106   - struct TranslationBlock *hash_next; /* next matching block */
107   - struct TranslationBlock *page_next[2]; /* next blocks in even/odd page */
  149 + struct TranslationBlock *hash_next; /* next matching tb for virtual address */
  150 + /* next matching tb for physical address. */
  151 + struct TranslationBlock *phys_hash_next;
  152 + /* first and second physical page containing code. The lower bit
  153 + of the pointer tells the index in page_next[] */
  154 + struct TranslationBlock *page_next[2];
  155 + target_ulong page_addr[2];
  156 +
108 157 /* the following data are used to directly call another TB from
109 158 the code of this one. */
110 159 uint16_t tb_next_offset[2]; /* offset of original jump target */
... ... @@ -126,11 +175,19 @@ static inline unsigned int tb_hash_func(unsigned long pc)
126 175 return pc & (CODE_GEN_HASH_SIZE - 1);
127 176 }
128 177  
  178 +static inline unsigned int tb_phys_hash_func(unsigned long pc)
  179 +{
  180 + return pc & (CODE_GEN_PHYS_HASH_SIZE - 1);
  181 +}
  182 +
129 183 TranslationBlock *tb_alloc(unsigned long pc);
130 184 void tb_flush(CPUState *env);
131 185 void tb_link(TranslationBlock *tb);
  186 +void tb_link_phys(TranslationBlock *tb,
  187 + target_ulong phys_pc, target_ulong phys_page2);
132 188  
133 189 extern TranslationBlock *tb_hash[CODE_GEN_HASH_SIZE];
  190 +extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
134 191  
135 192 extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
136 193 extern uint8_t *code_gen_ptr;
... ... @@ -159,8 +216,10 @@ static inline TranslationBlock *tb_find(TranslationBlock ***pptb,
159 216 return NULL;
160 217 }
161 218  
162   -#if defined(__powerpc__)
163 219  
  220 +#if defined(USE_DIRECT_JUMP)
  221 +
  222 +#if defined(__powerpc__)
164 223 static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
165 224 {
166 225 uint32_t val, *ptr;
... ... @@ -177,6 +236,14 @@ static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr
177 236 asm volatile ("sync" : : : "memory");
178 237 asm volatile ("isync" : : : "memory");
179 238 }
  239 +#elif defined(__i386__)
  240 +static inline void tb_set_jmp_target1(unsigned long jmp_addr, unsigned long addr)
  241 +{
  242 + /* patch the branch destination */
  243 + *(uint32_t *)jmp_addr = addr - (jmp_addr + 4);
  244 + /* no need to flush icache explicitely */
  245 +}
  246 +#endif
180 247  
181 248 static inline void tb_set_jmp_target(TranslationBlock *tb,
182 249 int n, unsigned long addr)
... ... @@ -223,7 +290,7 @@ TranslationBlock *tb_find_pc(unsigned long pc_ptr);
223 290  
224 291 #if defined(__powerpc__)
225 292  
226   -/* on PowerPC we patch the jump instruction directly */
  293 +/* we patch the jump instruction directly */
227 294 #define JUMP_TB(opname, tbparam, n, eip)\
228 295 do {\
229 296 asm volatile (".section \".data\"\n"\
... ... @@ -239,7 +306,28 @@ do {\
239 306  
240 307 #define JUMP_TB2(opname, tbparam, n)\
241 308 do {\
242   - asm volatile ("b __op_jmp%0\n" : : "i" (n + 2));\
  309 + asm volatile ("b __op_jmp" #n "\n");\
  310 +} while (0)
  311 +
  312 +#elif defined(__i386__) && defined(USE_DIRECT_JUMP)
  313 +
  314 +/* we patch the jump instruction directly */
  315 +#define JUMP_TB(opname, tbparam, n, eip)\
  316 +do {\
  317 + asm volatile (".section \".data\"\n"\
  318 + "__op_label" #n "." stringify(opname) ":\n"\
  319 + ".long 1f\n"\
  320 + ".previous\n"\
  321 + "jmp __op_jmp" #n "\n"\
  322 + "1:\n");\
  323 + T0 = (long)(tbparam) + (n);\
  324 + EIP = eip;\
  325 + EXIT_TB();\
  326 +} while (0)
  327 +
  328 +#define JUMP_TB2(opname, tbparam, n)\
  329 +do {\
  330 + asm volatile ("jmp __op_jmp" #n "\n");\
243 331 } while (0)
244 332  
245 333 #else
... ... @@ -261,19 +349,11 @@ dummy_label ## n:\
261 349 /* second jump to same destination 'n' */
262 350 #define JUMP_TB2(opname, tbparam, n)\
263 351 do {\
264   - goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n]);\
  352 + goto *(void *)(((TranslationBlock *)tbparam)->tb_next[n - 2]);\
265 353 } while (0)
266 354  
267 355 #endif
268 356  
269   -/* physical memory access */
270   -#define IO_MEM_NB_ENTRIES 256
271   -#define TLB_INVALID_MASK (1 << 3)
272   -#define IO_MEM_SHIFT 4
273   -#define IO_MEM_UNASSIGNED (1 << IO_MEM_SHIFT)
274   -
275   -unsigned long physpage_find(unsigned long page);
276   -
277 357 extern CPUWriteMemoryFunc *io_mem_write[IO_MEM_NB_ENTRIES][4];
278 358 extern CPUReadMemoryFunc *io_mem_read[IO_MEM_NB_ENTRIES][4];
279 359  
... ... @@ -441,3 +521,26 @@ void tlb_fill(unsigned long addr, int is_write, int is_user,
441 521 #undef env
442 522  
443 523 #endif
  524 +
  525 +#if defined(CONFIG_USER_ONLY)
  526 +static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
  527 +{
  528 + return addr;
  529 +}
  530 +#else
  531 +/* NOTE: this function can trigger an exception */
  532 +/* XXX: i386 target specific */
  533 +static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
  534 +{
  535 + int is_user, index;
  536 +
  537 + index = (addr >> TARGET_PAGE_BITS) & (CPU_TLB_SIZE - 1);
  538 + is_user = ((env->hflags & HF_CPL_MASK) == 3);
  539 + if (__builtin_expect(env->tlb_read[is_user][index].address !=
  540 + (addr & TARGET_PAGE_MASK), 0)) {
  541 + ldub_code((void *)addr);
  542 + }
  543 + return addr + env->tlb_read[is_user][index].addend - (unsigned long)phys_ram_base;
  544 +}
  545 +#endif
  546 +
... ...