diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2018-03-22 11:10:36 +0000 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2018-03-22 11:10:37 +0000 |
commit | 3be2e41b3323169852dca11ffe6ff772c33e5aaa (patch) | |
tree | 634af6095c54758f1e83cb78fd52145489389e52 | |
parent | f1a63fcfcd92c88be8942b5ae71aef9749a4f135 (diff) | |
parent | 2a53535af471f4bee9d6cb5b363746b8d5ed21dd (diff) |
Merge remote-tracking branch 'remotes/vivier2/tags/linux-user-for-2.12-pull-request' into staging
# gpg: Signature made Tue 20 Mar 2018 20:43:37 GMT
# gpg: using RSA key F30C38BD3F2FBE3C
# gpg: Good signature from "Laurent Vivier <lvivier@redhat.com>"
# gpg: aka "Laurent Vivier <laurent@vivier.eu>"
# gpg: aka "Laurent Vivier (Red Hat) <lvivier@redhat.com>"
# Primary key fingerprint: CD2F 75DD C8E3 A4DC 2E4F 5173 F30C 38BD 3F2F BE3C
* remotes/vivier2/tags/linux-user-for-2.12-pull-request:
linux-user: init_guest_space: Try to make ARM space+commpage continuous
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r-- | linux-user/elfload.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/linux-user/elfload.c b/linux-user/elfload.c index 4563a3190b..23e34957f9 100644 --- a/linux-user/elfload.c +++ b/linux-user/elfload.c @@ -1889,6 +1889,55 @@ unsigned long init_guest_space(unsigned long host_start, /* Otherwise, a non-zero size region of memory needs to be mapped * and validated. */ + +#if defined(TARGET_ARM) && !defined(TARGET_AARCH64) + /* On 32-bit ARM, we need to map not just the usable memory, but + * also the commpage. Try to find a suitable place by allocating + * a big chunk for all of it. If host_start, then the naive + * strategy probably does good enough. + */ + if (!host_start) { + unsigned long guest_full_size, host_full_size, real_start; + + guest_full_size = + (0xffff0f00 & qemu_host_page_mask) + qemu_host_page_size; + host_full_size = guest_full_size - guest_start; + real_start = (unsigned long) + mmap(NULL, host_full_size, PROT_NONE, flags, -1, 0); + if (real_start == (unsigned long)-1) { + if (host_size < host_full_size - qemu_host_page_size) { + /* We failed to map a continous segment, but we're + * allowed to have a gap between the usable memory and + * the commpage where other things can be mapped. + * This sparseness gives us more flexibility to find + * an address range. + */ + goto naive; + } + return (unsigned long)-1; + } + munmap((void *)real_start, host_full_size); + if (real_start & ~qemu_host_page_mask) { + /* The same thing again, but with an extra qemu_host_page_size + * so that we can shift around alignment. + */ + unsigned long real_size = host_full_size + qemu_host_page_size; + real_start = (unsigned long) + mmap(NULL, real_size, PROT_NONE, flags, -1, 0); + if (real_start == (unsigned long)-1) { + if (host_size < host_full_size - qemu_host_page_size) { + goto naive; + } + return (unsigned long)-1; + } + munmap((void *)real_start, real_size); + real_start = HOST_PAGE_ALIGN(real_start); + } + current_start = real_start; + } + naive: +#endif + while (1) { unsigned long real_start, real_size, aligned_size; aligned_size = real_size = host_size; |