On 06/27/2012 12:32 PM, Richard Henderson wrote: > On 06/27/2012 08:51 AM, Meador Inge wrote: >> To solve this issue I experimented with performing a similar probing in >> 'main' >> as in 'probe_guest_base' so that we can find a reserved VA region that also >> passes validation. If a region isn't found that can be validated, then QEMU >> gives up. Does this approach seem reasonable? > > I guess so, depending on how you adjust the hint each time.
What I am currently experimenting with is essentially the same as what is in 'probe_guest_base'. So something like (not an actually patch submission, just listing this here for discussion): Index: linux-user/main.c =================================================================== --- linux-user/main.c (revision 376549) +++ linux-user/main.c (working copy) @@ -3486,35 +3486,53 @@ int main(int argc, char **argv, char **e guest_base = HOST_PAGE_ALIGN(guest_base); if (reserved_va) { - void *p; + unsigned long host_start, real_start, first_start, host_size; 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) { + + first_start = host_start = HOST_PAGE_ALIGN(guest_base); + while (1) { + host_size = reserved_va; + real_start = (unsigned long) mmap((void *)host_start, host_size, + PROT_NONE, flags, -1, 0); + if (real_start == (unsigned long)-1) { + fprintf(stderr, "Unable to reserve guest address space\n"); + exit(1); + } + guest_base = host_start; + /* Make sure the address is properly aligned. */ + if (guest_base & ~qemu_host_page_mask) { + munmap((void*)real_start, host_size); + host_size += qemu_host_page_size; + real_start = (unsigned long) mmap((void *)guest_base, + host_size, + PROT_NONE, flags, -1, 0); + if (real_start == (unsigned long)-1) { + fprintf(stderr, "Unable to reserve guest address space\n"); + exit(1); + } + guest_base = HOST_PAGE_ALIGN(real_start); + } + + if (guest_validate_base(guest_base)) + break; + + munmap((void *)real_start, host_size); + host_start += qemu_host_page_size; + if (host_start == first_start) { 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); mmap_next_start = reserved_va; } - if (reserved_va || have_guest_base) { + if (have_guest_base) { if (!guest_validate_base(guest_base)) { fprintf(stderr, "Guest base/Reserved VA rejected by guest code\n"); exit(1); > I do wonder if it wouldn't be better to rearrange things such that > for 64-bit hosts and 32-bit guests we *always* reserve 4G so that > there's zero possibility of the guest stomping on host memory. That > would also solve your problem. I am seeing problems with 32-on-32 where the ARM commpage check wraps around (incidentally I also ran into problems with -B because for some values of guest_base it is easy for guest_base >= min_mmap_addr and guest_base + kernel_helper_addr < min_mmap_addr to hold). -- Meador Inge CodeSourcery / Mentor Embedded http://www.mentor.com/embedded-software