From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1M1KgZ-0000Jl-72 for qemu-devel@nongnu.org; Tue, 05 May 2009 09:27:51 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1M1KgY-0000Iy-6F for qemu-devel@nongnu.org; Tue, 05 May 2009 09:27:50 -0400 Received: from [199.232.76.173] (port=52789 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1M1KgX-0000Il-TP for qemu-devel@nongnu.org; Tue, 05 May 2009 09:27:50 -0400 Received: from naru.obs2.net ([84.20.150.76]:56536) by monty-python.gnu.org with esmtps (TLS-1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.60) (envelope-from ) id 1M1KgV-0002hC-D2 for qemu-devel@nongnu.org; Tue, 05 May 2009 09:27:48 -0400 Date: Tue, 5 May 2009 16:27:43 +0300 From: Riku Voipio Message-ID: <20090505132743.GA29021@kos.to> References: <1241028203-19687-1-git-send-email-riku.voipio@iki.fi> <1241028203-19687-6-git-send-email-riku.voipio@iki.fi> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: Subject: [Qemu-devel] [PATCH] Revived GUEST_BASE support for usermode emulation targets [v3] List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: malc Cc: mika.westerberg@iki.fi, qemu-devel@nongnu.org On Wed, Apr 29, 2009 at 11:50:47PM +0400, malc wrote: > After actually considering the whole picture neither MOV+ADD nor LEA > are needed at all, something like the following (i386 case, and not > tested): Thanks, tested, found out to work, and implemented case amd64 too. > P.S. BTW revived? Well, GUEST_BASE variable was there already, so we though that it has worked at some point of history, just that it bitrotted and broken. >>From 0f80be6130b37e0beaf4f1c2a2f2ff6633157113 Mon Sep 17 00:00:00 2001 From: Mika Westerberg Date: Sun, 29 Mar 2009 21:46:34 +0300 Subject: [PATCH 06/16] Revived GUEST_BASE support for usermode emulation targets [v3] From: Mika Westerberg - Now GUEST_BASE is dynamic and can be set from command line. - Qemu checks /proc/sys/vm/mmap_min_addr and sets GUEST_BASE if needed. - Code generation supports GUEST_BASE for i386 and x86_64 hosts. [v3]: implemented GUEST_BASE with offset mods Using malc's advice, instead of a mov or lea, just adjust the offset parameter of tcg_out_modrm_offset(). - Riku Signed-off-by: Riku Voipio --- configure | 9 +++++++ cpu-all.h | 6 ++++- linux-user/elfload.c | 24 ++++++++++++++++++++ linux-user/main.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++ linux-user/qemu.h | 3 ++ tcg/i386/tcg-target.c | 32 ++++++++++++++-------------- tcg/x86_64/tcg-target.c | 26 +++++++++++----------- 7 files changed, 124 insertions(+), 30 deletions(-) diff --git a/configure b/configure index 82fb60a..bc89227 100755 --- a/configure +++ b/configure @@ -178,6 +178,7 @@ softmmu="yes" linux_user="no" darwin_user="no" bsd_user="no" +guest_base="no" build_docs="no" uname_release="" curses="yes" @@ -457,6 +458,8 @@ for opt do ;; --enable-bsd-user) bsd_user="yes" ;; + --enable-guest-base) guest_base="yes" + ;; --enable-uname-release=*) uname_release="$optarg" ;; --sparc_cpu=*) @@ -611,6 +614,8 @@ echo " --enable-darwin-user enable all darwin usermode emulation targets" echo " --disable-darwin-user disable all darwin usermode emulation targets" echo " --enable-bsd-user enable all BSD usermode emulation targets" echo " --disable-bsd-user disable all BSD usermode emulation targets" +echo " --enable-guest-base enable GUEST_BASE support for usermode" +echo " emulation targets" echo " --fmod-lib path to FMOD library" echo " --fmod-inc path to FMOD includes" echo " --oss-lib path to OSS library" @@ -1335,6 +1340,7 @@ echo "Documentation $build_docs" [ ! -z "$uname_release" ] && \ echo "uname -r $uname_release" echo "NPTL support $nptl" +echo "GUEST_BASE $guest_base" echo "vde support $vde" echo "AIO support $aio" echo "IO thread $io_thread" @@ -2022,6 +2028,9 @@ if test "$target_user_only" = "yes" -a "$elfload32" = "yes"; then echo "TARGET_HAS_ELFLOAD32=yes" >> $config_mak echo "#define TARGET_HAS_ELFLOAD32 1" >> $config_h fi +if test "$target_user_only" = "yes" -a "$guest_base" = "yes"; then + echo "#define CONFIG_USE_GUEST_BASE 1" >> $config_h +fi if test "$target_bsd_user" = "yes" ; then echo "CONFIG_BSD_USER=yes" >> $config_mak echo "#define CONFIG_BSD_USER 1" >> $config_h diff --git a/cpu-all.h b/cpu-all.h index 676c4a9..4f87ee7 100644 --- a/cpu-all.h +++ b/cpu-all.h @@ -629,8 +629,12 @@ static inline void stfq_be_p(void *ptr, float64 v) /* On some host systems the guest address space is reserved on the host. * This allows the guest address space to be offset to a convenient location. */ -//#define GUEST_BASE 0x20000000 +#if defined(CONFIG_USE_GUEST_BASE) +extern unsigned long guest_base; +#define GUEST_BASE guest_base +#else #define GUEST_BASE 0 +#endif /* All direct uses of g2h and h2g need to go away for usermode softmmu. */ #define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) diff --git a/linux-user/elfload.c b/linux-user/elfload.c index dc797bd..b5565dd 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1466,6 +1466,30 @@ int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * regs, info->mmap = 0; elf_entry = (abi_ulong) elf_ex.e_entry; +#if defined(CONFIG_USE_GUEST_BASE) + /* + * In case where user has not explicitly set the guest_base, we + * probe here that should we set it automatically. + */ + if (guest_base == 0) { + /* + * Go through ELF program header table and find out whether + * any of the segments drop below our current mmap_min_addr and + * in that case set guest_base to corresponding address. + */ + for (i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum; + i++, elf_ppnt++) { + if (elf_ppnt->p_type != PT_LOAD) + continue; + if (HOST_PAGE_ALIGN(elf_ppnt->p_vaddr) < mmap_min_addr) { + guest_base = HOST_PAGE_ALIGN(mmap_min_addr); + qemu_log("setting guest_base=0x%lx\n", guest_base); + break; + } + } + } +#endif /* CONFIG_USE_GUEST_BASE */ + /* Do this so that we can load the interpreter, if need be. We will change some of these later */ info->rss = 0; diff --git a/linux-user/main.c b/linux-user/main.c index 72734c1..64b1ff0 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -41,6 +41,10 @@ char *exec_path; int singlestep; +#if defined(CONFIG_USE_GUEST_BASE) +unsigned long mmap_min_addr = 0; +unsigned long guest_base = 0; +#endif static const char *interp_prefix = CONFIG_QEMU_PREFIX; const char *qemu_uname_release = CONFIG_UNAME_RELEASE; @@ -2229,6 +2233,9 @@ static void usage(void) "-E var=value sets/modifies targets environment variable(s)\n" "-U var unsets targets environment variable(s)\n" "-0 argv0 forces target process argv[0] to be argv0\n" +#if defined(CONFIG_USE_GUEST_BASE) + "-B address set guest_base address to address\n" +#endif "\n" "Debug options:\n" "-d options activate log (logfile=%s)\n" @@ -2403,6 +2410,10 @@ int main(int argc, char **argv, char **envp) #endif exit(1); } +#if defined(CONFIG_USE_GUEST_BASE) + } else if (!strcmp(r, "B")) { + guest_base = strtol(argv[optind++], NULL, 0); +#endif } else if (!strcmp(r, "drop-ld-preload")) { (void) envlist_unsetenv(envlist, "LD_PRELOAD"); } else if (!strcmp(r, "singlestep")) { @@ -2480,6 +2491,36 @@ int main(int argc, char **argv, char **envp) target_environ = envlist_to_environ(envlist, NULL); envlist_free(envlist); +#if defined(CONFIG_USE_GUEST_BASE) + /* + * Now that page sizes are configured in cpu_init() we can do + * proper page alignment for guest_base. + */ + guest_base = HOST_PAGE_ALIGN(guest_base); + + /* + * Read in mmap_min_addr kernel parameter and check + * whether it is set to some value > 0. This value is used + * later on when doing mmap(2)s to calculate where guest_base + * is to set, if needed. + * + * When user has explicitly set the quest base, we skip this + * test. + */ + if (guest_base == 0) { + FILE *fp; + + if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) { + unsigned long tmp; + if (fscanf(fp, "%lu", &tmp) == 1) { + mmap_min_addr = tmp; + qemu_log("kernel mmap_min_addr=%lu\n", mmap_min_addr); + } + fclose(fp); + } + } +#endif /* CONFIG_USE_GUEST_BASE */ + /* * Prepare copy of argv vector for target. */ @@ -2529,6 +2570,19 @@ int main(int argc, char **argv, char **envp) free(target_environ); if (qemu_log_enabled()) { +#if defined(CONFIG_USE_GUEST_BASE) + if (guest_base > 0) { + qemu_log("guest_base is set to 0x%lx\n", guest_base); + qemu_log( + "==========================================================\n" + "Note that all target addresses below are given in target\n" + "address space which is different from host by guest_base.\n" + "For example: target address 0x" TARGET_ABI_FMT_lx " becomes\n" + "%p and so on.\n" + "==========================================================\n", + (abi_ulong)0x8000, g2h(0x8000)); + } +#endif log_page_dump(); qemu_log("start_brk 0x" TARGET_ABI_FMT_lx "\n", info->start_brk); diff --git a/linux-user/qemu.h b/linux-user/qemu.h index ea4a57d..762f31f 100644 --- a/linux-user/qemu.h +++ b/linux-user/qemu.h @@ -133,6 +133,9 @@ void init_task_state(TaskState *ts); void task_settid(TaskState *); void stop_all_tasks(void); extern const char *qemu_uname_release; +#if defined(CONFIG_USE_GUEST_BASE) +extern unsigned long mmap_min_addr; +#endif /* ??? See if we can avoid exposing so much of the loader internals. */ /* diff --git a/tcg/i386/tcg-target.c b/tcg/i386/tcg-target.c index e0fd434..b73ab30 100644 --- a/tcg/i386/tcg-target.c +++ b/tcg/i386/tcg-target.c @@ -572,15 +572,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, switch(opc) { case 0: /* movzbl */ - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE); break; case 0 | 4: /* movsbl */ - tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xbe | P_EXT, data_reg, r0, GUEST_BASE); break; case 1: /* movzwl */ - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE); if (bswap) { /* rolw $8, data_reg */ tcg_out8(s, 0x66); @@ -590,7 +590,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, break; case 1 | 4: /* movswl */ - tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xbf | P_EXT, data_reg, r0, GUEST_BASE); if (bswap) { /* rolw $8, data_reg */ tcg_out8(s, 0x66); @@ -603,7 +603,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, break; case 2: /* movl (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE); if (bswap) { /* bswap */ tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); @@ -619,13 +619,13 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, r0 = r1; } if (!bswap) { - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); - tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 4); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE); + tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE + 4); } else { - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 4); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE + 4); tcg_out_opc(s, (0xc8 + data_reg) | P_EXT); - tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, 0); + tcg_out_modrm_offset(s, 0x8b, data_reg2, r0, GUEST_BASE); /* bswap */ tcg_out_opc(s, (0xc8 + data_reg2) | P_EXT); } @@ -806,7 +806,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, switch(opc) { case 0: /* movb */ - tcg_out_modrm_offset(s, 0x88, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x88, data_reg, r0, GUEST_BASE); break; case 1: if (bswap) { @@ -818,7 +818,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, } /* movw */ tcg_out8(s, 0x66); - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); break; case 2: if (bswap) { @@ -828,21 +828,21 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, data_reg = r1; } /* movl */ - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); break; case 3: if (bswap) { tcg_out_mov(s, r1, data_reg2); /* bswap data_reg */ tcg_out_opc(s, (0xc8 + r1) | P_EXT); - tcg_out_modrm_offset(s, 0x89, r1, r0, 0); + tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE); tcg_out_mov(s, r1, data_reg); /* bswap data_reg */ tcg_out_opc(s, (0xc8 + r1) | P_EXT); - tcg_out_modrm_offset(s, 0x89, r1, r0, 4); + tcg_out_modrm_offset(s, 0x89, r1, r0, GUEST_BASE + 4); } else { - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); - tcg_out_modrm_offset(s, 0x89, data_reg2, r0, 4); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); + tcg_out_modrm_offset(s, 0x89, data_reg2, r0, GUEST_BASE + 4); } break; default: diff --git a/tcg/x86_64/tcg-target.c b/tcg/x86_64/tcg-target.c index 5378e85..e239dcb 100644 --- a/tcg/x86_64/tcg-target.c +++ b/tcg/x86_64/tcg-target.c @@ -616,15 +616,15 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, switch(opc) { case 0: /* movzbl */ - tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb6 | P_EXT, data_reg, r0, GUEST_BASE); break; case 0 | 4: /* movsbX */ - tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xbe | P_EXT | rexw, data_reg, r0, GUEST_BASE); break; case 1: /* movzwl */ - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE); if (bswap) { /* rolw $8, data_reg */ tcg_out8(s, 0x66); @@ -635,7 +635,7 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, case 1 | 4: if (bswap) { /* movzwl */ - tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xb7 | P_EXT, data_reg, r0, GUEST_BASE); /* rolw $8, data_reg */ tcg_out8(s, 0x66); tcg_out_modrm(s, 0xc1, 0, data_reg); @@ -645,12 +645,12 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, tcg_out_modrm(s, 0xbf | P_EXT | rexw, data_reg, data_reg); } else { /* movswX */ - tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0xbf | P_EXT | rexw, data_reg, r0, GUEST_BASE); } break; case 2: /* movl (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE); if (bswap) { /* bswap */ tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); @@ -659,19 +659,19 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, case 2 | 4: if (bswap) { /* movl (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b, data_reg, r0, GUEST_BASE); /* bswap */ tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT, 0, data_reg, 0); /* movslq */ tcg_out_modrm(s, 0x63 | P_REXW, data_reg, data_reg); } else { /* movslq */ - tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x63 | P_REXW, data_reg, r0, GUEST_BASE); } break; case 3: /* movq (r0), data_reg */ - tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x8b | P_REXW, data_reg, r0, GUEST_BASE); if (bswap) { /* bswap */ tcg_out_opc(s, (0xc8 + (data_reg & 7)) | P_EXT | P_REXW, 0, data_reg, 0); @@ -787,7 +787,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, switch(opc) { case 0: /* movb */ - tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x88 | P_REXB, data_reg, r0, GUEST_BASE); break; case 1: if (bswap) { @@ -799,7 +799,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, } /* movw */ tcg_out8(s, 0x66); - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); break; case 2: if (bswap) { @@ -809,7 +809,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, data_reg = r1; } /* movl */ - tcg_out_modrm_offset(s, 0x89, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89, data_reg, r0, GUEST_BASE); break; case 3: if (bswap) { @@ -819,7 +819,7 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, data_reg = r1; } /* movq */ - tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, 0); + tcg_out_modrm_offset(s, 0x89 | P_REXW, data_reg, r0, GUEST_BASE); break; default: tcg_abort(); -- 1.6.2.1