* [Qemu-devel] [4600] variable dynamic translation buffer size
@ 2008-05-28 12:30 Fabrice Bellard
2008-05-28 12:55 ` Paul Brook
2008-05-28 19:08 ` Blue Swirl
0 siblings, 2 replies; 4+ messages in thread
From: Fabrice Bellard @ 2008-05-28 12:30 UTC (permalink / raw)
To: qemu-devel
Revision: 4600
http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4600
Author: bellard
Date: 2008-05-28 12:30:31 +0000 (Wed, 28 May 2008)
Log Message:
-----------
variable dynamic translation buffer size
Modified Paths:
--------------
trunk/cpu-all.h
trunk/darwin-user/main.c
trunk/exec-all.h
trunk/exec.c
trunk/linux-user/main.c
trunk/target-i386/cpu.h
trunk/vl.c
Modified: trunk/cpu-all.h
===================================================================
--- trunk/cpu-all.h 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/cpu-all.h 2008-05-28 12:30:31 UTC (rev 4600)
@@ -767,6 +767,7 @@
void page_set_flags(target_ulong start, target_ulong end, 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);
void cpu_dump_state(CPUState *env, FILE *f,
Modified: trunk/darwin-user/main.c
===================================================================
--- trunk/darwin-user/main.c 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/darwin-user/main.c 2008-05-28 12:30:31 UTC (rev 4600)
@@ -873,6 +873,7 @@
#endif
}
+ cpu_exec_init_all(0);
/* NOTE: we need to init the CPU at this stage to get
qemu_host_page_size */
env = cpu_init(cpu_model);
Modified: trunk/exec-all.h
===================================================================
--- trunk/exec-all.h 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/exec-all.h 2008-05-28 12:30:31 UTC (rev 4600)
@@ -56,12 +56,6 @@
typedef void (GenOpFunc2)(long, long);
typedef void (GenOpFunc3)(long, long, long);
-#if defined(TARGET_I386)
-
-void optimize_flags_init(void);
-
-#endif
-
extern FILE *logfile;
extern int loglevel;
@@ -105,32 +99,8 @@
#define CODE_GEN_PHYS_HASH_BITS 15
#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 */
/* XXX: use a per code average code fragment size and modulate it
according to the host CPU */
@@ -140,8 +110,6 @@
#define CODE_GEN_AVG_BLOCK_SIZE 64
#endif
-#define CODE_GEN_MAX_BLOCKS (CODE_GEN_BUFFER_SIZE / CODE_GEN_AVG_BLOCK_SIZE)
-
#if defined(__powerpc__) || defined(__x86_64__) || defined(__arm__)
#define USE_DIRECT_JUMP
#endif
@@ -210,9 +178,8 @@
target_ulong phys_pc, target_ulong phys_page2);
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 int code_gen_max_blocks;
#if defined(USE_DIRECT_JUMP)
Modified: trunk/exec.c
===================================================================
--- trunk/exec.c 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/exec.c 2008-05-28 12:30:31 UTC (rev 4600)
@@ -58,9 +58,6 @@
#undef DEBUG_TB_CHECK
#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 MMAP_AREA_START 0x00000000
@@ -85,13 +82,17 @@
#endif
TranslationBlock *tbs;
+int code_gen_max_blocks;
TranslationBlock *tb_phys_hash[CODE_GEN_PHYS_HASH_SIZE];
int nb_tbs;
/* any access to the tbs or the page table must use this lock */
spinlock_t tb_lock = SPIN_LOCK_UNLOCKED;
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;
ram_addr_t phys_ram_size;
@@ -215,9 +216,6 @@
#else
qemu_real_host_page_size = getpagesize();
#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)
qemu_host_page_size = qemu_real_host_page_size;
if (qemu_host_page_size < TARGET_PAGE_SIZE)
@@ -328,18 +326,67 @@
target_ulong vaddr);
#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)
{
CPUState **penv;
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;
penv = &first_cpu;
cpu_index = 0;
@@ -390,7 +437,7 @@
nb_tbs, nb_tbs > 0 ?
((unsigned long)(code_gen_ptr - code_gen_buffer)) / nb_tbs : 0);
#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");
nb_tbs = 0;
@@ -960,8 +1007,8 @@
{
TranslationBlock *tb;
- if (nb_tbs >= CODE_GEN_MAX_BLOCKS ||
- (code_gen_ptr - code_gen_buffer) >= CODE_GEN_BUFFER_MAX_SIZE)
+ if (nb_tbs >= code_gen_max_blocks ||
+ (code_gen_ptr - code_gen_buffer) >= code_gen_buffer_max_size)
return NULL;
tb = &tbs[nb_tbs++];
tb->pc = pc;
@@ -2990,7 +3037,10 @@
}
/* XXX: avoid using doubles ? */
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",
nb_tbs ? target_code_size / nb_tbs : 0,
max_target_code_size);
Modified: trunk/linux-user/main.c
===================================================================
--- trunk/linux-user/main.c 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/linux-user/main.c 2008-05-28 12:30:31 UTC (rev 4600)
@@ -2115,6 +2115,7 @@
cpu_model = "any";
#endif
}
+ cpu_exec_init_all(0);
/* NOTE: we need to init the CPU at this stage to get
qemu_host_page_size */
env = cpu_init(cpu_model);
Modified: trunk/target-i386/cpu.h
===================================================================
--- trunk/target-i386/cpu.h 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/target-i386/cpu.h 2008-05-28 12:30:31 UTC (rev 4600)
@@ -723,6 +723,8 @@
return (env->hflags & HF_CPL_MASK) == 3 ? 1 : 0;
}
+void optimize_flags_init(void);
+
typedef struct CCTable {
int (*compute_all)(void); /* return all the flags */
int (*compute_c)(void); /* return the C flag */
Modified: trunk/vl.c
===================================================================
--- trunk/vl.c 2008-05-28 09:51:09 UTC (rev 4599)
+++ trunk/vl.c 2008-05-28 12:30:31 UTC (rev 4600)
@@ -7378,6 +7378,7 @@
QEMU_OPTION_old_param,
QEMU_OPTION_clock,
QEMU_OPTION_startdate,
+ QEMU_OPTION_tb_size,
};
typedef struct QEMUOption {
@@ -7489,6 +7490,7 @@
#endif
{ "clock", HAS_ARG, QEMU_OPTION_clock },
{ "startdate", HAS_ARG, QEMU_OPTION_startdate },
+ { "tb-size", HAS_ARG, QEMU_OPTION_tb_size },
{ NULL },
};
@@ -7697,6 +7699,7 @@
const char *usb_devices[MAX_USB_CMDLINE];
int usb_devices_index;
int fds[2];
+ int tb_size;
const char *pid_file = NULL;
VLANState *vlan;
@@ -7768,8 +7771,9 @@
hda_index = -1;
nb_nics = 0;
- /* default mac address of the first network interface */
+ tb_size = 0;
+
optind = 1;
for(;;) {
if (optind >= argc)
@@ -8296,6 +8300,11 @@
}
}
break;
+ case QEMU_OPTION_tb_size:
+ tb_size = strtol(optarg, NULL, 0);
+ if (tb_size < 0)
+ tb_size = 0;
+ break;
}
}
}
@@ -8467,6 +8476,9 @@
exit(1);
}
+ /* init the dynamic translator */
+ cpu_exec_init_all(tb_size * 1024 * 1024);
+
bdrv_init();
/* we always create the cdrom drive, even if no disk is there */
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [4600] variable dynamic translation buffer size
2008-05-28 12:30 [Qemu-devel] [4600] variable dynamic translation buffer size Fabrice Bellard
@ 2008-05-28 12:55 ` Paul Brook
2008-05-28 15:11 ` Fabrice Bellard
2008-05-28 19:08 ` Blue Swirl
1 sibling, 1 reply; 4+ messages in thread
From: Paul Brook @ 2008-05-28 12:55 UTC (permalink / raw)
To: qemu-devel
On Wednesday 28 May 2008, Fabrice Bellard wrote:
> + code_gen_buffer = mmap(NULL, code_gen_buffer_size,
> + PROT_WRITE | PROT_READ | PROT_EXEC,
> + flags, -1, 0);
I'd expect this to cause a significant performance regression on hosts that
have limited branch range (i.e. everything except x86). The mmap region is
almost never close to the application text segment, so all helper calls have
to be indirect.
Paul
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [4600] variable dynamic translation buffer size
2008-05-28 12:55 ` Paul Brook
@ 2008-05-28 15:11 ` Fabrice Bellard
0 siblings, 0 replies; 4+ messages in thread
From: Fabrice Bellard @ 2008-05-28 15:11 UTC (permalink / raw)
To: qemu-devel; +Cc: Paul Brook
Paul Brook wrote:
> On Wednesday 28 May 2008, Fabrice Bellard wrote:
>> + code_gen_buffer = mmap(NULL, code_gen_buffer_size,
>> + PROT_WRITE | PROT_READ | PROT_EXEC,
>> + flags, -1, 0);
>
> I'd expect this to cause a significant performance regression on hosts that
> have limited branch range (i.e. everything except x86). The mmap region is
> almost never close to the application text segment, so all helper calls have
> to be indirect.
I knew that when I did the patch, but having a dynamic size on x86 hosts
prevails.
The other hosts can still implement hacks if they really need to, either
by reserving a huge data in BSS as it was done before or by using the
proc/x/maps entries to compute a possible mmap() address. IMHO I think
this is unnecessary as helpers should be the exception.
Fabrice.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [Qemu-devel] [4600] variable dynamic translation buffer size
2008-05-28 12:30 [Qemu-devel] [4600] variable dynamic translation buffer size Fabrice Bellard
2008-05-28 12:55 ` Paul Brook
@ 2008-05-28 19:08 ` Blue Swirl
1 sibling, 0 replies; 4+ messages in thread
From: Blue Swirl @ 2008-05-28 19:08 UTC (permalink / raw)
To: qemu-devel
On 5/28/08, Fabrice Bellard <fabrice@bellard.org> wrote:
> Revision: 4600
> http://svn.sv.gnu.org/viewvc/?view=rev&root=qemu&revision=4600
> Author: bellard
> Date: 2008-05-28 12:30:31 +0000 (Wed, 28 May 2008)
>
> Log Message:
> -----------
> variable dynamic translation buffer size
This commit broke sparc-linux-user, tested on amd64 host:
./obj-amd64/sparc-linux-user/qemu-sparc -L
../qemu-tests/usr/local/gnemul/qemu-sparc ../qemu-tests/sparc/ash
-help
qemu: uncaught target signal 11 (Segmentation fault) - exiting
While expected result is:
Illegal option -h
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2008-05-28 19:08 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2008-05-28 12:30 [Qemu-devel] [4600] variable dynamic translation buffer size Fabrice Bellard
2008-05-28 12:55 ` Paul Brook
2008-05-28 15:11 ` Fabrice Bellard
2008-05-28 19:08 ` Blue Swirl
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).