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,6 +767,7 @@ int page_get_flags(target_ulong address); | ||
767 | void page_set_flags(target_ulong start, target_ulong end, int flags); | 767 | void page_set_flags(target_ulong start, target_ulong end, int flags); |
768 | int page_check_range(target_ulong start, target_ulong len, int flags); | 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 | CPUState *cpu_copy(CPUState *env); | 771 | CPUState *cpu_copy(CPUState *env); |
771 | 772 | ||
772 | void cpu_dump_state(CPUState *env, FILE *f, | 773 | void cpu_dump_state(CPUState *env, FILE *f, |
darwin-user/main.c
@@ -873,6 +873,7 @@ int main(int argc, char **argv) | @@ -873,6 +873,7 @@ int main(int argc, char **argv) | ||
873 | #endif | 873 | #endif |
874 | } | 874 | } |
875 | 875 | ||
876 | + cpu_exec_init_all(0); | ||
876 | /* NOTE: we need to init the CPU at this stage to get | 877 | /* NOTE: we need to init the CPU at this stage to get |
877 | qemu_host_page_size */ | 878 | qemu_host_page_size */ |
878 | env = cpu_init(cpu_model); | 879 | env = cpu_init(cpu_model); |
exec-all.h
@@ -56,12 +56,6 @@ typedef void (GenOpFunc1)(long); | @@ -56,12 +56,6 @@ typedef void (GenOpFunc1)(long); | ||
56 | typedef void (GenOpFunc2)(long, long); | 56 | typedef void (GenOpFunc2)(long, long); |
57 | typedef void (GenOpFunc3)(long, long, long); | 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 | extern FILE *logfile; | 59 | extern FILE *logfile; |
66 | extern int loglevel; | 60 | extern int loglevel; |
67 | 61 | ||
@@ -105,31 +99,7 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, | @@ -105,31 +99,7 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, | ||
105 | #define CODE_GEN_PHYS_HASH_BITS 15 | 99 | #define CODE_GEN_PHYS_HASH_BITS 15 |
106 | #define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS) | 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 | /* estimated block size for TB allocation */ | 104 | /* estimated block size for TB allocation */ |
135 | /* XXX: use a per code average code fragment size and modulate it | 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,8 +110,6 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr, | ||
140 | #define CODE_GEN_AVG_BLOCK_SIZE 64 | 110 | #define CODE_GEN_AVG_BLOCK_SIZE 64 |
141 | #endif | 111 | #endif |
142 | 112 | ||
143 | -#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE) | ||
144 | - | ||
145 | #if defined(__powerpc__) || defined(__x86_64__) || defined(__arm__) | 113 | #if defined(__powerpc__) || defined(__x86_64__) || defined(__arm__) |
146 | #define USE_DIRECT_JUMP | 114 | #define USE_DIRECT_JUMP |
147 | #endif | 115 | #endif |
@@ -210,9 +178,8 @@ void tb_link_phys(TranslationBlock *tb, | @@ -210,9 +178,8 @@ void tb_link_phys(TranslationBlock *tb, | ||
210 | target_ulong phys_pc, target_ulong phys_page2); | 178 | target_ulong phys_pc, target_ulong phys_page2); |
211 | 179 | ||
212 | extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; | 180 | extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; |
213 | - | ||
214 | -extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE]; | ||
215 | extern uint8_t *code_gen_ptr; | 181 | extern uint8_t *code_gen_ptr; |
182 | +extern int code_gen_max_blocks; | ||
216 | 183 | ||
217 | #if defined(USE_DIRECT_JUMP) | 184 | #if defined(USE_DIRECT_JUMP) |
218 | 185 |
exec.c
@@ -58,9 +58,6 @@ | @@ -58,9 +58,6 @@ | ||
58 | #undef DEBUG_TB_CHECK | 58 | #undef DEBUG_TB_CHECK |
59 | #endif | 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 | #define SMC_BITMAP_USE_THRESHOLD 10 | 61 | #define SMC_BITMAP_USE_THRESHOLD 10 |
65 | 62 | ||
66 | #define MMAP_AREA_START 0x00000000 | 63 | #define MMAP_AREA_START 0x00000000 |
@@ -85,13 +82,17 @@ | @@ -85,13 +82,17 @@ | ||
85 | #endif | 82 | #endif |
86 | 83 | ||
87 | TranslationBlock *tbs; | 84 | TranslationBlock *tbs; |
85 | +int code_gen_max_blocks; | ||
88 | TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; | 86 | TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE]; |
89 | int nb_tbs; | 87 | int nb_tbs; |
90 | /* any access to the tbs or the page table must use this lock */ | 88 | /* any access to the tbs or the page table must use this lock */ |
91 | spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; | 89 | spinlock_t tb_lock = SPIN_LOCK_UNLOCKED; |
92 | 90 | ||
93 | uint8_t code_gen_prologue[1024] __attribute__((aligned (32))); | 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 | uint8_t *code_gen_ptr; | 96 | uint8_t *code_gen_ptr; |
96 | 97 | ||
97 | ram_addr_t phys_ram_size; | 98 | ram_addr_t phys_ram_size; |
@@ -215,9 +216,6 @@ static void page_init(void) | @@ -215,9 +216,6 @@ static void page_init(void) | ||
215 | #else | 216 | #else |
216 | qemu_real_host_page_size = getpagesize(); | 217 | qemu_real_host_page_size = getpagesize(); |
217 | #endif | 218 | #endif |
218 | - map_exec(code_gen_buffer, sizeof(code_gen_buffer)); | ||
219 | - map_exec(code_gen_prologue, sizeof(code_gen_prologue)); | ||
220 | - | ||
221 | if (qemu_host_page_size == 0) | 219 | if (qemu_host_page_size == 0) |
222 | qemu_host_page_size = qemu_real_host_page_size; | 220 | qemu_host_page_size = qemu_real_host_page_size; |
223 | if (qemu_host_page_size < TARGET_PAGE_SIZE) | 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,18 +326,67 @@ static void tlb_unprotect_code_phys(CPUState *env, ram_addr_t ram_addr, | ||
328 | target_ulong vaddr); | 326 | target_ulong vaddr); |
329 | #endif | 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 | void cpu_exec_init(CPUState *env) | 385 | void cpu_exec_init(CPUState *env) |
332 | { | 386 | { |
333 | CPUState **penv; | 387 | CPUState **penv; |
334 | int cpu_index; | 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 | env->next_cpu = NULL; | 390 | env->next_cpu = NULL; |
344 | penv = &first_cpu; | 391 | penv = &first_cpu; |
345 | cpu_index = 0; | 392 | cpu_index = 0; |
@@ -390,7 +437,7 @@ void tb_flush(CPUState *env1) | @@ -390,7 +437,7 @@ void tb_flush(CPUState *env1) | ||
390 | nb_tbs, nb_tbs > 0 ? | 437 | nb_tbs, nb_tbs > 0 ? |
391 | ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); | 438 | ((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0); |
392 | #endif | 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 | cpu_abort(env1, "Internal error: code buffer overflow\n"); | 441 | cpu_abort(env1, "Internal error: code buffer overflow\n"); |
395 | 442 | ||
396 | nb_tbs = 0; | 443 | nb_tbs = 0; |
@@ -960,8 +1007,8 @@ TranslationBlock *tb_alloc(target_ulong pc) | @@ -960,8 +1007,8 @@ TranslationBlock *tb_alloc(target_ulong pc) | ||
960 | { | 1007 | { |
961 | TranslationBlock *tb; | 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 | return NULL; | 1012 | return NULL; |
966 | tb = &tbs[nb_tbs++]; | 1013 | tb = &tbs[nb_tbs++]; |
967 | tb->pc = pc; | 1014 | tb->pc = pc; |
@@ -2990,7 +3037,10 @@ void dump_exec_info(FILE *f, | @@ -2990,7 +3037,10 @@ void dump_exec_info(FILE *f, | ||
2990 | } | 3037 | } |
2991 | /* XXX: avoid using doubles ? */ | 3038 | /* XXX: avoid using doubles ? */ |
2992 | cpu_fprintf(f, "Translation buffer state:\n"); | 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 | cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", | 3044 | cpu_fprintf(f, "TB avg target size %d max=%d bytes\n", |
2995 | nb_tbs ? target_code_size / nb_tbs : 0, | 3045 | nb_tbs ? target_code_size / nb_tbs : 0, |
2996 | max_target_code_size); | 3046 | max_target_code_size); |
linux-user/main.c
@@ -2115,6 +2115,7 @@ int main(int argc, char **argv) | @@ -2115,6 +2115,7 @@ int main(int argc, char **argv) | ||
2115 | cpu_model = "any"; | 2115 | cpu_model = "any"; |
2116 | #endif | 2116 | #endif |
2117 | } | 2117 | } |
2118 | + cpu_exec_init_all(0); | ||
2118 | /* NOTE: we need to init the CPU at this stage to get | 2119 | /* NOTE: we need to init the CPU at this stage to get |
2119 | qemu_host_page_size */ | 2120 | qemu_host_page_size */ |
2120 | env = cpu_init(cpu_model); | 2121 | env = cpu_init(cpu_model); |
target-i386/cpu.h
@@ -723,6 +723,8 @@ static inline int cpu_mmu_index (CPUState *env) | @@ -723,6 +723,8 @@ static inline int cpu_mmu_index (CPUState *env) | ||
723 | return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; | 723 | return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0; |
724 | } | 724 | } |
725 | 725 | ||
726 | +void optimize_flags_init(void); | ||
727 | + | ||
726 | typedef struct CCTable { | 728 | typedef struct CCTable { |
727 | int (*compute_all)(void); /* return all the flags */ | 729 | int (*compute_all)(void); /* return all the flags */ |
728 | int (*compute_c)(void); /* return the C flag */ | 730 | int (*compute_c)(void); /* return the C flag */ |
vl.c
@@ -7378,6 +7378,7 @@ enum { | @@ -7378,6 +7378,7 @@ enum { | ||
7378 | QEMU_OPTION_old_param, | 7378 | QEMU_OPTION_old_param, |
7379 | QEMU_OPTION_clock, | 7379 | QEMU_OPTION_clock, |
7380 | QEMU_OPTION_startdate, | 7380 | QEMU_OPTION_startdate, |
7381 | + QEMU_OPTION_tb_size, | ||
7381 | }; | 7382 | }; |
7382 | 7383 | ||
7383 | typedef struct QEMUOption { | 7384 | typedef struct QEMUOption { |
@@ -7489,6 +7490,7 @@ const QEMUOption qemu_options[] = { | @@ -7489,6 +7490,7 @@ const QEMUOption qemu_options[] = { | ||
7489 | #endif | 7490 | #endif |
7490 | { "clock", HAS_ARG, QEMU_OPTION_clock }, | 7491 | { "clock", HAS_ARG, QEMU_OPTION_clock }, |
7491 | { "startdate", HAS_ARG, QEMU_OPTION_startdate }, | 7492 | { "startdate", HAS_ARG, QEMU_OPTION_startdate }, |
7493 | + { "tb-size", HAS_ARG, QEMU_OPTION_tb_size }, | ||
7492 | { NULL }, | 7494 | { NULL }, |
7493 | }; | 7495 | }; |
7494 | 7496 | ||
@@ -7697,6 +7699,7 @@ int main(int argc, char **argv) | @@ -7697,6 +7699,7 @@ int main(int argc, char **argv) | ||
7697 | const char *usb_devices[MAX_USB_CMDLINE]; | 7699 | const char *usb_devices[MAX_USB_CMDLINE]; |
7698 | int usb_devices_index; | 7700 | int usb_devices_index; |
7699 | int fds[2]; | 7701 | int fds[2]; |
7702 | + int tb_size; | ||
7700 | const char *pid_file = NULL; | 7703 | const char *pid_file = NULL; |
7701 | VLANState *vlan; | 7704 | VLANState *vlan; |
7702 | 7705 | ||
@@ -7768,8 +7771,9 @@ int main(int argc, char **argv) | @@ -7768,8 +7771,9 @@ int main(int argc, char **argv) | ||
7768 | hda_index = -1; | 7771 | hda_index = -1; |
7769 | 7772 | ||
7770 | nb_nics = 0; | 7773 | nb_nics = 0; |
7771 | - /* default mac address of the first network interface */ | ||
7772 | 7774 | ||
7775 | + tb_size = 0; | ||
7776 | + | ||
7773 | optind = 1; | 7777 | optind = 1; |
7774 | for(;;) { | 7778 | for(;;) { |
7775 | if (optind >= argc) | 7779 | if (optind >= argc) |
@@ -8296,6 +8300,11 @@ int main(int argc, char **argv) | @@ -8296,6 +8300,11 @@ int main(int argc, char **argv) | ||
8296 | } | 8300 | } |
8297 | } | 8301 | } |
8298 | break; | 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,6 +8476,9 @@ int main(int argc, char **argv) | ||
8467 | exit(1); | 8476 | exit(1); |
8468 | } | 8477 | } |
8469 | 8478 | ||
8479 | + /* init the dynamic translator */ | ||
8480 | + cpu_exec_init_all(tb_size * 1024 * 1024); | ||
8481 | + | ||
8470 | bdrv_init(); | 8482 | bdrv_init(); |
8471 | 8483 | ||
8472 | /* we always create the cdrom drive, even if no disk is there */ | 8484 | /* we always create the cdrom drive, even if no disk is there */ |