mirror of https://github.com/xqemu/xqemu.git
variable dynamic translation buffer size
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4600 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
bed5cc5207
commit
26a5f13b8e
|
@ -767,6 +767,7 @@ int page_get_flags(target_ulong address);
|
||||||
void page_set_flags(target_ulong start, target_ulong end, int flags);
|
void page_set_flags(target_ulong start, target_ulong end, int flags);
|
||||||
int page_check_range(target_ulong start, target_ulong len, int flags);
|
int page_check_range(target_ulong start, target_ulong len, int flags);
|
||||||
|
|
||||||
|
void cpu_exec_init_all(unsigned long tb_size);
|
||||||
CPUState *cpu_copy(CPUState *env);
|
CPUState *cpu_copy(CPUState *env);
|
||||||
|
|
||||||
void cpu_dump_state(CPUState *env, FILE *f,
|
void cpu_dump_state(CPUState *env, FILE *f,
|
||||||
|
|
|
@ -873,6 +873,7 @@ int main(int argc, char **argv)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cpu_exec_init_all(0);
|
||||||
/* NOTE: we need to init the CPU at this stage to get
|
/* NOTE: we need to init the CPU at this stage to get
|
||||||
qemu_host_page_size */
|
qemu_host_page_size */
|
||||||
env = cpu_init(cpu_model);
|
env = cpu_init(cpu_model);
|
||||||
|
|
37
exec-all.h
37
exec-all.h
|
@ -56,12 +56,6 @@ typedef void (GenOpFunc1)(long);
|
||||||
typedef void (GenOpFunc2)(long, long);
|
typedef void (GenOpFunc2)(long, long);
|
||||||
typedef void (GenOpFunc3)(long, long, long);
|
typedef void (GenOpFunc3)(long, long, long);
|
||||||
|
|
||||||
#if defined(TARGET_I386)
|
|
||||||
|
|
||||||
void optimize_flags_init(void);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
extern FILE *logfile;
|
extern FILE *logfile;
|
||||||
extern int loglevel;
|
extern int loglevel;
|
||||||
|
|
||||||
|
@ -105,31 +99,7 @@ static inline int tlb_set_page(CPUState *env1, target_ulong vaddr,
|
||||||
#define CODE_GEN_PHYS_HASH_BITS 15
|
#define CODE_GEN_PHYS_HASH_BITS 15
|
||||||
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
|
#define CODE_GEN_PHYS_HASH_SIZE (1 << CODE_GEN_PHYS_HASH_BITS)
|
||||||
|
|
||||||
/* maximum total translate dcode allocated */
|
#define MIN_CODE_GEN_BUFFER_SIZE (1024 * 1024)
|
||||||
|
|
||||||
/* NOTE: the translated code area cannot be too big because on some
|
|
||||||
archs the range of "fast" function calls is limited. Here is a
|
|
||||||
summary of the ranges:
|
|
||||||
|
|
||||||
i386 : signed 32 bits
|
|
||||||
arm : signed 26 bits
|
|
||||||
ppc : signed 24 bits
|
|
||||||
sparc : signed 32 bits
|
|
||||||
alpha : signed 23 bits
|
|
||||||
*/
|
|
||||||
|
|
||||||
#if defined(__alpha__)
|
|
||||||
#define CODE_GEN_BUFFER_SIZE (2 * 1024 * 1024)
|
|
||||||
#elif defined(__ia64)
|
|
||||||
#define CODE_GEN_BUFFER_SIZE (4 * 1024 * 1024) /* range of addl */
|
|
||||||
#elif defined(__powerpc__)
|
|
||||||
#define CODE_GEN_BUFFER_SIZE (6 * 1024 * 1024)
|
|
||||||
#else
|
|
||||||
/* XXX: make it dynamic on x86 */
|
|
||||||
#define CODE_GEN_BUFFER_SIZE (64 * 1024 * 1024)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define CODE_GEN_BUFFER_SIZE (128 * 1024)
|
|
||||||
|
|
||||||
/* estimated block size for TB allocation */
|
/* estimated block size for TB allocation */
|
||||||
/* XXX: use a per code average code fragment size and modulate it
|
/* 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,
|
||||||
#define CODE_GEN_AVG_BLOCK_SIZE 64
|
#define CODE_GEN_AVG_BLOCK_SIZE 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
|
|
||||||
|
|
||||||
#if defined(__powerpc__) || defined(__x86_64__) || defined(__arm__)
|
#if defined(__powerpc__) || defined(__x86_64__) || defined(__arm__)
|
||||||
#define USE_DIRECT_JUMP
|
#define USE_DIRECT_JUMP
|
||||||
#endif
|
#endif
|
||||||
|
@ -210,9 +178,8 @@ void tb_link_phys(TranslationBlock *tb,
|
||||||
target_ulong phys_pc, target_ulong phys_page2);
|
target_ulong phys_pc, target_ulong phys_page2);
|
||||||
|
|
||||||
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
|
extern TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
|
||||||
|
|
||||||
extern uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE];
|
|
||||||
extern uint8_t *code_gen_ptr;
|
extern uint8_t *code_gen_ptr;
|
||||||
|
extern int code_gen_max_blocks;
|
||||||
|
|
||||||
#if defined(USE_DIRECT_JUMP)
|
#if defined(USE_DIRECT_JUMP)
|
||||||
|
|
||||||
|
|
86
exec.c
86
exec.c
|
@ -58,9 +58,6 @@
|
||||||
#undef DEBUG_TB_CHECK
|
#undef DEBUG_TB_CHECK
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* threshold to flush the translated code buffer */
|
|
||||||
#define CODE_GEN_BUFFER_MAX_SIZE (CODE_GEN_BUFFER_SIZE - code_gen_max_block_size())
|
|
||||||
|
|
||||||
#define SMC_BITMAP_USE_THRESHOLD 10
|
#define SMC_BITMAP_USE_THRESHOLD 10
|
||||||
|
|
||||||
#define MMAP_AREA_START 0x00000000
|
#define MMAP_AREA_START 0x00000000
|
||||||
|
@ -85,13 +82,17 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TranslationBlock *tbs;
|
TranslationBlock *tbs;
|
||||||
|
int code_gen_max_blocks;
|
||||||
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
|
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
|
||||||
int nb_tbs;
|
int nb_tbs;
|
||||||
/* any access to the tbs or the page table must use this lock */
|
/* any access to the tbs or the page table must use this lock */
|
||||||
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
|
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
|
||||||
|
|
||||||
uint8_t code_gen_prologue[1024] __attribute__((aligned (32)));
|
uint8_t code_gen_prologue[1024] __attribute__((aligned (32)));
|
||||||
uint8_t code_gen_buffer[CODE_GEN_BUFFER_SIZE] __attribute__((aligned (32)));
|
uint8_t *code_gen_buffer;
|
||||||
|
unsigned long code_gen_buffer_size;
|
||||||
|
/* threshold to flush the translated code buffer */
|
||||||
|
unsigned long code_gen_buffer_max_size;
|
||||||
uint8_t *code_gen_ptr;
|
uint8_t *code_gen_ptr;
|
||||||
|
|
||||||
ram_addr_t phys_ram_size;
|
ram_addr_t phys_ram_size;
|
||||||
|
@ -215,9 +216,6 @@ static void page_init(void)
|
||||||
#else
|
#else
|
||||||
qemu_real_host_page_size = getpagesize();
|
qemu_real_host_page_size = getpagesize();
|
||||||
#endif
|
#endif
|
||||||
map_exec(code_gen_buffer, sizeof(code_gen_buffer));
|
|
||||||
map_exec(code_gen_prologue, sizeof(code_gen_prologue));
|
|
||||||
|
|
||||||
if (qemu_host_page_size == 0)
|
if (qemu_host_page_size == 0)
|
||||||
qemu_host_page_size = qemu_real_host_page_size;
|
qemu_host_page_size = qemu_real_host_page_size;
|
||||||
if (qemu_host_page_size < TARGET_PAGE_SIZE)
|
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,
|
||||||
target_ulong vaddr);
|
target_ulong vaddr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void code_gen_alloc(unsigned long tb_size)
|
||||||
|
{
|
||||||
|
code_gen_buffer_size = tb_size;
|
||||||
|
if (code_gen_buffer_size == 0) {
|
||||||
|
/* XXX: needs ajustments */
|
||||||
|
code_gen_buffer_size = (int)(phys_ram_size / 4);
|
||||||
|
}
|
||||||
|
if (code_gen_buffer_size < MIN_CODE_GEN_BUFFER_SIZE)
|
||||||
|
code_gen_buffer_size = MIN_CODE_GEN_BUFFER_SIZE;
|
||||||
|
/* The code gen buffer location may have constraints depending on
|
||||||
|
the host cpu and OS */
|
||||||
|
#if defined(__linux__)
|
||||||
|
{
|
||||||
|
int flags;
|
||||||
|
flags = MAP_PRIVATE | MAP_ANONYMOUS;
|
||||||
|
#if defined(__x86_64__)
|
||||||
|
flags |= MAP_32BIT;
|
||||||
|
/* Cannot map more than that */
|
||||||
|
if (code_gen_buffer_size > (800 * 1024 * 1024))
|
||||||
|
code_gen_buffer_size = (800 * 1024 * 1024);
|
||||||
|
#endif
|
||||||
|
code_gen_buffer = mmap(NULL, code_gen_buffer_size,
|
||||||
|
PROT_WRITE | PROT_READ | PROT_EXEC,
|
||||||
|
flags, -1, 0);
|
||||||
|
if (code_gen_buffer == MAP_FAILED) {
|
||||||
|
fprintf(stderr, "Could not allocate dynamic translator buffer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
code_gen_buffer = qemu_malloc(code_gen_buffer_size);
|
||||||
|
if (!code_gen_buffer) {
|
||||||
|
fprintf(stderr, "Could not allocate dynamic translator buffer\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
map_exec(code_gen_buffer, code_gen_buffer_size);
|
||||||
|
#endif
|
||||||
|
map_exec(code_gen_prologue, sizeof(code_gen_prologue));
|
||||||
|
code_gen_buffer_max_size = code_gen_buffer_size -
|
||||||
|
code_gen_max_block_size();
|
||||||
|
code_gen_max_blocks = code_gen_buffer_size / CODE_GEN_AVG_BLOCK_SIZE;
|
||||||
|
tbs = qemu_malloc(code_gen_max_blocks * sizeof(TranslationBlock));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Must be called before using the QEMU cpus. 'tb_size' is the size
|
||||||
|
(in bytes) allocated to the translation buffer. Zero means default
|
||||||
|
size. */
|
||||||
|
void cpu_exec_init_all(unsigned long tb_size)
|
||||||
|
{
|
||||||
|
page_init();
|
||||||
|
cpu_gen_init();
|
||||||
|
code_gen_alloc(tb_size);
|
||||||
|
code_gen_ptr = code_gen_buffer;
|
||||||
|
io_mem_init();
|
||||||
|
}
|
||||||
|
|
||||||
void cpu_exec_init(CPUState *env)
|
void cpu_exec_init(CPUState *env)
|
||||||
{
|
{
|
||||||
CPUState **penv;
|
CPUState **penv;
|
||||||
int cpu_index;
|
int cpu_index;
|
||||||
|
|
||||||
if (!code_gen_ptr) {
|
|
||||||
cpu_gen_init();
|
|
||||||
tbs = qemu_malloc(CODE_GEN_MAX_BLOCKS * sizeof(TranslationBlock));
|
|
||||||
code_gen_ptr = code_gen_buffer;
|
|
||||||
page_init();
|
|
||||||
io_mem_init();
|
|
||||||
}
|
|
||||||
env->next_cpu = NULL;
|
env->next_cpu = NULL;
|
||||||
penv = &first_cpu;
|
penv = &first_cpu;
|
||||||
cpu_index = 0;
|
cpu_index = 0;
|
||||||
|
@ -390,7 +437,7 @@ void tb_flush(CPUState *env1)
|
||||||
nb_tbs, nb_tbs > 0 ?
|
nb_tbs, nb_tbs > 0 ?
|
||||||
((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
|
((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
|
||||||
#endif
|
#endif
|
||||||
if ((unsigned long)(code_gen_ptr - code_gen_buffer) > CODE_GEN_BUFFER_SIZE)
|
if ((unsigned long)(code_gen_ptr - code_gen_buffer) > code_gen_buffer_size)
|
||||||
cpu_abort(env1, "Internal error: code buffer overflow\n");
|
cpu_abort(env1, "Internal error: code buffer overflow\n");
|
||||||
|
|
||||||
nb_tbs = 0;
|
nb_tbs = 0;
|
||||||
|
@ -960,8 +1007,8 @@ TranslationBlock *tb_alloc(target_ulong pc)
|
||||||
{
|
{
|
||||||
TranslationBlock *tb;
|
TranslationBlock *tb;
|
||||||
|
|
||||||
if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
|
if (nb_tbs >= code_gen_max_blocks ||
|
||||||
(code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
|
(code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
|
||||||
return NULL;
|
return NULL;
|
||||||
tb = &tbs[nb_tbs++];
|
tb = &tbs[nb_tbs++];
|
||||||
tb->pc = pc;
|
tb->pc = pc;
|
||||||
|
@ -2990,7 +3037,10 @@ void dump_exec_info(FILE *f,
|
||||||
}
|
}
|
||||||
/* XXX: avoid using doubles ? */
|
/* XXX: avoid using doubles ? */
|
||||||
cpu_fprintf(f, "Translation buffer state:\n");
|
cpu_fprintf(f, "Translation buffer state:\n");
|
||||||
cpu_fprintf(f, "TB count %d\n", nb_tbs);
|
cpu_fprintf(f, "gen code size %ld/%ld\n",
|
||||||
|
code_gen_ptr - code_gen_buffer, code_gen_buffer_max_size);
|
||||||
|
cpu_fprintf(f, "TB count %d/%d\n",
|
||||||
|
nb_tbs, code_gen_max_blocks);
|
||||||
cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
|
cpu_fprintf(f, "TB avg target size %d max=%d bytes\n",
|
||||||
nb_tbs ? target_code_size / nb_tbs : 0,
|
nb_tbs ? target_code_size / nb_tbs : 0,
|
||||||
max_target_code_size);
|
max_target_code_size);
|
||||||
|
|
|
@ -2115,6 +2115,7 @@ int main(int argc, char **argv)
|
||||||
cpu_model = "any";
|
cpu_model = "any";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
cpu_exec_init_all(0);
|
||||||
/* NOTE: we need to init the CPU at this stage to get
|
/* NOTE: we need to init the CPU at this stage to get
|
||||||
qemu_host_page_size */
|
qemu_host_page_size */
|
||||||
env = cpu_init(cpu_model);
|
env = cpu_init(cpu_model);
|
||||||
|
|
|
@ -723,6 +723,8 @@ static inline int cpu_mmu_index (CPUState *env)
|
||||||
return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
|
return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void optimize_flags_init(void);
|
||||||
|
|
||||||
typedef struct CCTable {
|
typedef struct CCTable {
|
||||||
int (*compute_all)(void); /* return all the flags */
|
int (*compute_all)(void); /* return all the flags */
|
||||||
int (*compute_c)(void); /* return the C flag */
|
int (*compute_c)(void); /* return the C flag */
|
||||||
|
|
14
vl.c
14
vl.c
|
@ -7378,6 +7378,7 @@ enum {
|
||||||
QEMU_OPTION_old_param,
|
QEMU_OPTION_old_param,
|
||||||
QEMU_OPTION_clock,
|
QEMU_OPTION_clock,
|
||||||
QEMU_OPTION_startdate,
|
QEMU_OPTION_startdate,
|
||||||
|
QEMU_OPTION_tb_size,
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef struct QEMUOption {
|
typedef struct QEMUOption {
|
||||||
|
@ -7489,6 +7490,7 @@ const QEMUOption qemu_options[] = {
|
||||||
#endif
|
#endif
|
||||||
{ "clock", HAS_ARG, QEMU_OPTION_clock },
|
{ "clock", HAS_ARG, QEMU_OPTION_clock },
|
||||||
{ "startdate", HAS_ARG, QEMU_OPTION_startdate },
|
{ "startdate", HAS_ARG, QEMU_OPTION_startdate },
|
||||||
|
{ "tb-size", HAS_ARG, QEMU_OPTION_tb_size },
|
||||||
{ NULL },
|
{ NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -7697,6 +7699,7 @@ int main(int argc, char **argv)
|
||||||
const char *usb_devices[MAX_USB_CMDLINE];
|
const char *usb_devices[MAX_USB_CMDLINE];
|
||||||
int usb_devices_index;
|
int usb_devices_index;
|
||||||
int fds[2];
|
int fds[2];
|
||||||
|
int tb_size;
|
||||||
const char *pid_file = NULL;
|
const char *pid_file = NULL;
|
||||||
VLANState *vlan;
|
VLANState *vlan;
|
||||||
|
|
||||||
|
@ -7768,8 +7771,9 @@ int main(int argc, char **argv)
|
||||||
hda_index = -1;
|
hda_index = -1;
|
||||||
|
|
||||||
nb_nics = 0;
|
nb_nics = 0;
|
||||||
/* default mac address of the first network interface */
|
|
||||||
|
|
||||||
|
tb_size = 0;
|
||||||
|
|
||||||
optind = 1;
|
optind = 1;
|
||||||
for(;;) {
|
for(;;) {
|
||||||
if (optind >= argc)
|
if (optind >= argc)
|
||||||
|
@ -8296,6 +8300,11 @@ int main(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case QEMU_OPTION_tb_size:
|
||||||
|
tb_size = strtol(optarg, NULL, 0);
|
||||||
|
if (tb_size < 0)
|
||||||
|
tb_size = 0;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8467,6 +8476,9 @@ int main(int argc, char **argv)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* init the dynamic translator */
|
||||||
|
cpu_exec_init_all(tb_size * 1024 * 1024);
|
||||||
|
|
||||||
bdrv_init();
|
bdrv_init();
|
||||||
|
|
||||||
/* we always create the cdrom drive, even if no disk is there */
|
/* we always create the cdrom drive, even if no disk is there */
|
||||||
|
|
Loading…
Reference in New Issue