Commit 379f6698d73f476de38682b3ff96ecb226728c43

Authored by Paul Brook
1 parent a9ff9df1

Userspace guest address offsetting

Re-implement GUEST_BASE support.
Offset guest ddress space by default if the guest binary contains
regions below the host mmap_min_addr.
Implement support for i386, x86-64 and arm hosts.

Signed-off-by: Riku Voipio <riku.voipio@iki.fi>
Signed-off-by: Paul Brook <paul@codesourcery.com>
configure
@@ -184,6 +184,7 @@ softmmu=&quot;yes&quot; @@ -184,6 +184,7 @@ softmmu=&quot;yes&quot;
184 linux_user="no" 184 linux_user="no"
185 darwin_user="no" 185 darwin_user="no"
186 bsd_user="no" 186 bsd_user="no"
  187 +guest_base=""
187 build_docs="yes" 188 build_docs="yes"
188 uname_release="" 189 uname_release=""
189 curses="yes" 190 curses="yes"
@@ -465,6 +466,10 @@ for opt do @@ -465,6 +466,10 @@ for opt do
465 ;; 466 ;;
466 --enable-bsd-user) bsd_user="yes" 467 --enable-bsd-user) bsd_user="yes"
467 ;; 468 ;;
  469 + --enable-guest-base) guest_base="yes"
  470 + ;;
  471 + --disable-guest-base) guest_base="no"
  472 + ;;
468 --enable-uname-release=*) uname_release="$optarg" 473 --enable-uname-release=*) uname_release="$optarg"
469 ;; 474 ;;
470 --sparc_cpu=*) 475 --sparc_cpu=*)
@@ -544,6 +549,7 @@ fi @@ -544,6 +549,7 @@ fi
544 # If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right 549 # If cpu ~= sparc and sparc_cpu hasn't been defined, plug in the right
545 # ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit) 550 # ARCH_CFLAGS/ARCH_LDFLAGS (assume sparc_v8plus for 32-bit and sparc_v9 for 64-bit)
546 # 551 #
  552 +host_guest_base="no"
547 case "$cpu" in 553 case "$cpu" in
548 sparc) if test -z "$sparc_cpu" ; then 554 sparc) if test -z "$sparc_cpu" ; then
549 ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__" 555 ARCH_CFLAGS="-m32 -mcpu=ultrasparc -D__sparc_v8plus__"
@@ -576,13 +582,20 @@ case &quot;$cpu&quot; in @@ -576,13 +582,20 @@ case &quot;$cpu&quot; in
576 i386) 582 i386)
577 ARCH_CFLAGS="-m32" 583 ARCH_CFLAGS="-m32"
578 ARCH_LDFLAGS="-m32" 584 ARCH_LDFLAGS="-m32"
  585 + host_guest_base="yes"
579 ;; 586 ;;
580 x86_64) 587 x86_64)
581 ARCH_CFLAGS="-m64" 588 ARCH_CFLAGS="-m64"
582 ARCH_LDFLAGS="-m64" 589 ARCH_LDFLAGS="-m64"
  590 + host_guest_base="yes"
  591 + ;;
  592 + arm*)
  593 + host_guest_base="yes"
583 ;; 594 ;;
584 esac 595 esac
585 596
  597 +[ -z "$guest_base" ] && guest_base="$host_guest_base"
  598 +
586 if test x"$show_help" = x"yes" ; then 599 if test x"$show_help" = x"yes" ; then
587 cat << EOF 600 cat << EOF
588 601
@@ -641,6 +654,9 @@ echo &quot; --enable-darwin-user enable all darwin usermode emulation targets&quot; @@ -641,6 +654,9 @@ echo &quot; --enable-darwin-user enable all darwin usermode emulation targets&quot;
641 echo " --disable-darwin-user disable all darwin usermode emulation targets" 654 echo " --disable-darwin-user disable all darwin usermode emulation targets"
642 echo " --enable-bsd-user enable all BSD usermode emulation targets" 655 echo " --enable-bsd-user enable all BSD usermode emulation targets"
643 echo " --disable-bsd-user disable all BSD usermode emulation targets" 656 echo " --disable-bsd-user disable all BSD usermode emulation targets"
  657 +echo " --enable-guest-base enable GUEST_BASE support for usermode"
  658 +echo " emulation targets"
  659 +echo " --disable-guest-base disable GUEST_BASE support"
644 echo " --fmod-lib path to FMOD library" 660 echo " --fmod-lib path to FMOD library"
645 echo " --fmod-inc path to FMOD includes" 661 echo " --fmod-inc path to FMOD includes"
646 echo " --oss-lib path to OSS library" 662 echo " --oss-lib path to OSS library"
@@ -1446,6 +1462,7 @@ echo &quot;Documentation $build_docs&quot; @@ -1446,6 +1462,7 @@ echo &quot;Documentation $build_docs&quot;
1446 [ ! -z "$uname_release" ] && \ 1462 [ ! -z "$uname_release" ] && \
1447 echo "uname -r $uname_release" 1463 echo "uname -r $uname_release"
1448 echo "NPTL support $nptl" 1464 echo "NPTL support $nptl"
  1465 +echo "GUEST_BASE $guest_base"
1449 echo "vde support $vde" 1466 echo "vde support $vde"
1450 echo "AIO support $aio" 1467 echo "AIO support $aio"
1451 echo "IO thread $io_thread" 1468 echo "IO thread $io_thread"
@@ -2070,6 +2087,9 @@ fi @@ -2070,6 +2087,9 @@ fi
2070 if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then 2087 if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then
2071 echo "TARGET_HAS_ELFLOAD32=y" >> $config_mak 2088 echo "TARGET_HAS_ELFLOAD32=y" >> $config_mak
2072 fi 2089 fi
  2090 +if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then
  2091 + echo "CONFIG_USE_GUEST_BASE=y" >> $config_mak
  2092 +fi
2073 if test "$target_bsd_user" = "yes" ; then 2093 if test "$target_bsd_user" = "yes" ; then
2074 echo "CONFIG_BSD_USER=y" >> $config_mak 2094 echo "CONFIG_BSD_USER=y" >> $config_mak
2075 fi 2095 fi
cpu-all.h
@@ -624,8 +624,13 @@ static inline void stfq_be_p(void *ptr, float64 v) @@ -624,8 +624,13 @@ static inline void stfq_be_p(void *ptr, float64 v)
624 /* On some host systems the guest address space is reserved on the host. 624 /* On some host systems the guest address space is reserved on the host.
625 * This allows the guest address space to be offset to a convenient location. 625 * This allows the guest address space to be offset to a convenient location.
626 */ 626 */
627 -//#define GUEST_BASE 0x20000000  
628 -#define GUEST_BASE 0 627 +#if defined(CONFIG_USE_GUEST_BASE)
  628 +extern unsigned long guest_base;
  629 +extern int have_guest_base;
  630 +#define GUEST_BASE guest_base
  631 +#else
  632 +#define GUEST_BASE 0ul
  633 +#endif
629 634
630 /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ 635 /* All direct uses of g2h and h2g need to go away for usermode softmmu. */
631 #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) 636 #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE))
linux-user/elfload.c
@@ -1545,6 +1545,29 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, @@ -1545,6 +1545,29 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs,
1545 info->mmap = 0; 1545 info->mmap = 0;
1546 elf_entry = (abi_ulong) elf_ex.e_entry; 1546 elf_entry = (abi_ulong) elf_ex.e_entry;
1547 1547
  1548 +#if defined(CONFIG_USE_GUEST_BASE)
  1549 + /*
  1550 + * In case where user has not explicitly set the guest_base, we
  1551 + * probe here that should we set it automatically.
  1552 + */
  1553 + if (!have_guest_base) {
  1554 + /*
  1555 + * Go through ELF program header table and find out whether
  1556 + * any of the segments drop below our current mmap_min_addr and
  1557 + * in that case set guest_base to corresponding address.
  1558 + */
  1559 + for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
  1560 + i++, elf_ppnt++) {
  1561 + if (elf_ppnt->p_type != PT_LOAD)
  1562 + continue;
  1563 + if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) {
  1564 + guest_base = HOST_PAGE_ALIGN(mmap_min_addr);
  1565 + break;
  1566 + }
  1567 + }
  1568 + }
  1569 +#endif /* CONFIG_USE_GUEST_BASE */
  1570 +
1548 /* Do this so that we can load the interpreter, if need be. We will 1571 /* Do this so that we can load the interpreter, if need be. We will
1549 change some of these later */ 1572 change some of these later */
1550 info->rss = 0; 1573 info->rss = 0;
linux-user/main.c
@@ -39,6 +39,11 @@ @@ -39,6 +39,11 @@
39 char *exec_path; 39 char *exec_path;
40 40
41 int singlestep; 41 int singlestep;
  42 +#if defined(CONFIG_USE_GUEST_BASE)
  43 +unsigned long mmap_min_addr;
  44 +unsigned long guest_base;
  45 +int have_guest_base;
  46 +#endif
42 47
43 static const char *interp_prefix = CONFIG_QEMU_PREFIX; 48 static const char *interp_prefix = CONFIG_QEMU_PREFIX;
44 const char *qemu_uname_release = CONFIG_UNAME_RELEASE; 49 const char *qemu_uname_release = CONFIG_UNAME_RELEASE;
@@ -2320,6 +2325,9 @@ static void usage(void) @@ -2320,6 +2325,9 @@ static void usage(void)
2320 "-E var=value sets/modifies targets environment variable(s)\n" 2325 "-E var=value sets/modifies targets environment variable(s)\n"
2321 "-U var unsets targets environment variable(s)\n" 2326 "-U var unsets targets environment variable(s)\n"
2322 "-0 argv0 forces target process argv[0] to be argv0\n" 2327 "-0 argv0 forces target process argv[0] to be argv0\n"
  2328 +#if defined(CONFIG_USE_GUEST_BASE)
  2329 + "-B address set guest_base address to address\n"
  2330 +#endif
2323 "\n" 2331 "\n"
2324 "Debug options:\n" 2332 "Debug options:\n"
2325 "-d options activate log (logfile=%s)\n" 2333 "-d options activate log (logfile=%s)\n"
@@ -2495,6 +2503,11 @@ int main(int argc, char **argv, char **envp) @@ -2495,6 +2503,11 @@ int main(int argc, char **argv, char **envp)
2495 #endif 2503 #endif
2496 exit(1); 2504 exit(1);
2497 } 2505 }
  2506 +#if defined(CONFIG_USE_GUEST_BASE)
  2507 + } else if (!strcmp(r, "B")) {
  2508 + guest_base = strtol(argv[optind++], NULL, 0);
  2509 + have_guest_base = 1;
  2510 +#endif
2498 } else if (!strcmp(r, "drop-ld-preload")) { 2511 } else if (!strcmp(r, "drop-ld-preload")) {
2499 (void) envlist_unsetenv(envlist, "LD_PRELOAD"); 2512 (void) envlist_unsetenv(envlist, "LD_PRELOAD");
2500 } else if (!strcmp(r, "singlestep")) { 2513 } else if (!strcmp(r, "singlestep")) {
@@ -2572,6 +2585,35 @@ int main(int argc, char **argv, char **envp) @@ -2572,6 +2585,35 @@ int main(int argc, char **argv, char **envp)
2572 target_environ = envlist_to_environ(envlist, NULL); 2585 target_environ = envlist_to_environ(envlist, NULL);
2573 envlist_free(envlist); 2586 envlist_free(envlist);
2574 2587
  2588 +#if defined(CONFIG_USE_GUEST_BASE)
  2589 + /*
  2590 + * Now that page sizes are configured in cpu_init() we can do
  2591 + * proper page alignment for guest_base.
  2592 + */
  2593 + guest_base = HOST_PAGE_ALIGN(guest_base);
  2594 +
  2595 + /*
  2596 + * Read in mmap_min_addr kernel parameter. This value is used
  2597 + * When loading the ELF image to determine whether guest_base
  2598 + * is needed.
  2599 + *
  2600 + * When user has explicitly set the quest base, we skip this
  2601 + * test.
  2602 + */
  2603 + if (!have_guest_base) {
  2604 + FILE *fp;
  2605 +
  2606 + if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
  2607 + unsigned long tmp;
  2608 + if (fscanf(fp, "%lu", &tmp) == 1) {
  2609 + mmap_min_addr = tmp;
  2610 + qemu_log("host mmap_min_addr=0x%lx\n", mmap_min_addr);
  2611 + }
  2612 + fclose(fp);
  2613 + }
  2614 + }
  2615 +#endif /* CONFIG_USE_GUEST_BASE */
  2616 +
2575 /* 2617 /*
2576 * Prepare copy of argv vector for target. 2618 * Prepare copy of argv vector for target.
2577 */ 2619 */
@@ -2622,6 +2664,9 @@ int main(int argc, char **argv, char **envp) @@ -2622,6 +2664,9 @@ int main(int argc, char **argv, char **envp)
2622 free(target_environ); 2664 free(target_environ);
2623 2665
2624 if (qemu_log_enabled()) { 2666 if (qemu_log_enabled()) {
  2667 +#if defined(CONFIG_USE_GUEST_BASE)
  2668 + qemu_log("guest_base 0x%lx\n", guest_base);
  2669 +#endif
2625 log_page_dump(); 2670 log_page_dump();
2626 2671
2627 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); 2672 qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk);
linux-user/qemu.h
@@ -133,6 +133,9 @@ void init_task_state(TaskState *ts); @@ -133,6 +133,9 @@ void init_task_state(TaskState *ts);
133 void task_settid(TaskState *); 133 void task_settid(TaskState *);
134 void stop_all_tasks(void); 134 void stop_all_tasks(void);
135 extern const char *qemu_uname_release; 135 extern const char *qemu_uname_release;
  136 +#if defined(CONFIG_USE_GUEST_BASE)
  137 +extern unsigned long mmap_min_addr;
  138 +#endif
136 139
137 /* ??? See if we can avoid exposing so much of the loader internals. */ 140 /* ??? See if we can avoid exposing so much of the loader internals. */
138 /* 141 /*
qemu-doc.texi
@@ -2026,7 +2026,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine \ @@ -2026,7 +2026,7 @@ qemu-i386 /usr/local/qemu-i386/wine/bin/wine \
2026 @subsection Command line options 2026 @subsection Command line options
2027 2027
2028 @example 2028 @example
2029 -usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] program [arguments...] 2029 +usage: qemu-i386 [-h] [-d] [-L path] [-s size] [-cpu model] [-g port] [-B offset] program [arguments...]
2030 @end example 2030 @end example
2031 2031
2032 @table @option 2032 @table @option
@@ -2038,6 +2038,10 @@ Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386) @@ -2038,6 +2038,10 @@ Set the x86 elf interpreter prefix (default=/usr/local/qemu-i386)
2038 Set the x86 stack size in bytes (default=524288) 2038 Set the x86 stack size in bytes (default=524288)
2039 @item -cpu model 2039 @item -cpu model
2040 Select CPU model (-cpu ? for list and additional feature selection) 2040 Select CPU model (-cpu ? for list and additional feature selection)
  2041 +@item -B offset
  2042 +Offset guest address by the specified number of bytes. This is useful when
  2043 +the address region rewuired by guest applications is reserved on the host.
  2044 +Ths option is currently only supported on some hosts.
2041 @end table 2045 @end table
2042 2046
2043 Debug options: 2047 Debug options:
tcg/arm/tcg-target.c
@@ -990,7 +990,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond, @@ -990,7 +990,22 @@ static inline void tcg_out_qemu_ld(TCGContext *s, int cond,
990 # endif 990 # endif
991 991
992 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; 992 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
993 -#else 993 +#else /* !CONFIG_SOFTMMU */
  994 + if (GUEST_BASE) {
  995 + uint32_t offset = GUEST_BASE;
  996 + int i;
  997 + int rot;
  998 +
  999 + while (offset) {
  1000 + i = ctz32(offset) & ~1;
  1001 + rot = ((32 - i) << 7) & 0xf00;
  1002 +
  1003 + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg,
  1004 + ((offset >> i) & 0xff) | rot);
  1005 + addr_reg = 8;
  1006 + offset &= ~(0xff << i);
  1007 + }
  1008 + }
994 switch (opc) { 1009 switch (opc) {
995 case 0: 1010 case 0:
996 tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0); 1011 tcg_out_ld8_12(s, COND_AL, data_reg, addr_reg, 0);
@@ -1200,7 +1215,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond, @@ -1200,7 +1215,22 @@ static inline void tcg_out_qemu_st(TCGContext *s, int cond,
1200 # endif 1215 # endif
1201 1216
1202 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2; 1217 *label_ptr += ((void *) s->code_ptr - (void *) label_ptr - 8) >> 2;
1203 -#else 1218 +#else /* !CONFIG_SOFTMMU */
  1219 + if (GUEST_BASE) {
  1220 + uint32_t offset = GUEST_BASE;
  1221 + int i;
  1222 + int rot;
  1223 +
  1224 + while (offset) {
  1225 + i = ctz32(offset) & ~1;
  1226 + rot = ((32 - i) << 7) & 0xf00;
  1227 +
  1228 + tcg_out_dat_imm(s, COND_AL, ARITH_ADD, 8, addr_reg,
  1229 + ((offset >> i) & 0xff) | rot);
  1230 + addr_reg = 8;
  1231 + offset &= ~(0xff << i);
  1232 + }
  1233 + }
1204 switch (opc) { 1234 switch (opc) {
1205 case 0: 1235 case 0:
1206 tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0); 1236 tcg_out_st8_12(s, COND_AL, data_reg, addr_reg, 0);
tcg/arm/tcg-target.h
@@ -60,6 +60,8 @@ enum { @@ -60,6 +60,8 @@ enum {
60 #define TCG_TARGET_STACK_ALIGN 8 60 #define TCG_TARGET_STACK_ALIGN 8
61 #define TCG_TARGET_CALL_STACK_OFFSET 0 61 #define TCG_TARGET_CALL_STACK_OFFSET 0
62 62
  63 +#define TCG_TARGET_HAS_GUEST_BASE
  64 +
63 enum { 65 enum {
64 /* Note: must be synced with dyngen-exec.h */ 66 /* Note: must be synced with dyngen-exec.h */
65 TCG_AREG0 = TCG_REG_R7, 67 TCG_AREG0 = TCG_REG_R7,
tcg/i386/tcg-target.c
@@ -427,6 +427,10 @@ static void *qemu_st_helpers[4] = { @@ -427,6 +427,10 @@ static void *qemu_st_helpers[4] = {
427 }; 427 };
428 #endif 428 #endif
429 429
  430 +#ifndef CONFIG_USER_ONLY
  431 +#define GUEST_BASE 0
  432 +#endif
  433 +
430 /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and 434 /* XXX: qemu_ld and qemu_st could be modified to clobber only EDX and
431 EAX. It will be useful once fixed registers globals are less 435 EAX. It will be useful once fixed registers globals are less
432 common. */ 436 common. */
@@ -572,15 +576,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -572,15 +576,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
572 switch(opc) { 576 switch(opc) {
573 case 0: 577 case 0:
574 /* movzbl */ 578 /* movzbl */
575 - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); 579 + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE);
576 break; 580 break;
577 case 0 | 4: 581 case 0 | 4:
578 /* movsbl */ 582 /* movsbl */
579 - tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, 0); 583 + tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE);
580 break; 584 break;
581 case 1: 585 case 1:
582 /* movzwl */ 586 /* movzwl */
583 - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); 587 + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE);
584 if (bswap) { 588 if (bswap) {
585 /* rolw $8, data_reg */ 589 /* rolw $8, data_reg */
586 tcg_out8(s, 0x66); 590 tcg_out8(s, 0x66);
@@ -590,7 +594,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -590,7 +594,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
590 break; 594 break;
591 case 1 | 4: 595 case 1 | 4:
592 /* movswl */ 596 /* movswl */
593 - tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, 0); 597 + tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE);
594 if (bswap) { 598 if (bswap) {
595 /* rolw $8, data_reg */ 599 /* rolw $8, data_reg */
596 tcg_out8(s, 0x66); 600 tcg_out8(s, 0x66);
@@ -603,7 +607,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -603,7 +607,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
603 break; 607 break;
604 case 2: 608 case 2:
605 /* movl (r0), data_reg */ 609 /* movl (r0), data_reg */
606 - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); 610 + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
607 if (bswap) { 611 if (bswap) {
608 /* bswap */ 612 /* bswap */
609 tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); 613 tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
@@ -619,13 +623,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -619,13 +623,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
619 r0 = r1; 623 r0 = r1;
620 } 624 }
621 if (!bswap) { 625 if (!bswap) {
622 - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0);  
623 - tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 4); 626 + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE);
  627 + tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST+BASE + 4);
624 } else { 628 } else {
625 - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 4); 629 + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4);
626 tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); 630 tcg_out_opc(s, (0xc8 + data_reg) | P_EXT);
627 631
628 - tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0); 632 + tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE);
629 /* bswap */ 633 /* bswap */
630 tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT); 634 tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT);
631 } 635 }
@@ -806,7 +810,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -806,7 +810,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
806 switch(opc) { 810 switch(opc) {
807 case 0: 811 case 0:
808 /* movb */ 812 /* movb */
809 - tcg_out_modrm_offset(s, 0x88, data_reg, r0, 0); 813 + tcg_out_modrm_offset(s, 0x88, data_reg, r0, GUEST_BASE);
810 break; 814 break;
811 case 1: 815 case 1:
812 if (bswap) { 816 if (bswap) {
@@ -818,7 +822,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -818,7 +822,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
818 } 822 }
819 /* movw */ 823 /* movw */
820 tcg_out8(s, 0x66); 824 tcg_out8(s, 0x66);
821 - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); 825 + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
822 break; 826 break;
823 case 2: 827 case 2:
824 if (bswap) { 828 if (bswap) {
@@ -828,21 +832,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -828,21 +832,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
828 data_reg = r1; 832 data_reg = r1;
829 } 833 }
830 /* movl */ 834 /* movl */
831 - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); 835 + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
832 break; 836 break;
833 case 3: 837 case 3:
834 if (bswap) { 838 if (bswap) {
835 tcg_out_mov(s, r1, data_reg2); 839 tcg_out_mov(s, r1, data_reg2);
836 /* bswap data_reg */ 840 /* bswap data_reg */
837 tcg_out_opc(s, (0xc8 + r1) | P_EXT); 841 tcg_out_opc(s, (0xc8 + r1) | P_EXT);
838 - tcg_out_modrm_offset(s, 0x89, r1, r0, 0); 842 + tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE);
839 tcg_out_mov(s, r1, data_reg); 843 tcg_out_mov(s, r1, data_reg);
840 /* bswap data_reg */ 844 /* bswap data_reg */
841 tcg_out_opc(s, (0xc8 + r1) | P_EXT); 845 tcg_out_opc(s, (0xc8 + r1) | P_EXT);
842 - tcg_out_modrm_offset(s, 0x89, r1, r0, 4); 846 + tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4);
843 } else { 847 } else {
844 - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0);  
845 - tcg_out_modrm_offset(s, 0x89, data_reg2, r0, 4); 848 + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE);
  849 + tcg_out_modrm_offset(s, 0x89, data_reg2, r0, GUEST_BASE + 4);
846 } 850 }
847 break; 851 break;
848 default: 852 default:
tcg/i386/tcg-target.h
@@ -53,6 +53,8 @@ enum { @@ -53,6 +53,8 @@ enum {
53 #define TCG_TARGET_HAS_ext16s_i32 53 #define TCG_TARGET_HAS_ext16s_i32
54 #define TCG_TARGET_HAS_rot_i32 54 #define TCG_TARGET_HAS_rot_i32
55 55
  56 +#define TCG_TARGET_HAS_GUEST_BASE
  57 +
56 /* Note: must be synced with dyngen-exec.h */ 58 /* Note: must be synced with dyngen-exec.h */
57 #define TCG_AREG0 TCG_REG_EBP 59 #define TCG_AREG0 TCG_REG_EBP
58 #define TCG_AREG1 TCG_REG_EBX 60 #define TCG_AREG1 TCG_REG_EBX
tcg/tcg.c
@@ -46,6 +46,7 @@ @@ -46,6 +46,7 @@
46 46
47 #include "qemu-common.h" 47 #include "qemu-common.h"
48 #include "cache-utils.h" 48 #include "cache-utils.h"
  49 +#include "host-utils.h"
49 50
50 /* Note: the long term plan is to reduce the dependancies on the QEMU 51 /* Note: the long term plan is to reduce the dependancies on the QEMU
51 CPU definitions. Currently they are used for qemu_ld/st 52 CPU definitions. Currently they are used for qemu_ld/st
@@ -57,6 +58,9 @@ @@ -57,6 +58,9 @@
57 #include "tcg-op.h" 58 #include "tcg-op.h"
58 #include "elf.h" 59 #include "elf.h"
59 60
  61 +#if defined(CONFIG_USE_GUEST_BASE) && !defined(TCG_TARGET_HAS_GUEST_BASE)
  62 +#error GUEST_BASE not supported on this host.
  63 +#endif
60 64
61 static void patch_reloc(uint8_t *code_ptr, int type, 65 static void patch_reloc(uint8_t *code_ptr, int type,
62 tcg_target_long value, tcg_target_long addend); 66 tcg_target_long value, tcg_target_long addend);
tcg/x86_64/tcg-target.c
@@ -508,6 +508,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -508,6 +508,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
508 int opc) 508 int opc)
509 { 509 {
510 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; 510 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
  511 + int32_t offset;
511 #if defined(CONFIG_SOFTMMU) 512 #if defined(CONFIG_SOFTMMU)
512 uint8_t *label1_ptr, *label2_ptr; 513 uint8_t *label1_ptr, *label2_ptr;
513 #endif 514 #endif
@@ -604,8 +605,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -604,8 +605,20 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
604 /* add x(r1), r0 */ 605 /* add x(r1), r0 */
605 tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 606 tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) -
606 offsetof(CPUTLBEntry, addr_read)); 607 offsetof(CPUTLBEntry, addr_read));
  608 + offset = 0;
607 #else 609 #else
608 - r0 = addr_reg; 610 + if (GUEST_BASE == (int32_t)GUEST_BASE) {
  611 + r0 = addr_reg;
  612 + offset = GUEST_BASE;
  613 + } else {
  614 + offset = 0;
  615 + /* movq $GUEST_BASE, r0 */
  616 + tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
  617 + tcg_out32(s, GUEST_BASE);
  618 + tcg_out32(s, GUEST_BASE >> 32);
  619 + /* addq addr_reg, r0 */
  620 + tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
  621 + }
609 #endif 622 #endif
610 623
611 #ifdef TARGET_WORDS_BIGENDIAN 624 #ifdef TARGET_WORDS_BIGENDIAN
@@ -616,15 +629,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -616,15 +629,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
616 switch(opc) { 629 switch(opc) {
617 case 0: 630 case 0:
618 /* movzbl */ 631 /* movzbl */
619 - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); 632 + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, offset);
620 break; 633 break;
621 case 0 | 4: 634 case 0 | 4:
622 /* movsbX */ 635 /* movsbX */
623 - tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, 0); 636 + tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, offset);
624 break; 637 break;
625 case 1: 638 case 1:
626 /* movzwl */ 639 /* movzwl */
627 - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); 640 + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
628 if (bswap) { 641 if (bswap) {
629 /* rolw $8, data_reg */ 642 /* rolw $8, data_reg */
630 tcg_out8(s, 0x66); 643 tcg_out8(s, 0x66);
@@ -635,7 +648,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -635,7 +648,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
635 case 1 | 4: 648 case 1 | 4:
636 if (bswap) { 649 if (bswap) {
637 /* movzwl */ 650 /* movzwl */
638 - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); 651 + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, offset);
639 /* rolw $8, data_reg */ 652 /* rolw $8, data_reg */
640 tcg_out8(s, 0x66); 653 tcg_out8(s, 0x66);
641 tcg_out_modrm(s, 0xc1, 0, data_reg); 654 tcg_out_modrm(s, 0xc1, 0, data_reg);
@@ -645,12 +658,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -645,12 +658,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
645 tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); 658 tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg);
646 } else { 659 } else {
647 /* movswX */ 660 /* movswX */
648 - tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, 0); 661 + tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, offset);
649 } 662 }
650 break; 663 break;
651 case 2: 664 case 2:
652 /* movl (r0), data_reg */ 665 /* movl (r0), data_reg */
653 - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); 666 + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
654 if (bswap) { 667 if (bswap) {
655 /* bswap */ 668 /* bswap */
656 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); 669 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
@@ -659,19 +672,19 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, @@ -659,19 +672,19 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args,
659 case 2 | 4: 672 case 2 | 4:
660 if (bswap) { 673 if (bswap) {
661 /* movl (r0), data_reg */ 674 /* movl (r0), data_reg */
662 - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); 675 + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, offset);
663 /* bswap */ 676 /* bswap */
664 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); 677 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0);
665 /* movslq */ 678 /* movslq */
666 tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); 679 tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg);
667 } else { 680 } else {
668 /* movslq */ 681 /* movslq */
669 - tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, 0); 682 + tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, offset);
670 } 683 }
671 break; 684 break;
672 case 3: 685 case 3:
673 /* movq (r0), data_reg */ 686 /* movq (r0), data_reg */
674 - tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, 0); 687 + tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, offset);
675 if (bswap) { 688 if (bswap) {
676 /* bswap */ 689 /* bswap */
677 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); 690 tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0);
@@ -691,6 +704,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -691,6 +704,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
691 int opc) 704 int opc)
692 { 705 {
693 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw; 706 int addr_reg, data_reg, r0, r1, mem_index, s_bits, bswap, rexw;
  707 + int32_t offset;
694 #if defined(CONFIG_SOFTMMU) 708 #if defined(CONFIG_SOFTMMU)
695 uint8_t *label1_ptr, *label2_ptr; 709 uint8_t *label1_ptr, *label2_ptr;
696 #endif 710 #endif
@@ -775,8 +789,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -775,8 +789,20 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
775 /* add x(r1), r0 */ 789 /* add x(r1), r0 */
776 tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) - 790 tcg_out_modrm_offset(s, 0x03 | P_REXW, r0, r1, offsetof(CPUTLBEntry, addend) -
777 offsetof(CPUTLBEntry, addr_write)); 791 offsetof(CPUTLBEntry, addr_write));
  792 + offset = 0;
778 #else 793 #else
779 - r0 = addr_reg; 794 + if (GUEST_BASE == (int32_t)GUEST_BASE) {
  795 + r0 = addr_reg;
  796 + offset = GUEST_BASE;
  797 + } else {
  798 + offset = 0;
  799 + /* movq $GUEST_BASE, r0 */
  800 + tcg_out_opc(s, (0xb8 + (r0 & 7)) | P_REXW, 0, r0, 0);
  801 + tcg_out32(s, GUEST_BASE);
  802 + tcg_out32(s, GUEST_BASE >> 32);
  803 + /* addq addr_reg, r0 */
  804 + tcg_out_modrm(s, 0x01 | P_REXW, addr_reg, r0);
  805 + }
780 #endif 806 #endif
781 807
782 #ifdef TARGET_WORDS_BIGENDIAN 808 #ifdef TARGET_WORDS_BIGENDIAN
@@ -787,7 +813,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -787,7 +813,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
787 switch(opc) { 813 switch(opc) {
788 case 0: 814 case 0:
789 /* movb */ 815 /* movb */
790 - tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, 0); 816 + tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, offset);
791 break; 817 break;
792 case 1: 818 case 1:
793 if (bswap) { 819 if (bswap) {
@@ -799,7 +825,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -799,7 +825,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
799 } 825 }
800 /* movw */ 826 /* movw */
801 tcg_out8(s, 0x66); 827 tcg_out8(s, 0x66);
802 - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); 828 + tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
803 break; 829 break;
804 case 2: 830 case 2:
805 if (bswap) { 831 if (bswap) {
@@ -809,7 +835,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -809,7 +835,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
809 data_reg = r1; 835 data_reg = r1;
810 } 836 }
811 /* movl */ 837 /* movl */
812 - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); 838 + tcg_out_modrm_offset(s, 0x89, data_reg, r0, offset);
813 break; 839 break;
814 case 3: 840 case 3:
815 if (bswap) { 841 if (bswap) {
@@ -819,7 +845,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, @@ -819,7 +845,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args,
819 data_reg = r1; 845 data_reg = r1;
820 } 846 }
821 /* movq */ 847 /* movq */
822 - tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, 0); 848 + tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, offset);
823 break; 849 break;
824 default: 850 default:
825 tcg_abort(); 851 tcg_abort();
tcg/x86_64/tcg-target.h
@@ -73,6 +73,8 @@ enum { @@ -73,6 +73,8 @@ enum {
73 #define TCG_TARGET_HAS_rot_i32 73 #define TCG_TARGET_HAS_rot_i32
74 #define TCG_TARGET_HAS_rot_i64 74 #define TCG_TARGET_HAS_rot_i64
75 75
  76 +#define TCG_TARGET_HAS_GUEST_BASE
  77 +
76 /* Note: must be synced with dyngen-exec.h */ 78 /* Note: must be synced with dyngen-exec.h */
77 #define TCG_AREG0 TCG_REG_R14 79 #define TCG_AREG0 TCG_REG_R14
78 #define TCG_AREG1 TCG_REG_R15 80 #define TCG_AREG1 TCG_REG_R15