diff options
author | Paul Brook <paul@codesourcery.com> | 2010-05-29 02:27:35 +0100 |
---|---|---|
committer | Paul Brook <paul@codesourcery.com> | 2010-05-29 02:27:35 +0100 |
commit | 68a1c816868b3e35a1da698af412b29e61b1948a (patch) | |
tree | 2f8ae184dd481d3a0e74d1de76fc7b53189fd97c /linux-user/main.c | |
parent | 0be1d07c0e4fa7395aca5129cfc5bb9a0a94a78c (diff) | |
download | qemu-68a1c816868b3e35a1da698af412b29e61b1948a.tar.gz qemu-68a1c816868b3e35a1da698af412b29e61b1948a.tar.bz2 qemu-68a1c816868b3e35a1da698af412b29e61b1948a.zip |
Pre-allocate guest address space
Allow pre-allocation of the guest virtual address space in usermode emulation.
Signed-off-by: Paul Brook <paul@codesourcery.com>
Diffstat (limited to 'linux-user/main.c')
-rw-r--r-- | linux-user/main.c | 63 |
1 files changed, 63 insertions, 0 deletions
diff --git a/linux-user/main.c b/linux-user/main.c index de1076b0af..0f23fc9cd9 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -44,6 +44,7 @@ unsigned long mmap_min_addr; #if defined(CONFIG_USE_GUEST_BASE) unsigned long guest_base; int have_guest_base; +unsigned long reserved_va; #endif static const char *interp_prefix = CONFIG_QEMU_PREFIX; @@ -2610,6 +2611,7 @@ static void usage(void) "-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" + "-R size reserve size bytes for guest virtual address space\n" #endif "\n" "Debug options:\n" @@ -2805,6 +2807,39 @@ int main(int argc, char **argv, char **envp) } else if (!strcmp(r, "B")) { guest_base = strtol(argv[optind++], NULL, 0); have_guest_base = 1; + } else if (!strcmp(r, "R")) { + char *p; + int shift = 0; + reserved_va = strtoul(argv[optind++], &p, 0); + switch (*p) { + case 'k': + case 'K': + shift = 10; + break; + case 'M': + shift = 20; + break; + case 'G': + shift = 30; + break; + } + if (shift) { + unsigned long unshifted = reserved_va; + p++; + reserved_va <<= shift; + if (((reserved_va >> shift) != unshifted) +#if HOST_LONG_BITS > TARGET_VIRT_ADDR_SPACE_BITS + || (reserved_va > (1ul << TARGET_VIRT_ADDR_SPACE_BITS)) +#endif + ) { + fprintf(stderr, "Reserved virtual address too big\n"); + exit(1); + } + } + if (*p) { + fprintf(stderr, "Unrecognised -R size suffix '%s'\n", p); + exit(1); + } #endif } else if (!strcmp(r, "drop-ld-preload")) { (void) envlist_unsetenv(envlist, "LD_PRELOAD"); @@ -2893,6 +2928,34 @@ int main(int argc, char **argv, char **envp) * proper page alignment for guest_base. */ guest_base = HOST_PAGE_ALIGN(guest_base); + + if (reserved_va) { + void *p; + int flags; + + flags = MAP_ANONYMOUS | MAP_PRIVATE | MAP_NORESERVE; + if (have_guest_base) { + flags |= MAP_FIXED; + } + p = mmap((void *)guest_base, reserved_va, PROT_NONE, flags, -1, 0); + if (p == MAP_FAILED) { + fprintf(stderr, "Unable to reserve guest address space\n"); + exit(1); + } + guest_base = (unsigned long)p; + /* Make sure the address is properly aligned. */ + if (guest_base & ~qemu_host_page_mask) { + munmap(p, reserved_va); + p = mmap((void *)guest_base, reserved_va + qemu_host_page_size, + PROT_NONE, flags, -1, 0); + if (p == MAP_FAILED) { + fprintf(stderr, "Unable to reserve guest address space\n"); + exit(1); + } + guest_base = HOST_PAGE_ALIGN((unsigned long)p); + } + qemu_log("Reserved 0x%lx bytes of guest address space\n", reserved_va); + } #endif /* CONFIG_USE_GUEST_BASE */ /* |