Commit 26a5f13b8eb1281d0552fe323e869806f3cefbfb
1 parent
bed5cc52
variable dynamic translation buffer size
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4600 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
88 additions
and
54 deletions
cpu-all.h
... | ... | @@ -767,6 +767,7 @@ int page_get_flags(target_ulong address); |
767 | 767 | void page_set_flags(target_ulong start, target_ulong end, int flags); |
768 | 768 | int page_check_range(target_ulong start, target_ulong len, int flags); |
769 | 769 | |
770 | +void cpu_exec_init_all(unsigned long tb_size); | |
770 | 771 | CPUState *cpu_copy(CPUState *env); |
771 | 772 | |
772 | 773 | void cpu_dump_state(CPUState *env, FILE *f, | ... | ... |
darwin-user/main.c
exec-all.h
... | ... | @@ -56,12 +56,6 @@ typedef void (GenOpFunc1)(long); |
56 | 56 | typedef void (GenOpFunc2)(long, long); |
57 | 57 | typedef void (GenOpFunc3)(long, long, long); |
58 | 58 | |
59 | -#if defined(TARGET_I386) | |
60 | - | |
61 | -void optimize_flags_init(void); | |
62 | - | |
63 | -#endif | |
64 | - | |
65 | 59 | extern FILE *logfile; |
66 | 60 | extern int loglevel; |
67 | 61 | |
... | ... | @@ -105,31 +99,7 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, |
105 | 99 | #define CODE_GEN_PHYS_HASH_BITS 15 |
106 | 100 | #define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS) |
107 | 101 | |
108 | -/* maximum total translate dcode allocated */ | |
109 | - | |
110 | -/* NOTE: the translated code area cannot be too big because on some | |
111 | - archs the range of "fast" function calls is limited. Here is a | |
112 | - summary of the ranges: | |
113 | - | |
114 | - i386 : signed 32 bits | |
115 | - arm : signed 26 bits | |
116 | - ppc : signed 24 bits | |
117 | - sparc : signed 32 bits | |
118 | - alpha : signed 23 bits | |
119 | -*/ | |
120 | - | |
121 | -#if defined(__alpha__) | |
122 | -#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024) | |
123 | -#elif defined(__ia64) | |
124 | -#define CODE_GEN_BUFFER_SIZE (4 * 1024 * 1024) /* range of addl */ | |
125 | -#elif defined(__powerpc__) | |
126 | -#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024) | |
127 | -#else | |
128 | -/* XXX: make it dynamic on x86 */ | |
129 | -#define CODE_GEN_BUFFER_SIZE (64 * 1024 * 1024) | |
130 | -#endif | |
131 | - | |
132 | -//#define CODE_GEN_BUFFER_SIZE (128 * 1024) | |
102 | +#define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024) | |
133 | 103 | |
134 | 104 | /* estimated block size for TB allocation */ |
135 | 105 | /* XXX: use a per code average code fragment size and modulate it |
... | ... | @@ -140,8 +110,6 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, |
140 | 110 | #define CODE_GEN_AVG_BLOCK_SIZE 64 |
141 | 111 | #endif |
142 | 112 | |
143 | -#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE) | |
144 | - | |
145 | 113 | #if defined(__powerpc__) || defined(__x86_64__) || defined(__arm__) |
146 | 114 | #define USE_DIRECT_JUMP |
147 | 115 | #endif |
... | ... | @@ -210,9 +178,8 @@ void tb_link_phys(TranslationBlock *tb, |
210 | 178 | target_ulong phys_pc, target_ulong phys_page2); |
211 | 179 | |
212 | 180 | extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; |
213 | - | |
214 | -extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE]; | |
215 | 181 | extern uint8_t *code_gen_ptr; |
182 | +extern int code_gen_max_blocks; | |
216 | 183 | |
217 | 184 | #if defined(USE_DIRECT_JUMP) |
218 | 185 | ... | ... |
exec.c
... | ... | @@ -58,9 +58,6 @@ |
58 | 58 | #undef DEBUG_TB_CHECK |
59 | 59 | #endif |
60 | 60 | |
61 | -/* threshold to flush the translated code buffer */ | |
62 | -#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - code_gen_max_block_size()) | |
63 | - | |
64 | 61 | #define SMC_BITMAP_USE_THRESHOLD 10 |
65 | 62 | |
66 | 63 | #define MMAP_AREA_START 0x00000000 |
... | ... | @@ -85,13 +82,17 @@ |
85 | 82 | #endif |
86 | 83 | |
87 | 84 | TranslationBlock *tbs; |
85 | +int code_gen_max_blocks; | |
88 | 86 | TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; |
89 | 87 | int nb_tbs; |
90 | 88 | /* any access to the tbs or the page table must use this lock */ |
91 | 89 | spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; |
92 | 90 | |
93 | 91 | uint8_t code_gen_prologue[1024] __attribute__((aligned (32))); |
94 | -uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE] __attribute__((aligned (32))); | |
92 | +uint8_t *code_gen_buffer; | |
93 | +unsigned long code_gen_buffer_size; | |
94 | +/* threshold to flush the translated code buffer */ | |
95 | +unsigned long code_gen_buffer_max_size; | |
95 | 96 | uint8_t *code_gen_ptr; |
96 | 97 | |
97 | 98 | ram_addr_t phys_ram_size; |
... | ... | @@ -215,9 +216,6 @@ static void page_init(void) |
215 | 216 | #else |
216 | 217 | qemu_real_host_page_size = getpagesize(); |
217 | 218 | #endif |
218 | - map_exec(code_gen_buffer, sizeof(code_gen_buffer)); | |
219 | - map_exec(code_gen_prologue, sizeof(code_gen_prologue)); | |
220 | - | |
221 | 219 | if (qemu_host_page_size == 0) |
222 | 220 | qemu_host_page_size = qemu_real_host_page_size; |
223 | 221 | if (qemu_host_page_size < TARGET_PAGE_SIZE) |
... | ... | @@ -328,18 +326,67 @@ static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, |
328 | 326 | target_ulong vaddr); |
329 | 327 | #endif |
330 | 328 | |
329 | +void code_gen_alloc(unsigned long tb_size) | |
330 | +{ | |
331 | + code_gen_buffer_size = tb_size; | |
332 | + if (code_gen_buffer_size == 0) { | |
333 | + /* XXX: needs ajustments */ | |
334 | + code_gen_buffer_size = (int)(phys_ram_size / 4); | |
335 | + } | |
336 | + if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE) | |
337 | + code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE; | |
338 | + /* The code gen buffer location may have constraints depending on | |
339 | + the host cpu and OS */ | |
340 | +#if defined(__linux__) | |
341 | + { | |
342 | + int flags; | |
343 | + flags = MAP_PRIVATE | MAP_ANONYMOUS; | |
344 | +#if defined(__x86_64__) | |
345 | + flags |= MAP_32BIT; | |
346 | + /* Cannot map more than that */ | |
347 | + if (code_gen_buffer_size > (800 * 1024 * 1024)) | |
348 | + code_gen_buffer_size = (800 * 1024 * 1024); | |
349 | +#endif | |
350 | + code_gen_buffer = mmap(NULL, code_gen_buffer_size, | |
351 | + PROT_WRITE | PROT_READ | PROT_EXEC, | |
352 | + flags, -1, 0); | |
353 | + if (code_gen_buffer == MAP_FAILED) { | |
354 | + fprintf(stderr, "Could not allocate dynamic translator buffer\n"); | |
355 | + exit(1); | |
356 | + } | |
357 | + } | |
358 | +#else | |
359 | + code_gen_buffer = qemu_malloc(code_gen_buffer_size); | |
360 | + if (!code_gen_buffer) { | |
361 | + fprintf(stderr, "Could not allocate dynamic translator buffer\n"); | |
362 | + exit(1); | |
363 | + } | |
364 | + map_exec(code_gen_buffer, code_gen_buffer_size); | |
365 | +#endif | |
366 | + map_exec(code_gen_prologue, sizeof(code_gen_prologue)); | |
367 | + code_gen_buffer_max_size = code_gen_buffer_size - | |
368 | + code_gen_max_block_size(); | |
369 | + code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE; | |
370 | + tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock)); | |
371 | +} | |
372 | + | |
373 | +/* Must be called before using the QEMU cpus. 'tb_size' is the size | |
374 | + (in bytes) allocated to the translation buffer. Zero means default | |
375 | + size. */ | |
376 | +void cpu_exec_init_all(unsigned long tb_size) | |
377 | +{ | |
378 | + page_init(); | |
379 | + cpu_gen_init(); | |
380 | + code_gen_alloc(tb_size); | |
381 | + code_gen_ptr = code_gen_buffer; | |
382 | + io_mem_init(); | |
383 | +} | |
384 | + | |
331 | 385 | void cpu_exec_init(CPUState *env) |
332 | 386 | { |
333 | 387 | CPUState **penv; |
334 | 388 | int cpu_index; |
335 | 389 | |
336 | - if (!code_gen_ptr) { | |
337 | - cpu_gen_init(); | |
338 | - tbs = qemu_malloc(CODE_GEN_MAX_BLOCKS * sizeof(TranslationBlock)); | |
339 | - code_gen_ptr = code_gen_buffer; | |
340 | - page_init(); | |
341 | - io_mem_init(); | |
342 | - } | |
343 | 390 | env->next_cpu = NULL; |
344 | 391 | penv = &first_cpu; |
345 | 392 | cpu_index = 0; |
... | ... | @@ -390,7 +437,7 @@ void tb_flush(CPUState *env1) |
390 | 437 | nb_tbs, nb_tbs > 0 ? |
391 | 438 | ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); |
392 | 439 | #endif |
393 | - if ((unsigned long)(code_gen_ptr - code_gen_buffer) > CODE_GEN_BUFFER_SIZE) | |
440 | + if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size) | |
394 | 441 | cpu_abort(env1, "Internal error: code buffer overflow\n"); |
395 | 442 | |
396 | 443 | nb_tbs = 0; |
... | ... | @@ -960,8 +1007,8 @@ TranslationBlock *tb_alloc(target_ulong pc) |
960 | 1007 | { |
961 | 1008 | TranslationBlock *tb; |
962 | 1009 | |
963 | - if (nb_tbs >= CODE_GEN_MAX_BLOCKS || | |
964 | - (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE) | |
1010 | + if (nb_tbs >= code_gen_max_blocks || | |
1011 | + (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size) | |
965 | 1012 | return NULL; |
966 | 1013 | tb = &tbs[nb_tbs++]; |
967 | 1014 | tb->pc = pc; |
... | ... | @@ -2990,7 +3037,10 @@ void dump_exec_info(FILE *f, |
2990 | 3037 | } |
2991 | 3038 | /* XXX: avoid using doubles ? */ |
2992 | 3039 | cpu_fprintf(f, "Translation buffer state:\n"); |
2993 | - cpu_fprintf(f, "TB count %d\n", nb_tbs); | |
3040 | + cpu_fprintf(f, "gen code size %ld/%ld\n", | |
3041 | + code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size); | |
3042 | + cpu_fprintf(f, "TB count %d/%d\n", | |
3043 | + nb_tbs, code_gen_max_blocks); | |
2994 | 3044 | cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", |
2995 | 3045 | nb_tbs ? target_code_size / nb_tbs : 0, |
2996 | 3046 | max_target_code_size); | ... | ... |
linux-user/main.c
target-i386/cpu.h
... | ... | @@ -723,6 +723,8 @@ static inline int cpu_mmu_index (CPUState *env) |
723 | 723 | return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; |
724 | 724 | } |
725 | 725 | |
726 | +void optimize_flags_init(void); | |
727 | + | |
726 | 728 | typedef struct CCTable { |
727 | 729 | int (*compute_all)(void); /* return all the flags */ |
728 | 730 | int (*compute_c)(void); /* return the C flag */ | ... | ... |
vl.c
... | ... | @@ -7378,6 +7378,7 @@ enum { |
7378 | 7378 | QEMU_OPTION_old_param, |
7379 | 7379 | QEMU_OPTION_clock, |
7380 | 7380 | QEMU_OPTION_startdate, |
7381 | + QEMU_OPTION_tb_size, | |
7381 | 7382 | }; |
7382 | 7383 | |
7383 | 7384 | typedef struct QEMUOption { |
... | ... | @@ -7489,6 +7490,7 @@ const QEMUOption qemu_options[] = { |
7489 | 7490 | #endif |
7490 | 7491 | { "clock", HAS_ARG, QEMU_OPTION_clock }, |
7491 | 7492 | { "startdate", HAS_ARG, QEMU_OPTION_startdate }, |
7493 | + { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, | |
7492 | 7494 | { NULL }, |
7493 | 7495 | }; |
7494 | 7496 | |
... | ... | @@ -7697,6 +7699,7 @@ int main(int argc, char **argv) |
7697 | 7699 | const char *usb_devices[MAX_USB_CMDLINE]; |
7698 | 7700 | int usb_devices_index; |
7699 | 7701 | int fds[2]; |
7702 | + int tb_size; | |
7700 | 7703 | const char *pid_file = NULL; |
7701 | 7704 | VLANState *vlan; |
7702 | 7705 | |
... | ... | @@ -7768,8 +7771,9 @@ int main(int argc, char **argv) |
7768 | 7771 | hda_index = -1; |
7769 | 7772 | |
7770 | 7773 | nb_nics = 0; |
7771 | - /* default mac address of the first network interface */ | |
7772 | 7774 | |
7775 | + tb_size = 0; | |
7776 | + | |
7773 | 7777 | optind = 1; |
7774 | 7778 | for(;;) { |
7775 | 7779 | if (optind >= argc) |
... | ... | @@ -8296,6 +8300,11 @@ int main(int argc, char **argv) |
8296 | 8300 | } |
8297 | 8301 | } |
8298 | 8302 | break; |
8303 | + case QEMU_OPTION_tb_size: | |
8304 | + tb_size = strtol(optarg, NULL, 0); | |
8305 | + if (tb_size < 0) | |
8306 | + tb_size = 0; | |
8307 | + break; | |
8299 | 8308 | } |
8300 | 8309 | } |
8301 | 8310 | } |
... | ... | @@ -8467,6 +8476,9 @@ int main(int argc, char **argv) |
8467 | 8476 | exit(1); |
8468 | 8477 | } |
8469 | 8478 | |
8479 | + /* init the dynamic translator */ | |
8480 | + cpu_exec_init_all(tb_size * 1024 * 1024); | |
8481 | + | |
8470 | 8482 | bdrv_init(); |
8471 | 8483 | |
8472 | 8484 | /* we always create the cdrom drive, even if no disk is there */ | ... | ... |