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 */ | ... | ... |