qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [4600] variable dynamic translation buffer size


From: Fabrice Bellard
Subject: [Qemu-devel] [4600] variable dynamic translation buffer size
Date: Wed, 28 May 2008 12:30:33 +0000

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






reply via email to

[Prev in Thread] Current Thread [Next in Thread]