aboutsummaryrefslogtreecommitdiff
path: root/bsd-user
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2023-07-27 09:11:48 -0700
committerRichard Henderson <richard.henderson@linaro.org>2023-07-31 12:19:13 -0700
commit28b61d49ac80bac8ef74aff0b75058bdd0b2f108 (patch)
tree0977685b89a4ff2b5f89de5155ae8e5c06de6633 /bsd-user
parentad17868eb162a5466d8ad43e5ccb428776403308 (diff)
bsd-user: Allocate guest virtual address space
With reserved_va, mmap.c expects to have pre-allocated host address space for the entire guest address space. When combined with the -B command-line option, ensure that the chosen address does not overlap anything else. Ensure that mmap_next_start is within reserved_va, as we use it within mmap.c without checking. Reviewed by: Warner Losh <imp@bsdimp.com> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-Id: <20230727161148.444988-1-richard.henderson@linaro.org>
Diffstat (limited to 'bsd-user')
-rw-r--r--bsd-user/main.c48
1 files changed, 43 insertions, 5 deletions
diff --git a/bsd-user/main.c b/bsd-user/main.c
index b597328118..381bb18df8 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -473,10 +473,6 @@ int main(int argc, char **argv)
target_environ = envlist_to_environ(envlist, NULL);
envlist_free(envlist);
- if (reserved_va) {
- mmap_next_start = reserved_va + 1;
- }
-
{
Error *err = NULL;
if (seed_optarg != NULL) {
@@ -494,7 +490,49 @@ int main(int argc, char **argv)
* Now that page sizes are configured we can do
* proper page alignment for guest_base.
*/
- guest_base = HOST_PAGE_ALIGN(guest_base);
+ if (have_guest_base) {
+ if (guest_base & ~qemu_host_page_mask) {
+ error_report("Selected guest base not host page aligned");
+ exit(1);
+ }
+ }
+
+ /*
+ * If reserving host virtual address space, do so now.
+ * Combined with '-B', ensure that the chosen range is free.
+ */
+ if (reserved_va) {
+ void *p;
+
+ if (have_guest_base) {
+ p = mmap((void *)guest_base, reserved_va + 1, PROT_NONE,
+ MAP_ANON | MAP_PRIVATE | MAP_FIXED | MAP_EXCL, -1, 0);
+ } else {
+ p = mmap(NULL, reserved_va + 1, PROT_NONE,
+ MAP_ANON | MAP_PRIVATE, -1, 0);
+ }
+ if (p == MAP_FAILED) {
+ const char *err = strerror(errno);
+ char *sz = size_to_str(reserved_va + 1);
+
+ if (have_guest_base) {
+ error_report("Cannot allocate %s bytes at -B %p for guest "
+ "address space: %s", sz, (void *)guest_base, err);
+ } else {
+ error_report("Cannot allocate %s bytes for guest "
+ "address space: %s", sz, err);
+ }
+ exit(1);
+ }
+ guest_base = (uintptr_t)p;
+ have_guest_base = true;
+
+ /* Ensure that mmap_next_start is within range. */
+ if (reserved_va <= mmap_next_start) {
+ mmap_next_start = (reserved_va / 4 * 3)
+ & TARGET_PAGE_MASK & qemu_host_page_mask;
+ }
+ }
if (loader_exec(filename, argv + optind, target_environ, regs, info,
&bprm) != 0) {