[PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()

Mohamed Ayman posted 1 patch 4 weeks, 1 day ago
Patches applied successfully (tree, apply log)
git fetch https://github.com/patchew-project/qemu tags/patchew/20260501161106.818373-1-mohamedaymanworkspace@gmail.com
Maintainers: Warner Losh <imp@bsdimp.com>, Kyle Evans <kevans@freebsd.org>
There is a newer version of this series
bsd-user/elfload.c |  25 ++---------
bsd-user/main.c    |  14 ++-----
bsd-user/mmap.c    | 102 ++++++++++++++++-----------------------------
bsd-user/qemu.h    |  10 ++---
4 files changed, 46 insertions(+), 105 deletions(-)
[PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Mohamed Ayman 4 weeks, 1 day ago
The bsd-user implementation previously cached host page size and mask
in global variables (qemu_host_page_size and qemu_host_page_mask),
which duplicated information already available through
qemu_real_host_page_size().

This introduced unnecessary global state and potential inconsistencies
if the host page size is queried or changes during initialization.

Replace all usages of qemu_host_page_size and qemu_host_page_mask with
HOST_PAGE_SIZE and HOST_PAGE_MASK macros defined as:

  MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)

This preserves the original behavior where the effective host page size
is the maximum of the real host page size and the target page size,
which matters on targets like aarch64 with 16K pages running on an
amd64 host with 4K pages.

This also opens the way for renaming qemu_real_host_page_size() to
qemu_host_page_size() now that the bsd-user globals no longer occupy
that name.

Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com>
---
 bsd-user/elfload.c |  25 ++---------
 bsd-user/main.c    |  14 ++-----
 bsd-user/mmap.c    | 102 ++++++++++++++++-----------------------------
 bsd-user/qemu.h    |  10 ++---
 4 files changed, 46 insertions(+), 105 deletions(-)

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 3bca0cc9ed..00250fc3c1 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -192,14 +192,14 @@ static void setup_arg_pages(struct bsd_binprm *bprm, struct image_info *info,
      */
     size = target_dflssiz;
     stack_base = TARGET_USRSTACK - size;
-    addr = target_mmap(stack_base , size + qemu_host_page_size,
+    addr = target_mmap(stack_base , size + HOST_PAGE_SIZE,
             PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
     if (addr == -1) {
         perror("stk mmap");
         exit(-1);
     }
     /* we reserve one extra page at the top of the stack as guard */
-    target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
+    target_mprotect(addr + size, HOST_PAGE_SIZE, PROT_NONE);
 
     target_stksiz = size;
     target_stkbas = addr;
@@ -239,27 +239,10 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
         return;
     }
 
-    /*
-     * XXX: this is really a hack : if the real host page size is
-     * smaller than the target page size, some pages after the end
-     * of the file may not be mapped. A better fix would be to
-     * patch target_mmap(), but it is more complicated as the file
-     * size must be known.
-     */
-    if (qemu_real_host_page_size() < qemu_host_page_size) {
-        abi_ulong end_addr, end_addr1;
-        end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
-        end_addr = HOST_PAGE_ALIGN(elf_bss);
-        if (end_addr1 < end_addr) {
-            mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
-                 PROT_READ | PROT_WRITE | PROT_EXEC,
-                 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
-        }
-    }
 
-    nbyte = elf_bss & (qemu_host_page_size - 1);
+    nbyte = elf_bss & (HOST_PAGE_SIZE - 1);
     if (nbyte) {
-        nbyte = qemu_host_page_size - nbyte;
+        nbyte = HOST_PAGE_SIZE - nbyte;
         do {
             /* FIXME - what to do if put_user() fails? */
             put_user_u8(0, elf_bss);
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 73aae8c327..3f5141e794 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -54,11 +54,6 @@
 #include "target_arch_cpu.h"
 
 
-/*
- * TODO: Remove these and rely only on qemu_real_host_page_size().
- */
-uintptr_t qemu_host_page_size;
-intptr_t qemu_host_page_mask;
 
 static bool opt_one_insn_per_tb;
 static unsigned long opt_tb_size;
@@ -302,8 +297,6 @@ int main(int argc, char **argv)
         (void) envlist_setenv(envlist, *wrk);
     }
 
-    qemu_host_page_size = getpagesize();
-    qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);
 
     cpu_model = NULL;
 
@@ -405,7 +398,6 @@ int main(int argc, char **argv)
         }
     }
 
-    qemu_host_page_mask = -qemu_host_page_size;
 
     /* init debug */
     {
@@ -452,7 +444,7 @@ int main(int argc, char **argv)
 
     cpu_type = parse_cpu_option(cpu_model);
 
-    /* init tcg before creating CPUs and to get qemu_host_page_size */
+    /* init tcg before creating CPUs */
     {
         AccelState *accel = current_accel();
         AccelClass *ac = ACCEL_GET_CLASS(accel);
@@ -534,7 +526,7 @@ int main(int argc, char **argv)
      * proper page alignment for guest_base.
      */
     if (have_guest_base) {
-        if (guest_base & ~qemu_host_page_mask) {
+        if (guest_base & ~HOST_PAGE_MASK) {
             error_report("Selected guest base not host page aligned");
             exit(1);
         }
@@ -573,7 +565,7 @@ int main(int argc, char **argv)
         /* 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;
+                              & TARGET_PAGE_MASK & HOST_PAGE_MASK;
         }
     }
 
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index fe77eceb48..59c70083a4 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -84,7 +84,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
         return 0;
 
     mmap_lock();
-    host_start = start & qemu_host_page_mask;
+    host_start = start & HOST_PAGE_MASK;
     host_end = HOST_PAGE_ALIGN(end);
     if (start > host_start) {
         /* handle host page containing start */
@@ -92,28 +92,28 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
         for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot1 |= page_get_flags(addr);
         }
-        if (host_end == host_start + qemu_host_page_size) {
+        if (host_end == host_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
                 prot1 |= page_get_flags(addr);
             }
             end = host_end;
         }
         ret = mprotect(g2h_untagged(host_start),
-                       qemu_host_page_size, prot1 & PAGE_RWX);
+                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
         if (ret != 0)
             goto error;
-        host_start += qemu_host_page_size;
+        host_start += HOST_PAGE_SIZE;
     }
     if (end < host_end) {
         prot1 = prot;
         for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
             prot1 |= page_get_flags(addr);
         }
-        ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
-                       qemu_host_page_size, prot1 & PAGE_RWX);
+        ret = mprotect(g2h_untagged(host_end - HOST_PAGE_SIZE),
+                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
         if (ret != 0)
             goto error;
-        host_end -= qemu_host_page_size;
+        host_end -= HOST_PAGE_SIZE;
     }
 
     /* handle the pages in the middle */
@@ -193,7 +193,7 @@ static int mmap_frag(abi_ulong real_start,
     void *host_start;
     int prot1, prot_new;
 
-    real_end = real_start + qemu_host_page_size;
+    real_end = real_start + HOST_PAGE_SIZE;
     host_start = g2h_untagged(real_start);
 
     /* get the protection of the target pages outside the mapping */
@@ -205,7 +205,7 @@ static int mmap_frag(abi_ulong real_start,
 
     if (prot1 == 0) {
         /* no page was there, so we allocate one. See also above. */
-        void *p = mmap(host_start, qemu_host_page_size, prot,
+        void *p = mmap(host_start, HOST_PAGE_SIZE, prot,
                        flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
         if (p == MAP_FAILED)
             return -1;
@@ -223,7 +223,7 @@ static int mmap_frag(abi_ulong real_start,
 
         /* adjust protection to be able to read */
         if (!(prot1 & PROT_WRITE))
-            mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
+            mprotect(host_start, HOST_PAGE_SIZE, prot1 | PROT_WRITE);
 
         /* read the corresponding file data */
         if (!mmap_pread(fd, g2h_untagged(start), end - start, offset, true)) {
@@ -232,10 +232,10 @@ static int mmap_frag(abi_ulong real_start,
 
         /* put final protection */
         if (prot_new != (prot1 | PROT_WRITE))
-            mprotect(host_start, qemu_host_page_size, prot_new);
+            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
     } else {
         if (prot_new != prot1) {
-            mprotect(host_start, qemu_host_page_size, prot_new);
+            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
         }
         if (prot_new & PROT_WRITE) {
             memset(g2h_untagged(start), 0, end - start);
@@ -289,7 +289,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment)
     if (start == 0) {
         start = mmap_next_start;
     } else {
-        start &= qemu_host_page_mask;
+        start &= HOST_PAGE_MASK;
     }
 
     size = HOST_PAGE_ALIGN(size);
@@ -297,7 +297,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment)
     if (reserved_va) {
         return mmap_find_vma_reserved(start, size,
             (alignment != 0 ? 1 << alignment :
-             MAX(qemu_host_page_size, TARGET_PAGE_SIZE)));
+             MAX(HOST_PAGE_SIZE, TARGET_PAGE_SIZE)));
     }
 
     addr = start;
@@ -478,8 +478,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         goto fail;
     }
 
-    real_start = start & qemu_host_page_mask;
-    host_offset = offset & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
+    host_offset = offset & HOST_PAGE_MASK;
 
     /*
      * If the user is asking for the kernel to find a location, do that
@@ -498,38 +498,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         }
     }
 
-    /*
-     * When mapping files into a memory area larger than the file, accesses
-     * to pages beyond the file size will cause a SIGBUS.
-     *
-     * For example, if mmaping a file of 100 bytes on a host with 4K pages
-     * emulating a target with 8K pages, the target expects to be able to
-     * access the first 8K. But the host will trap us on any access beyond
-     * 4K.
-     *
-     * When emulating a target with a larger page-size than the hosts, we
-     * may need to truncate file maps at EOF and add extra anonymous pages
-     * up to the targets page boundary.
-     */
-
-    if ((qemu_real_host_page_size() < qemu_host_page_size) && fd != -1) {
-        struct stat sb;
-
-        if (fstat(fd, &sb) == -1) {
-            goto fail;
-        }
-
-        /* Are we trying to create a map beyond EOF?.  */
-        if (offset + len > sb.st_size) {
-            /*
-             * If so, truncate the file map at eof aligned with
-             * the hosts real pagesize. Additional anonymous maps
-             * will be created beyond EOF.
-             */
-            len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
-        }
-    }
-
     if (!(flags & MAP_FIXED)) {
         unsigned long host_start;
         void *p;
@@ -539,8 +507,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
 
         /*
          * Note: we prefer to control the mapping address. It is
-         * especially important if qemu_host_page_size >
-         * qemu_real_host_page_size
+         * especially important if HOST_PAGE_SIZE >
+         * TARGET_PAGE_SIZE
          */
         p = mmap(g2h_untagged(start), host_len, prot,
                  flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
@@ -581,7 +549,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
          * aligned, so we read it
          */
         if (fd != -1 &&
-            (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
+            (offset & ~HOST_PAGE_MASK) != (start & ~HOST_PAGE_MASK)) {
             /*
              * msync() won't work here, so we return an error if write is
              * possible while it is a shared mapping
@@ -614,7 +582,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
 
         /* handle the start of the mapping */
         if (start > real_start) {
-            if (real_end == real_start + qemu_host_page_size) {
+            if (real_end == real_start + HOST_PAGE_SIZE) {
                 /* one single host page */
                 ret = mmap_frag(real_start, start, end,
                                 prot, flags, fd, offset);
@@ -622,21 +590,21 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
                     goto fail;
                 goto the_end1;
             }
-            ret = mmap_frag(real_start, start, real_start + qemu_host_page_size,
+            ret = mmap_frag(real_start, start, real_start + HOST_PAGE_SIZE,
                             prot, flags, fd, offset);
             if (ret == -1)
                 goto fail;
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
         }
         /* handle the end of the mapping */
         if (end < real_end) {
-            ret = mmap_frag(real_end - qemu_host_page_size,
-                            real_end - qemu_host_page_size, end,
+            ret = mmap_frag(real_end - HOST_PAGE_SIZE,
+                            real_end - HOST_PAGE_SIZE, end,
                             prot, flags, fd,
-                            offset + real_end - qemu_host_page_size - start);
+                            offset + real_end - HOST_PAGE_SIZE - start);
             if (ret == -1)
                 goto fail;
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
         }
 
         /* map the middle (easier) */
@@ -676,7 +644,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
     abi_ulong end;
     int prot;
 
-    real_start = start & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
     real_end = HOST_PAGE_ALIGN(start + size);
     end = start + size;
     if (start > real_start) {
@@ -685,14 +653,14 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
         for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot |= page_get_flags(addr);
         }
-        if (real_end == real_start + qemu_host_page_size) {
+        if (real_end == real_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
                 prot |= page_get_flags(addr);
             }
             end = real_end;
         }
         if (prot != 0) {
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
         }
     }
     if (end < real_end) {
@@ -701,7 +669,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
             prot |= page_get_flags(addr);
         }
         if (prot != 0) {
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
         }
     }
     if (real_start != real_end) {
@@ -727,7 +695,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
         return -EINVAL;
     mmap_lock();
     end = start + len;
-    real_start = start & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
     real_end = HOST_PAGE_ALIGN(end);
 
     if (start > real_start) {
@@ -736,14 +704,14 @@ int target_munmap(abi_ulong start, abi_ulong len)
         for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot |= page_get_flags(addr);
         }
-        if (real_end == real_start + qemu_host_page_size) {
+        if (real_end == real_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
                 prot |= page_get_flags(addr);
             }
             end = real_end;
         }
         if (prot != 0)
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
     }
     if (end < real_end) {
         prot = 0;
@@ -751,7 +719,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
             prot |= page_get_flags(addr);
         }
         if (prot != 0)
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
     }
 
     ret = 0;
@@ -784,6 +752,6 @@ int target_msync(abi_ulong start, abi_ulong len, int flags)
     if (end == start)
         return 0;
 
-    start &= qemu_host_page_mask;
+    start &= HOST_PAGE_MASK;
     return msync(g2h_untagged(start), end - start, flags);
 }
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index b0b2c249fb..7553ac154c 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -44,12 +44,10 @@ extern char **environ;
 #include "accel/tcg/vcpu-state.h"
 
 #include "qemu-os.h"
-/*
- * TODO: Remove these and rely only on qemu_real_host_page_size().
- */
-extern uintptr_t qemu_host_page_size;
-extern intptr_t qemu_host_page_mask;
-#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
+
+#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
+#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
+#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)
 
 /*
  * This struct is used to hold certain information about the image.  Basically,
-- 
2.34.1
Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Richard Henderson 3 weeks, 3 days ago
On 5/1/26 11:11, Mohamed Ayman wrote:
> +++ b/bsd-user/qemu.h
> @@ -44,12 +44,10 @@ extern char **environ;
>   #include "accel/tcg/vcpu-state.h"
>   
>   #include "qemu-os.h"
> -/*
> - * TODO: Remove these and rely only on qemu_real_host_page_size().
> - */
> -extern uintptr_t qemu_host_page_size;
> -extern intptr_t qemu_host_page_mask;
> -#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
> +
> +#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
> +#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
> +#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)

This is a bad idea, hiding the true size of the host page.

There are oodles of corner cases that require the exact size of the host page.  If you 
hide this in a macro, you are going to stumble over them all of the time.


r~
Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Warner Losh 3 weeks, 3 days ago
On Tue, May 5, 2026 at 4:40 PM Richard Henderson <
richard.henderson@linaro.org> wrote:

> On 5/1/26 11:11, Mohamed Ayman wrote:
> > +++ b/bsd-user/qemu.h
> > @@ -44,12 +44,10 @@ extern char **environ;
> >   #include "accel/tcg/vcpu-state.h"
> >
> >   #include "qemu-os.h"
> > -/*
> > - * TODO: Remove these and rely only on qemu_real_host_page_size().
> > - */
> > -extern uintptr_t qemu_host_page_size;
> > -extern intptr_t qemu_host_page_mask;
> > -#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
> > +
> > +#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(),
> TARGET_PAGE_SIZE)
> > +#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
> > +#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)
>
> This is a bad idea, hiding the true size of the host page.
>
> There are oodles of corner cases that require the exact size of the host
> page.  If you
> hide this in a macro, you are going to stumble over them all of the time.
>

Yes. I've thought about writing test cases for maybe aarch64 16k page
binaries on a 4k x86_64 mahine.
I don't suppose there's tests like that for linux-user today?

Thinking about it for a couple of minutes, I think not hiding it, and
keeping the chunk that was deleted will
make sense. But I've not pondered all the edge cases in detail yet.

Warner
Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Richard Henderson 3 weeks, 3 days ago
On 5/5/26 17:52, Warner Losh wrote:
> 
> 
> On Tue, May 5, 2026 at 4:40 PM Richard Henderson <richard.henderson@linaro.org 
> <mailto:richard.henderson@linaro.org>> wrote:
> 
>     On 5/1/26 11:11, Mohamed Ayman wrote:
>      > +++ b/bsd-user/qemu.h
>      > @@ -44,12 +44,10 @@ extern char **environ;
>      >   #include "accel/tcg/vcpu-state.h"
>      >
>      >   #include "qemu-os.h"
>      > -/*
>      > - * TODO: Remove these and rely only on qemu_real_host_page_size().
>      > - */
>      > -extern uintptr_t qemu_host_page_size;
>      > -extern intptr_t qemu_host_page_mask;
>      > -#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
>      > +
>      > +#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
>      > +#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
>      > +#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)
> 
>     This is a bad idea, hiding the true size of the host page.
> 
>     There are oodles of corner cases that require the exact size of the host page.  If you
>     hide this in a macro, you are going to stumble over them all of the time.
> 
> 
> Yes. I've thought about writing test cases for maybe aarch64 16k page binaries on a 4k 
> x86_64 mahine.
> I don't suppose there's tests like that for linux-user today?

No, because it doesn't really work there either.


r~

Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Richard Henderson 3 weeks, 3 days ago
On 5/6/26 07:56, Richard Henderson wrote:
> On 5/5/26 17:52, Warner Losh wrote:
>> Yes. I've thought about writing test cases for maybe aarch64 16k page binaries on a 4k 
>> x86_64 mahine.
>> I don't suppose there's tests like that for linux-user today?

Actually, what we have today that makes this specific case "work" is by allowing the guest 
page size to mirror the host for various guests.  See

     /*
      * Finalize page size before creating CPUs.
      * This will do nothing if !TARGET_PAGE_BITS_VARY.
      * The most efficient setting is to match the host.
      */
     host_page_size = qemu_real_host_page_size();
     set_preferred_target_page_bits(ctz32(host_page_size));
     finalize_target_page_bits();

So, on an x86_64 host, aarch64 guests will always use 4k pages.


r~
Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by MOHAMED AYMAN 4 weeks, 1 day ago
Hi Warner and Peter,

Thanks for the review. :)

Here is v2 addressing your comments:

- Fixed the duplicate HOST_PAGE_MASK definition
- HOST_PAGE_SIZE now uses:
MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)

This preserves correct behavior for cases where the target page size
exceeds the host page size (e.g. aarch64 16K pages on a 4K amd64 host)

- Updated the commit message to clarify behavior and remove the incorrect
"No functional change intended" wording

Regarding your question, I am not currently using bsd-user in production;
this started as a cleanup/contribution effort while working through the code.

Thanks again for the feedback.

Mohamed Ayman

On Fri, May 1, 2026 at 7:11 PM Mohamed Ayman
<mohamedaymanworkspace@gmail.com> wrote:
>
> The bsd-user implementation previously cached host page size and mask
> in global variables (qemu_host_page_size and qemu_host_page_mask),
> which duplicated information already available through
> qemu_real_host_page_size().
>
> This introduced unnecessary global state and potential inconsistencies
> if the host page size is queried or changes during initialization.
>
> Replace all usages of qemu_host_page_size and qemu_host_page_mask with
> HOST_PAGE_SIZE and HOST_PAGE_MASK macros defined as:
>
>   MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
>
> This preserves the original behavior where the effective host page size
> is the maximum of the real host page size and the target page size,
> which matters on targets like aarch64 with 16K pages running on an
> amd64 host with 4K pages.
>
> This also opens the way for renaming qemu_real_host_page_size() to
> qemu_host_page_size() now that the bsd-user globals no longer occupy
> that name.
>
> Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com>
> ---
>  bsd-user/elfload.c |  25 ++---------
>  bsd-user/main.c    |  14 ++-----
>  bsd-user/mmap.c    | 102 ++++++++++++++++-----------------------------
>  bsd-user/qemu.h    |  10 ++---
>  4 files changed, 46 insertions(+), 105 deletions(-)
>
> diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
> index 3bca0cc9ed..00250fc3c1 100644
> --- a/bsd-user/elfload.c
> +++ b/bsd-user/elfload.c
> @@ -192,14 +192,14 @@ static void setup_arg_pages(struct bsd_binprm *bprm, struct image_info *info,
>       */
>      size = target_dflssiz;
>      stack_base = TARGET_USRSTACK - size;
> -    addr = target_mmap(stack_base , size + qemu_host_page_size,
> +    addr = target_mmap(stack_base , size + HOST_PAGE_SIZE,
>              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
>      if (addr == -1) {
>          perror("stk mmap");
>          exit(-1);
>      }
>      /* we reserve one extra page at the top of the stack as guard */
> -    target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
> +    target_mprotect(addr + size, HOST_PAGE_SIZE, PROT_NONE);
>
>      target_stksiz = size;
>      target_stkbas = addr;
> @@ -239,27 +239,10 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
>          return;
>      }
>
> -    /*
> -     * XXX: this is really a hack : if the real host page size is
> -     * smaller than the target page size, some pages after the end
> -     * of the file may not be mapped. A better fix would be to
> -     * patch target_mmap(), but it is more complicated as the file
> -     * size must be known.
> -     */
> -    if (qemu_real_host_page_size() < qemu_host_page_size) {
> -        abi_ulong end_addr, end_addr1;
> -        end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
> -        end_addr = HOST_PAGE_ALIGN(elf_bss);
> -        if (end_addr1 < end_addr) {
> -            mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
> -                 PROT_READ | PROT_WRITE | PROT_EXEC,
> -                 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
> -        }
> -    }
>
> -    nbyte = elf_bss & (qemu_host_page_size - 1);
> +    nbyte = elf_bss & (HOST_PAGE_SIZE - 1);
>      if (nbyte) {
> -        nbyte = qemu_host_page_size - nbyte;
> +        nbyte = HOST_PAGE_SIZE - nbyte;
>          do {
>              /* FIXME - what to do if put_user() fails? */
>              put_user_u8(0, elf_bss);
> diff --git a/bsd-user/main.c b/bsd-user/main.c
> index 73aae8c327..3f5141e794 100644
> --- a/bsd-user/main.c
> +++ b/bsd-user/main.c
> @@ -54,11 +54,6 @@
>  #include "target_arch_cpu.h"
>
>
> -/*
> - * TODO: Remove these and rely only on qemu_real_host_page_size().
> - */
> -uintptr_t qemu_host_page_size;
> -intptr_t qemu_host_page_mask;
>
>  static bool opt_one_insn_per_tb;
>  static unsigned long opt_tb_size;
> @@ -302,8 +297,6 @@ int main(int argc, char **argv)
>          (void) envlist_setenv(envlist, *wrk);
>      }
>
> -    qemu_host_page_size = getpagesize();
> -    qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);
>
>      cpu_model = NULL;
>
> @@ -405,7 +398,6 @@ int main(int argc, char **argv)
>          }
>      }
>
> -    qemu_host_page_mask = -qemu_host_page_size;
>
>      /* init debug */
>      {
> @@ -452,7 +444,7 @@ int main(int argc, char **argv)
>
>      cpu_type = parse_cpu_option(cpu_model);
>
> -    /* init tcg before creating CPUs and to get qemu_host_page_size */
> +    /* init tcg before creating CPUs */
>      {
>          AccelState *accel = current_accel();
>          AccelClass *ac = ACCEL_GET_CLASS(accel);
> @@ -534,7 +526,7 @@ int main(int argc, char **argv)
>       * proper page alignment for guest_base.
>       */
>      if (have_guest_base) {
> -        if (guest_base & ~qemu_host_page_mask) {
> +        if (guest_base & ~HOST_PAGE_MASK) {
>              error_report("Selected guest base not host page aligned");
>              exit(1);
>          }
> @@ -573,7 +565,7 @@ int main(int argc, char **argv)
>          /* 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;
> +                              & TARGET_PAGE_MASK & HOST_PAGE_MASK;
>          }
>      }
>
> diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
> index fe77eceb48..59c70083a4 100644
> --- a/bsd-user/mmap.c
> +++ b/bsd-user/mmap.c
> @@ -84,7 +84,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
>          return 0;
>
>      mmap_lock();
> -    host_start = start & qemu_host_page_mask;
> +    host_start = start & HOST_PAGE_MASK;
>      host_end = HOST_PAGE_ALIGN(end);
>      if (start > host_start) {
>          /* handle host page containing start */
> @@ -92,28 +92,28 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
>          for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
>              prot1 |= page_get_flags(addr);
>          }
> -        if (host_end == host_start + qemu_host_page_size) {
> +        if (host_end == host_start + HOST_PAGE_SIZE) {
>              for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
>                  prot1 |= page_get_flags(addr);
>              }
>              end = host_end;
>          }
>          ret = mprotect(g2h_untagged(host_start),
> -                       qemu_host_page_size, prot1 & PAGE_RWX);
> +                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
>          if (ret != 0)
>              goto error;
> -        host_start += qemu_host_page_size;
> +        host_start += HOST_PAGE_SIZE;
>      }
>      if (end < host_end) {
>          prot1 = prot;
>          for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
>              prot1 |= page_get_flags(addr);
>          }
> -        ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
> -                       qemu_host_page_size, prot1 & PAGE_RWX);
> +        ret = mprotect(g2h_untagged(host_end - HOST_PAGE_SIZE),
> +                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
>          if (ret != 0)
>              goto error;
> -        host_end -= qemu_host_page_size;
> +        host_end -= HOST_PAGE_SIZE;
>      }
>
>      /* handle the pages in the middle */
> @@ -193,7 +193,7 @@ static int mmap_frag(abi_ulong real_start,
>      void *host_start;
>      int prot1, prot_new;
>
> -    real_end = real_start + qemu_host_page_size;
> +    real_end = real_start + HOST_PAGE_SIZE;
>      host_start = g2h_untagged(real_start);
>
>      /* get the protection of the target pages outside the mapping */
> @@ -205,7 +205,7 @@ static int mmap_frag(abi_ulong real_start,
>
>      if (prot1 == 0) {
>          /* no page was there, so we allocate one. See also above. */
> -        void *p = mmap(host_start, qemu_host_page_size, prot,
> +        void *p = mmap(host_start, HOST_PAGE_SIZE, prot,
>                         flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
>          if (p == MAP_FAILED)
>              return -1;
> @@ -223,7 +223,7 @@ static int mmap_frag(abi_ulong real_start,
>
>          /* adjust protection to be able to read */
>          if (!(prot1 & PROT_WRITE))
> -            mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
> +            mprotect(host_start, HOST_PAGE_SIZE, prot1 | PROT_WRITE);
>
>          /* read the corresponding file data */
>          if (!mmap_pread(fd, g2h_untagged(start), end - start, offset, true)) {
> @@ -232,10 +232,10 @@ static int mmap_frag(abi_ulong real_start,
>
>          /* put final protection */
>          if (prot_new != (prot1 | PROT_WRITE))
> -            mprotect(host_start, qemu_host_page_size, prot_new);
> +            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
>      } else {
>          if (prot_new != prot1) {
> -            mprotect(host_start, qemu_host_page_size, prot_new);
> +            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
>          }
>          if (prot_new & PROT_WRITE) {
>              memset(g2h_untagged(start), 0, end - start);
> @@ -289,7 +289,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment)
>      if (start == 0) {
>          start = mmap_next_start;
>      } else {
> -        start &= qemu_host_page_mask;
> +        start &= HOST_PAGE_MASK;
>      }
>
>      size = HOST_PAGE_ALIGN(size);
> @@ -297,7 +297,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment)
>      if (reserved_va) {
>          return mmap_find_vma_reserved(start, size,
>              (alignment != 0 ? 1 << alignment :
> -             MAX(qemu_host_page_size, TARGET_PAGE_SIZE)));
> +             MAX(HOST_PAGE_SIZE, TARGET_PAGE_SIZE)));
>      }
>
>      addr = start;
> @@ -478,8 +478,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
>          goto fail;
>      }
>
> -    real_start = start & qemu_host_page_mask;
> -    host_offset = offset & qemu_host_page_mask;
> +    real_start = start & HOST_PAGE_MASK;
> +    host_offset = offset & HOST_PAGE_MASK;
>
>      /*
>       * If the user is asking for the kernel to find a location, do that
> @@ -498,38 +498,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
>          }
>      }
>
> -    /*
> -     * When mapping files into a memory area larger than the file, accesses
> -     * to pages beyond the file size will cause a SIGBUS.
> -     *
> -     * For example, if mmaping a file of 100 bytes on a host with 4K pages
> -     * emulating a target with 8K pages, the target expects to be able to
> -     * access the first 8K. But the host will trap us on any access beyond
> -     * 4K.
> -     *
> -     * When emulating a target with a larger page-size than the hosts, we
> -     * may need to truncate file maps at EOF and add extra anonymous pages
> -     * up to the targets page boundary.
> -     */
> -
> -    if ((qemu_real_host_page_size() < qemu_host_page_size) && fd != -1) {
> -        struct stat sb;
> -
> -        if (fstat(fd, &sb) == -1) {
> -            goto fail;
> -        }
> -
> -        /* Are we trying to create a map beyond EOF?.  */
> -        if (offset + len > sb.st_size) {
> -            /*
> -             * If so, truncate the file map at eof aligned with
> -             * the hosts real pagesize. Additional anonymous maps
> -             * will be created beyond EOF.
> -             */
> -            len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
> -        }
> -    }
> -
>      if (!(flags & MAP_FIXED)) {
>          unsigned long host_start;
>          void *p;
> @@ -539,8 +507,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
>
>          /*
>           * Note: we prefer to control the mapping address. It is
> -         * especially important if qemu_host_page_size >
> -         * qemu_real_host_page_size
> +         * especially important if HOST_PAGE_SIZE >
> +         * TARGET_PAGE_SIZE
>           */
>          p = mmap(g2h_untagged(start), host_len, prot,
>                   flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
> @@ -581,7 +549,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
>           * aligned, so we read it
>           */
>          if (fd != -1 &&
> -            (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
> +            (offset & ~HOST_PAGE_MASK) != (start & ~HOST_PAGE_MASK)) {
>              /*
>               * msync() won't work here, so we return an error if write is
>               * possible while it is a shared mapping
> @@ -614,7 +582,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
>
>          /* handle the start of the mapping */
>          if (start > real_start) {
> -            if (real_end == real_start + qemu_host_page_size) {
> +            if (real_end == real_start + HOST_PAGE_SIZE) {
>                  /* one single host page */
>                  ret = mmap_frag(real_start, start, end,
>                                  prot, flags, fd, offset);
> @@ -622,21 +590,21 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
>                      goto fail;
>                  goto the_end1;
>              }
> -            ret = mmap_frag(real_start, start, real_start + qemu_host_page_size,
> +            ret = mmap_frag(real_start, start, real_start + HOST_PAGE_SIZE,
>                              prot, flags, fd, offset);
>              if (ret == -1)
>                  goto fail;
> -            real_start += qemu_host_page_size;
> +            real_start += HOST_PAGE_SIZE;
>          }
>          /* handle the end of the mapping */
>          if (end < real_end) {
> -            ret = mmap_frag(real_end - qemu_host_page_size,
> -                            real_end - qemu_host_page_size, end,
> +            ret = mmap_frag(real_end - HOST_PAGE_SIZE,
> +                            real_end - HOST_PAGE_SIZE, end,
>                              prot, flags, fd,
> -                            offset + real_end - qemu_host_page_size - start);
> +                            offset + real_end - HOST_PAGE_SIZE - start);
>              if (ret == -1)
>                  goto fail;
> -            real_end -= qemu_host_page_size;
> +            real_end -= HOST_PAGE_SIZE;
>          }
>
>          /* map the middle (easier) */
> @@ -676,7 +644,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
>      abi_ulong end;
>      int prot;
>
> -    real_start = start & qemu_host_page_mask;
> +    real_start = start & HOST_PAGE_MASK;
>      real_end = HOST_PAGE_ALIGN(start + size);
>      end = start + size;
>      if (start > real_start) {
> @@ -685,14 +653,14 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
>          for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
>              prot |= page_get_flags(addr);
>          }
> -        if (real_end == real_start + qemu_host_page_size) {
> +        if (real_end == real_start + HOST_PAGE_SIZE) {
>              for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
>                  prot |= page_get_flags(addr);
>              }
>              end = real_end;
>          }
>          if (prot != 0) {
> -            real_start += qemu_host_page_size;
> +            real_start += HOST_PAGE_SIZE;
>          }
>      }
>      if (end < real_end) {
> @@ -701,7 +669,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
>              prot |= page_get_flags(addr);
>          }
>          if (prot != 0) {
> -            real_end -= qemu_host_page_size;
> +            real_end -= HOST_PAGE_SIZE;
>          }
>      }
>      if (real_start != real_end) {
> @@ -727,7 +695,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
>          return -EINVAL;
>      mmap_lock();
>      end = start + len;
> -    real_start = start & qemu_host_page_mask;
> +    real_start = start & HOST_PAGE_MASK;
>      real_end = HOST_PAGE_ALIGN(end);
>
>      if (start > real_start) {
> @@ -736,14 +704,14 @@ int target_munmap(abi_ulong start, abi_ulong len)
>          for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
>              prot |= page_get_flags(addr);
>          }
> -        if (real_end == real_start + qemu_host_page_size) {
> +        if (real_end == real_start + HOST_PAGE_SIZE) {
>              for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
>                  prot |= page_get_flags(addr);
>              }
>              end = real_end;
>          }
>          if (prot != 0)
> -            real_start += qemu_host_page_size;
> +            real_start += HOST_PAGE_SIZE;
>      }
>      if (end < real_end) {
>          prot = 0;
> @@ -751,7 +719,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
>              prot |= page_get_flags(addr);
>          }
>          if (prot != 0)
> -            real_end -= qemu_host_page_size;
> +            real_end -= HOST_PAGE_SIZE;
>      }
>
>      ret = 0;
> @@ -784,6 +752,6 @@ int target_msync(abi_ulong start, abi_ulong len, int flags)
>      if (end == start)
>          return 0;
>
> -    start &= qemu_host_page_mask;
> +    start &= HOST_PAGE_MASK;
>      return msync(g2h_untagged(start), end - start, flags);
>  }
> diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
> index b0b2c249fb..7553ac154c 100644
> --- a/bsd-user/qemu.h
> +++ b/bsd-user/qemu.h
> @@ -44,12 +44,10 @@ extern char **environ;
>  #include "accel/tcg/vcpu-state.h"
>
>  #include "qemu-os.h"
> -/*
> - * TODO: Remove these and rely only on qemu_real_host_page_size().
> - */
> -extern uintptr_t qemu_host_page_size;
> -extern intptr_t qemu_host_page_mask;
> -#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
> +
> +#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
> +#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
> +#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)
>
>  /*
>   * This struct is used to hold certain information about the image.  Basically,
> --
> 2.34.1
>
Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Warner Losh 3 weeks, 4 days ago
On Fri, May 1, 2026 at 10:23 AM MOHAMED AYMAN <
mohamedaymanworkspace@gmail.com> wrote:

> Hi Warner and Peter,
>
> Thanks for the review. :)
>
> Here is v2 addressing your comments:
>
> - Fixed the duplicate HOST_PAGE_MASK definition
> - HOST_PAGE_SIZE now uses:
> MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
>
> This preserves correct behavior for cases where the target page size
> exceeds the host page size (e.g. aarch64 16K pages on a 4K amd64 host)
>
> - Updated the commit message to clarify behavior and remove the incorrect
> "No functional change intended" wording
>
> Regarding your question, I am not currently using bsd-user in production;
> this started as a cleanup/contribution effort while working through the
> code.
>
> Thanks again for the feedback.
>

Hi Mohamed,

I was getting ready to create a pull request when I recalled you'd sent
this in. However, it looks
like you didn't attach v2 of the path. Can you please resend it? All that
was here was what appeared
to be an email quoted copy of the first patch.

Thanks a lot!

Warner


> Mohamed Ayman
>
> On Fri, May 1, 2026 at 7:11 PM Mohamed Ayman
> <mohamedaymanworkspace@gmail.com> wrote:
> >
> > The bsd-user implementation previously cached host page size and mask
> > in global variables (qemu_host_page_size and qemu_host_page_mask),
> > which duplicated information already available through
> > qemu_real_host_page_size().
> >
> > This introduced unnecessary global state and potential inconsistencies
> > if the host page size is queried or changes during initialization.
> >
> > Replace all usages of qemu_host_page_size and qemu_host_page_mask with
> > HOST_PAGE_SIZE and HOST_PAGE_MASK macros defined as:
> >
> >   MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
> >
> > This preserves the original behavior where the effective host page size
> > is the maximum of the real host page size and the target page size,
> > which matters on targets like aarch64 with 16K pages running on an
> > amd64 host with 4K pages.
> >
> > This also opens the way for renaming qemu_real_host_page_size() to
> > qemu_host_page_size() now that the bsd-user globals no longer occupy
> > that name.
> >
> > Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com>
> > ---
> >  bsd-user/elfload.c |  25 ++---------
> >  bsd-user/main.c    |  14 ++-----
> >  bsd-user/mmap.c    | 102 ++++++++++++++++-----------------------------
> >  bsd-user/qemu.h    |  10 ++---
> >  4 files changed, 46 insertions(+), 105 deletions(-)
> >
> > diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
> > index 3bca0cc9ed..00250fc3c1 100644
> > --- a/bsd-user/elfload.c
> > +++ b/bsd-user/elfload.c
> > @@ -192,14 +192,14 @@ static void setup_arg_pages(struct bsd_binprm
> *bprm, struct image_info *info,
> >       */
> >      size = target_dflssiz;
> >      stack_base = TARGET_USRSTACK - size;
> > -    addr = target_mmap(stack_base , size + qemu_host_page_size,
> > +    addr = target_mmap(stack_base , size + HOST_PAGE_SIZE,
> >              PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
> >      if (addr == -1) {
> >          perror("stk mmap");
> >          exit(-1);
> >      }
> >      /* we reserve one extra page at the top of the stack as guard */
> > -    target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
> > +    target_mprotect(addr + size, HOST_PAGE_SIZE, PROT_NONE);
> >
> >      target_stksiz = size;
> >      target_stkbas = addr;
> > @@ -239,27 +239,10 @@ static void padzero(abi_ulong elf_bss, abi_ulong
> last_bss)
> >          return;
> >      }
> >
> > -    /*
> > -     * XXX: this is really a hack : if the real host page size is
> > -     * smaller than the target page size, some pages after the end
> > -     * of the file may not be mapped. A better fix would be to
> > -     * patch target_mmap(), but it is more complicated as the file
> > -     * size must be known.
> > -     */
> > -    if (qemu_real_host_page_size() < qemu_host_page_size) {
> > -        abi_ulong end_addr, end_addr1;
> > -        end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
> > -        end_addr = HOST_PAGE_ALIGN(elf_bss);
> > -        if (end_addr1 < end_addr) {
> > -            mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
> > -                 PROT_READ | PROT_WRITE | PROT_EXEC,
> > -                 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
> > -        }
> > -    }
> >
> > -    nbyte = elf_bss & (qemu_host_page_size - 1);
> > +    nbyte = elf_bss & (HOST_PAGE_SIZE - 1);
> >      if (nbyte) {
> > -        nbyte = qemu_host_page_size - nbyte;
> > +        nbyte = HOST_PAGE_SIZE - nbyte;
> >          do {
> >              /* FIXME - what to do if put_user() fails? */
> >              put_user_u8(0, elf_bss);
> > diff --git a/bsd-user/main.c b/bsd-user/main.c
> > index 73aae8c327..3f5141e794 100644
> > --- a/bsd-user/main.c
> > +++ b/bsd-user/main.c
> > @@ -54,11 +54,6 @@
> >  #include "target_arch_cpu.h"
> >
> >
> > -/*
> > - * TODO: Remove these and rely only on qemu_real_host_page_size().
> > - */
> > -uintptr_t qemu_host_page_size;
> > -intptr_t qemu_host_page_mask;
> >
> >  static bool opt_one_insn_per_tb;
> >  static unsigned long opt_tb_size;
> > @@ -302,8 +297,6 @@ int main(int argc, char **argv)
> >          (void) envlist_setenv(envlist, *wrk);
> >      }
> >
> > -    qemu_host_page_size = getpagesize();
> > -    qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);
> >
> >      cpu_model = NULL;
> >
> > @@ -405,7 +398,6 @@ int main(int argc, char **argv)
> >          }
> >      }
> >
> > -    qemu_host_page_mask = -qemu_host_page_size;
> >
> >      /* init debug */
> >      {
> > @@ -452,7 +444,7 @@ int main(int argc, char **argv)
> >
> >      cpu_type = parse_cpu_option(cpu_model);
> >
> > -    /* init tcg before creating CPUs and to get qemu_host_page_size */
> > +    /* init tcg before creating CPUs */
> >      {
> >          AccelState *accel = current_accel();
> >          AccelClass *ac = ACCEL_GET_CLASS(accel);
> > @@ -534,7 +526,7 @@ int main(int argc, char **argv)
> >       * proper page alignment for guest_base.
> >       */
> >      if (have_guest_base) {
> > -        if (guest_base & ~qemu_host_page_mask) {
> > +        if (guest_base & ~HOST_PAGE_MASK) {
> >              error_report("Selected guest base not host page aligned");
> >              exit(1);
> >          }
> > @@ -573,7 +565,7 @@ int main(int argc, char **argv)
> >          /* 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;
> > +                              & TARGET_PAGE_MASK & HOST_PAGE_MASK;
> >          }
> >      }
> >
> > diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
> > index fe77eceb48..59c70083a4 100644
> > --- a/bsd-user/mmap.c
> > +++ b/bsd-user/mmap.c
> > @@ -84,7 +84,7 @@ int target_mprotect(abi_ulong start, abi_ulong len,
> int prot)
> >          return 0;
> >
> >      mmap_lock();
> > -    host_start = start & qemu_host_page_mask;
> > +    host_start = start & HOST_PAGE_MASK;
> >      host_end = HOST_PAGE_ALIGN(end);
> >      if (start > host_start) {
> >          /* handle host page containing start */
> > @@ -92,28 +92,28 @@ int target_mprotect(abi_ulong start, abi_ulong len,
> int prot)
> >          for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE)
> {
> >              prot1 |= page_get_flags(addr);
> >          }
> > -        if (host_end == host_start + qemu_host_page_size) {
> > +        if (host_end == host_start + HOST_PAGE_SIZE) {
> >              for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE)
> {
> >                  prot1 |= page_get_flags(addr);
> >              }
> >              end = host_end;
> >          }
> >          ret = mprotect(g2h_untagged(host_start),
> > -                       qemu_host_page_size, prot1 & PAGE_RWX);
> > +                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
> >          if (ret != 0)
> >              goto error;
> > -        host_start += qemu_host_page_size;
> > +        host_start += HOST_PAGE_SIZE;
> >      }
> >      if (end < host_end) {
> >          prot1 = prot;
> >          for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
> >              prot1 |= page_get_flags(addr);
> >          }
> > -        ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
> > -                       qemu_host_page_size, prot1 & PAGE_RWX);
> > +        ret = mprotect(g2h_untagged(host_end - HOST_PAGE_SIZE),
> > +                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
> >          if (ret != 0)
> >              goto error;
> > -        host_end -= qemu_host_page_size;
> > +        host_end -= HOST_PAGE_SIZE;
> >      }
> >
> >      /* handle the pages in the middle */
> > @@ -193,7 +193,7 @@ static int mmap_frag(abi_ulong real_start,
> >      void *host_start;
> >      int prot1, prot_new;
> >
> > -    real_end = real_start + qemu_host_page_size;
> > +    real_end = real_start + HOST_PAGE_SIZE;
> >      host_start = g2h_untagged(real_start);
> >
> >      /* get the protection of the target pages outside the mapping */
> > @@ -205,7 +205,7 @@ static int mmap_frag(abi_ulong real_start,
> >
> >      if (prot1 == 0) {
> >          /* no page was there, so we allocate one. See also above. */
> > -        void *p = mmap(host_start, qemu_host_page_size, prot,
> > +        void *p = mmap(host_start, HOST_PAGE_SIZE, prot,
> >                         flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
> >          if (p == MAP_FAILED)
> >              return -1;
> > @@ -223,7 +223,7 @@ static int mmap_frag(abi_ulong real_start,
> >
> >          /* adjust protection to be able to read */
> >          if (!(prot1 & PROT_WRITE))
> > -            mprotect(host_start, qemu_host_page_size, prot1 |
> PROT_WRITE);
> > +            mprotect(host_start, HOST_PAGE_SIZE, prot1 | PROT_WRITE);
> >
> >          /* read the corresponding file data */
> >          if (!mmap_pread(fd, g2h_untagged(start), end - start, offset,
> true)) {
> > @@ -232,10 +232,10 @@ static int mmap_frag(abi_ulong real_start,
> >
> >          /* put final protection */
> >          if (prot_new != (prot1 | PROT_WRITE))
> > -            mprotect(host_start, qemu_host_page_size, prot_new);
> > +            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
> >      } else {
> >          if (prot_new != prot1) {
> > -            mprotect(host_start, qemu_host_page_size, prot_new);
> > +            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
> >          }
> >          if (prot_new & PROT_WRITE) {
> >              memset(g2h_untagged(start), 0, end - start);
> > @@ -289,7 +289,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong
> size, abi_ulong alignment)
> >      if (start == 0) {
> >          start = mmap_next_start;
> >      } else {
> > -        start &= qemu_host_page_mask;
> > +        start &= HOST_PAGE_MASK;
> >      }
> >
> >      size = HOST_PAGE_ALIGN(size);
> > @@ -297,7 +297,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong
> size, abi_ulong alignment)
> >      if (reserved_va) {
> >          return mmap_find_vma_reserved(start, size,
> >              (alignment != 0 ? 1 << alignment :
> > -             MAX(qemu_host_page_size, TARGET_PAGE_SIZE)));
> > +             MAX(HOST_PAGE_SIZE, TARGET_PAGE_SIZE)));
> >      }
> >
> >      addr = start;
> > @@ -478,8 +478,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len,
> int prot,
> >          goto fail;
> >      }
> >
> > -    real_start = start & qemu_host_page_mask;
> > -    host_offset = offset & qemu_host_page_mask;
> > +    real_start = start & HOST_PAGE_MASK;
> > +    host_offset = offset & HOST_PAGE_MASK;
> >
> >      /*
> >       * If the user is asking for the kernel to find a location, do that
> > @@ -498,38 +498,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong
> len, int prot,
> >          }
> >      }
> >
> > -    /*
> > -     * When mapping files into a memory area larger than the file,
> accesses
> > -     * to pages beyond the file size will cause a SIGBUS.
> > -     *
> > -     * For example, if mmaping a file of 100 bytes on a host with 4K
> pages
> > -     * emulating a target with 8K pages, the target expects to be able
> to
> > -     * access the first 8K. But the host will trap us on any access
> beyond
> > -     * 4K.
> > -     *
> > -     * When emulating a target with a larger page-size than the hosts,
> we
> > -     * may need to truncate file maps at EOF and add extra anonymous
> pages
> > -     * up to the targets page boundary.
> > -     */
> > -
> > -    if ((qemu_real_host_page_size() < qemu_host_page_size) && fd != -1)
> {
> > -        struct stat sb;
> > -
> > -        if (fstat(fd, &sb) == -1) {
> > -            goto fail;
> > -        }
> > -
> > -        /* Are we trying to create a map beyond EOF?.  */
> > -        if (offset + len > sb.st_size) {
> > -            /*
> > -             * If so, truncate the file map at eof aligned with
> > -             * the hosts real pagesize. Additional anonymous maps
> > -             * will be created beyond EOF.
> > -             */
> > -            len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
> > -        }
> > -    }
> > -
> >      if (!(flags & MAP_FIXED)) {
> >          unsigned long host_start;
> >          void *p;
> > @@ -539,8 +507,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len,
> int prot,
> >
> >          /*
> >           * Note: we prefer to control the mapping address. It is
> > -         * especially important if qemu_host_page_size >
> > -         * qemu_real_host_page_size
> > +         * especially important if HOST_PAGE_SIZE >
> > +         * TARGET_PAGE_SIZE
> >           */
> >          p = mmap(g2h_untagged(start), host_len, prot,
> >                   flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1,
> 0);
> > @@ -581,7 +549,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len,
> int prot,
> >           * aligned, so we read it
> >           */
> >          if (fd != -1 &&
> > -            (offset & ~qemu_host_page_mask) != (start &
> ~qemu_host_page_mask)) {
> > +            (offset & ~HOST_PAGE_MASK) != (start & ~HOST_PAGE_MASK)) {
> >              /*
> >               * msync() won't work here, so we return an error if write
> is
> >               * possible while it is a shared mapping
> > @@ -614,7 +582,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len,
> int prot,
> >
> >          /* handle the start of the mapping */
> >          if (start > real_start) {
> > -            if (real_end == real_start + qemu_host_page_size) {
> > +            if (real_end == real_start + HOST_PAGE_SIZE) {
> >                  /* one single host page */
> >                  ret = mmap_frag(real_start, start, end,
> >                                  prot, flags, fd, offset);
> > @@ -622,21 +590,21 @@ abi_long target_mmap(abi_ulong start, abi_ulong
> len, int prot,
> >                      goto fail;
> >                  goto the_end1;
> >              }
> > -            ret = mmap_frag(real_start, start, real_start +
> qemu_host_page_size,
> > +            ret = mmap_frag(real_start, start, real_start +
> HOST_PAGE_SIZE,
> >                              prot, flags, fd, offset);
> >              if (ret == -1)
> >                  goto fail;
> > -            real_start += qemu_host_page_size;
> > +            real_start += HOST_PAGE_SIZE;
> >          }
> >          /* handle the end of the mapping */
> >          if (end < real_end) {
> > -            ret = mmap_frag(real_end - qemu_host_page_size,
> > -                            real_end - qemu_host_page_size, end,
> > +            ret = mmap_frag(real_end - HOST_PAGE_SIZE,
> > +                            real_end - HOST_PAGE_SIZE, end,
> >                              prot, flags, fd,
> > -                            offset + real_end - qemu_host_page_size -
> start);
> > +                            offset + real_end - HOST_PAGE_SIZE - start);
> >              if (ret == -1)
> >                  goto fail;
> > -            real_end -= qemu_host_page_size;
> > +            real_end -= HOST_PAGE_SIZE;
> >          }
> >
> >          /* map the middle (easier) */
> > @@ -676,7 +644,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
> >      abi_ulong end;
> >      int prot;
> >
> > -    real_start = start & qemu_host_page_mask;
> > +    real_start = start & HOST_PAGE_MASK;
> >      real_end = HOST_PAGE_ALIGN(start + size);
> >      end = start + size;
> >      if (start > real_start) {
> > @@ -685,14 +653,14 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
> >          for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE)
> {
> >              prot |= page_get_flags(addr);
> >          }
> > -        if (real_end == real_start + qemu_host_page_size) {
> > +        if (real_end == real_start + HOST_PAGE_SIZE) {
> >              for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE)
> {
> >                  prot |= page_get_flags(addr);
> >              }
> >              end = real_end;
> >          }
> >          if (prot != 0) {
> > -            real_start += qemu_host_page_size;
> > +            real_start += HOST_PAGE_SIZE;
> >          }
> >      }
> >      if (end < real_end) {
> > @@ -701,7 +669,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
> >              prot |= page_get_flags(addr);
> >          }
> >          if (prot != 0) {
> > -            real_end -= qemu_host_page_size;
> > +            real_end -= HOST_PAGE_SIZE;
> >          }
> >      }
> >      if (real_start != real_end) {
> > @@ -727,7 +695,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
> >          return -EINVAL;
> >      mmap_lock();
> >      end = start + len;
> > -    real_start = start & qemu_host_page_mask;
> > +    real_start = start & HOST_PAGE_MASK;
> >      real_end = HOST_PAGE_ALIGN(end);
> >
> >      if (start > real_start) {
> > @@ -736,14 +704,14 @@ int target_munmap(abi_ulong start, abi_ulong len)
> >          for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE)
> {
> >              prot |= page_get_flags(addr);
> >          }
> > -        if (real_end == real_start + qemu_host_page_size) {
> > +        if (real_end == real_start + HOST_PAGE_SIZE) {
> >              for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE)
> {
> >                  prot |= page_get_flags(addr);
> >              }
> >              end = real_end;
> >          }
> >          if (prot != 0)
> > -            real_start += qemu_host_page_size;
> > +            real_start += HOST_PAGE_SIZE;
> >      }
> >      if (end < real_end) {
> >          prot = 0;
> > @@ -751,7 +719,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
> >              prot |= page_get_flags(addr);
> >          }
> >          if (prot != 0)
> > -            real_end -= qemu_host_page_size;
> > +            real_end -= HOST_PAGE_SIZE;
> >      }
> >
> >      ret = 0;
> > @@ -784,6 +752,6 @@ int target_msync(abi_ulong start, abi_ulong len, int
> flags)
> >      if (end == start)
> >          return 0;
> >
> > -    start &= qemu_host_page_mask;
> > +    start &= HOST_PAGE_MASK;
> >      return msync(g2h_untagged(start), end - start, flags);
> >  }
> > diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
> > index b0b2c249fb..7553ac154c 100644
> > --- a/bsd-user/qemu.h
> > +++ b/bsd-user/qemu.h
> > @@ -44,12 +44,10 @@ extern char **environ;
> >  #include "accel/tcg/vcpu-state.h"
> >
> >  #include "qemu-os.h"
> > -/*
> > - * TODO: Remove these and rely only on qemu_real_host_page_size().
> > - */
> > -extern uintptr_t qemu_host_page_size;
> > -extern intptr_t qemu_host_page_mask;
> > -#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
> > +
> > +#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(),
> TARGET_PAGE_SIZE)
> > +#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
> > +#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)
> >
> >  /*
> >   * This struct is used to hold certain information about the image.
> Basically,
> > --
> > 2.34.1
> >
>
Re: [PATCH v2] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by MOHAMED AYMAN 3 weeks, 4 days ago
Hi Warner,
Apologies for the missing patch, This is v2 of the patch.

Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com>
---
 bsd-user/elfload.c |  25 ++---------
 bsd-user/main.c    |  14 ++-----
 bsd-user/mmap.c    | 102 ++++++++++++++++-----------------------------
 bsd-user/qemu.h    |  10 ++---
 4 files changed, 46 insertions(+), 105 deletions(-)

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 3bca0cc9ed..00250fc3c1 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -192,14 +192,14 @@ static void setup_arg_pages(struct bsd_binprm
*bprm, struct image_info *info,
      */
     size = target_dflssiz;
     stack_base = TARGET_USRSTACK - size;
-    addr = target_mmap(stack_base , size + qemu_host_page_size,
+    addr = target_mmap(stack_base , size + HOST_PAGE_SIZE,
             PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
     if (addr == -1) {
         perror("stk mmap");
         exit(-1);
     }
     /* we reserve one extra page at the top of the stack as guard */
-    target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
+    target_mprotect(addr + size, HOST_PAGE_SIZE, PROT_NONE);

     target_stksiz = size;
     target_stkbas = addr;
@@ -239,27 +239,10 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
         return;
     }

-    /*
-     * XXX: this is really a hack : if the real host page size is
-     * smaller than the target page size, some pages after the end
-     * of the file may not be mapped. A better fix would be to
-     * patch target_mmap(), but it is more complicated as the file
-     * size must be known.
-     */
-    if (qemu_real_host_page_size() < qemu_host_page_size) {
-        abi_ulong end_addr, end_addr1;
-        end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
-        end_addr = HOST_PAGE_ALIGN(elf_bss);
-        if (end_addr1 < end_addr) {
-            mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
-                 PROT_READ | PROT_WRITE | PROT_EXEC,
-                 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
-        }
-    }

-    nbyte = elf_bss & (qemu_host_page_size - 1);
+    nbyte = elf_bss & (HOST_PAGE_SIZE - 1);
     if (nbyte) {
-        nbyte = qemu_host_page_size - nbyte;
+        nbyte = HOST_PAGE_SIZE - nbyte;
         do {
             /* FIXME - what to do if put_user() fails? */
             put_user_u8(0, elf_bss);
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 73aae8c327..3f5141e794 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -54,11 +54,6 @@
 #include "target_arch_cpu.h"


-/*
- * TODO: Remove these and rely only on qemu_real_host_page_size().
- */
-uintptr_t qemu_host_page_size;
-intptr_t qemu_host_page_mask;

 static bool opt_one_insn_per_tb;
 static unsigned long opt_tb_size;
@@ -302,8 +297,6 @@ int main(int argc, char **argv)
         (void) envlist_setenv(envlist, *wrk);
     }

-    qemu_host_page_size = getpagesize();
-    qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);

     cpu_model = NULL;

@@ -405,7 +398,6 @@ int main(int argc, char **argv)
         }
     }

-    qemu_host_page_mask = -qemu_host_page_size;

     /* init debug */
     {
@@ -452,7 +444,7 @@ int main(int argc, char **argv)

     cpu_type = parse_cpu_option(cpu_model);

-    /* init tcg before creating CPUs and to get qemu_host_page_size */
+    /* init tcg before creating CPUs */
     {
         AccelState *accel = current_accel();
         AccelClass *ac = ACCEL_GET_CLASS(accel);
@@ -534,7 +526,7 @@ int main(int argc, char **argv)
      * proper page alignment for guest_base.
      */
     if (have_guest_base) {
-        if (guest_base & ~qemu_host_page_mask) {
+        if (guest_base & ~HOST_PAGE_MASK) {
             error_report("Selected guest base not host page aligned");
             exit(1);
         }
@@ -573,7 +565,7 @@ int main(int argc, char **argv)
         /* 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;
+                              & TARGET_PAGE_MASK & HOST_PAGE_MASK;
         }
     }

diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index fe77eceb48..59c70083a4 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -84,7 +84,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
         return 0;

     mmap_lock();
-    host_start = start & qemu_host_page_mask;
+    host_start = start & HOST_PAGE_MASK;
     host_end = HOST_PAGE_ALIGN(end);
     if (start > host_start) {
         /* handle host page containing start */
@@ -92,28 +92,28 @@ int target_mprotect(abi_ulong start, abi_ulong
len, int prot)
         for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot1 |= page_get_flags(addr);
         }
-        if (host_end == host_start + qemu_host_page_size) {
+        if (host_end == host_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
                 prot1 |= page_get_flags(addr);
             }
             end = host_end;
         }
         ret = mprotect(g2h_untagged(host_start),
-                       qemu_host_page_size, prot1 & PAGE_RWX);
+                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
         if (ret != 0)
             goto error;
-        host_start += qemu_host_page_size;
+        host_start += HOST_PAGE_SIZE;
     }
     if (end < host_end) {
         prot1 = prot;
         for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
             prot1 |= page_get_flags(addr);
         }
-        ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
-                       qemu_host_page_size, prot1 & PAGE_RWX);
+        ret = mprotect(g2h_untagged(host_end - HOST_PAGE_SIZE),
+                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
         if (ret != 0)
             goto error;
-        host_end -= qemu_host_page_size;
+        host_end -= HOST_PAGE_SIZE;
     }

     /* handle the pages in the middle */
@@ -193,7 +193,7 @@ static int mmap_frag(abi_ulong real_start,
     void *host_start;
     int prot1, prot_new;

-    real_end = real_start + qemu_host_page_size;
+    real_end = real_start + HOST_PAGE_SIZE;
     host_start = g2h_untagged(real_start);

     /* get the protection of the target pages outside the mapping */
@@ -205,7 +205,7 @@ static int mmap_frag(abi_ulong real_start,

     if (prot1 == 0) {
         /* no page was there, so we allocate one. See also above. */
-        void *p = mmap(host_start, qemu_host_page_size, prot,
+        void *p = mmap(host_start, HOST_PAGE_SIZE, prot,
                        flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
         if (p == MAP_FAILED)
             return -1;
@@ -223,7 +223,7 @@ static int mmap_frag(abi_ulong real_start,

         /* adjust protection to be able to read */
         if (!(prot1 & PROT_WRITE))
-            mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
+            mprotect(host_start, HOST_PAGE_SIZE, prot1 | PROT_WRITE);

         /* read the corresponding file data */
         if (!mmap_pread(fd, g2h_untagged(start), end - start, offset, true)) {
@@ -232,10 +232,10 @@ static int mmap_frag(abi_ulong real_start,

         /* put final protection */
         if (prot_new != (prot1 | PROT_WRITE))
-            mprotect(host_start, qemu_host_page_size, prot_new);
+            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
     } else {
         if (prot_new != prot1) {
-            mprotect(host_start, qemu_host_page_size, prot_new);
+            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
         }
         if (prot_new & PROT_WRITE) {
             memset(g2h_untagged(start), 0, end - start);
@@ -289,7 +289,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong
size, abi_ulong alignment)
     if (start == 0) {
         start = mmap_next_start;
     } else {
-        start &= qemu_host_page_mask;
+        start &= HOST_PAGE_MASK;
     }

     size = HOST_PAGE_ALIGN(size);
@@ -297,7 +297,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong
size, abi_ulong alignment)
     if (reserved_va) {
         return mmap_find_vma_reserved(start, size,
             (alignment != 0 ? 1 << alignment :
-             MAX(qemu_host_page_size, TARGET_PAGE_SIZE)));
+             MAX(HOST_PAGE_SIZE, TARGET_PAGE_SIZE)));
     }

     addr = start;
@@ -478,8 +478,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong
len, int prot,
         goto fail;
     }

-    real_start = start & qemu_host_page_mask;
-    host_offset = offset & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
+    host_offset = offset & HOST_PAGE_MASK;

     /*
      * If the user is asking for the kernel to find a location, do that
@@ -498,38 +498,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong
len, int prot,
         }
     }

-    /*
-     * When mapping files into a memory area larger than the file, accesses
-     * to pages beyond the file size will cause a SIGBUS.
-     *
-     * For example, if mmaping a file of 100 bytes on a host with 4K pages
-     * emulating a target with 8K pages, the target expects to be able to
-     * access the first 8K. But the host will trap us on any access beyond
-     * 4K.
-     *
-     * When emulating a target with a larger page-size than the hosts, we
-     * may need to truncate file maps at EOF and add extra anonymous pages
-     * up to the targets page boundary.
-     */
-
-    if ((qemu_real_host_page_size() < qemu_host_page_size) && fd != -1) {
-        struct stat sb;
-
-        if (fstat(fd, &sb) == -1) {
-            goto fail;
-        }
-
-        /* Are we trying to create a map beyond EOF?.  */
-        if (offset + len > sb.st_size) {
-            /*
-             * If so, truncate the file map at eof aligned with
-             * the hosts real pagesize. Additional anonymous maps
-             * will be created beyond EOF.
-             */
-            len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
-        }
-    }
-
     if (!(flags & MAP_FIXED)) {
         unsigned long host_start;
         void *p;
@@ -539,8 +507,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong
len, int prot,

         /*
          * Note: we prefer to control the mapping address. It is
-         * especially important if qemu_host_page_size >
-         * qemu_real_host_page_size
+         * especially important if HOST_PAGE_SIZE >
+         * TARGET_PAGE_SIZE
          */
         p = mmap(g2h_untagged(start), host_len, prot,
                  flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
@@ -581,7 +549,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong
len, int prot,
          * aligned, so we read it
          */
         if (fd != -1 &&
-            (offset & ~qemu_host_page_mask) != (start &
~qemu_host_page_mask)) {
+            (offset & ~HOST_PAGE_MASK) != (start & ~HOST_PAGE_MASK)) {
             /*
              * msync() won't work here, so we return an error if write is
              * possible while it is a shared mapping
@@ -614,7 +582,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong
len, int prot,

         /* handle the start of the mapping */
         if (start > real_start) {
-            if (real_end == real_start + qemu_host_page_size) {
+            if (real_end == real_start + HOST_PAGE_SIZE) {
                 /* one single host page */
                 ret = mmap_frag(real_start, start, end,
                                 prot, flags, fd, offset);
@@ -622,21 +590,21 @@ abi_long target_mmap(abi_ulong start, abi_ulong
len, int prot,
                     goto fail;
                 goto the_end1;
             }
-            ret = mmap_frag(real_start, start, real_start +
qemu_host_page_size,
+            ret = mmap_frag(real_start, start, real_start + HOST_PAGE_SIZE,
                             prot, flags, fd, offset);
             if (ret == -1)
                 goto fail;
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
         }
         /* handle the end of the mapping */
         if (end < real_end) {
-            ret = mmap_frag(real_end - qemu_host_page_size,
-                            real_end - qemu_host_page_size, end,
+            ret = mmap_frag(real_end - HOST_PAGE_SIZE,
+                            real_end - HOST_PAGE_SIZE, end,
                             prot, flags, fd,
-                            offset + real_end - qemu_host_page_size - start);
+                            offset + real_end - HOST_PAGE_SIZE - start);
             if (ret == -1)
                 goto fail;
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
         }

         /* map the middle (easier) */
@@ -676,7 +644,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
     abi_ulong end;
     int prot;

-    real_start = start & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
     real_end = HOST_PAGE_ALIGN(start + size);
     end = start + size;
     if (start > real_start) {
@@ -685,14 +653,14 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
         for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot |= page_get_flags(addr);
         }
-        if (real_end == real_start + qemu_host_page_size) {
+        if (real_end == real_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
                 prot |= page_get_flags(addr);
             }
             end = real_end;
         }
         if (prot != 0) {
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
         }
     }
     if (end < real_end) {
@@ -701,7 +669,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
             prot |= page_get_flags(addr);
         }
         if (prot != 0) {
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
         }
     }
     if (real_start != real_end) {
@@ -727,7 +695,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
         return -EINVAL;
     mmap_lock();
     end = start + len;
-    real_start = start & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
     real_end = HOST_PAGE_ALIGN(end);

     if (start > real_start) {
@@ -736,14 +704,14 @@ int target_munmap(abi_ulong start, abi_ulong len)
         for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot |= page_get_flags(addr);
         }
-        if (real_end == real_start + qemu_host_page_size) {
+        if (real_end == real_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
                 prot |= page_get_flags(addr);
             }
             end = real_end;
         }
         if (prot != 0)
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
     }
     if (end < real_end) {
         prot = 0;
@@ -751,7 +719,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
             prot |= page_get_flags(addr);
         }
         if (prot != 0)
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
     }

     ret = 0;
@@ -784,6 +752,6 @@ int target_msync(abi_ulong start, abi_ulong len, int flags)
     if (end == start)
         return 0;

-    start &= qemu_host_page_mask;
+    start &= HOST_PAGE_MASK;
     return msync(g2h_untagged(start), end - start, flags);
 }
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index b0b2c249fb..7553ac154c 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -44,12 +44,10 @@ extern char **environ;
 #include "accel/tcg/vcpu-state.h"

 #include "qemu-os.h"
-/*
- * TODO: Remove these and rely only on qemu_real_host_page_size().
- */
-extern uintptr_t qemu_host_page_size;
-extern intptr_t qemu_host_page_mask;
-#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
+
+#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
+#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
+#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)

 /*
  * This struct is used to hold certain information about the image.  Basically,
-- 
2.34.1
[PATCH v3] bsd-user: remove cached host page size and rely on qemu_real_host_page_size()
Posted by Mohamed Ayman 3 weeks, 4 days ago
Fix duplicate HOST_PAGE_MASK definition and replace all remaining uses
of qemu_host_page_size/qemu_host_page_mask with HOST_PAGE_SIZE/HOST_PAGE_MASK.

HOST_PAGE_SIZE is now defined as:
MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)

This preserves correct behavior when the target page size exceeds the
host page size (e.g. aarch64 16K pages on a 4K amd64 host).

Signed-off-by: Mohamed Ayman <mohamedaymanworkspace@gmail.com>
---
 bsd-user/elfload.c |  25 ++---------
 bsd-user/main.c    |  14 ++-----
 bsd-user/mmap.c    | 102 ++++++++++++++++-----------------------------
 bsd-user/qemu.h    |  10 ++---
 4 files changed, 46 insertions(+), 105 deletions(-)

diff --git a/bsd-user/elfload.c b/bsd-user/elfload.c
index 3bca0cc9ed..00250fc3c1 100644
--- a/bsd-user/elfload.c
+++ b/bsd-user/elfload.c
@@ -192,14 +192,14 @@ static void setup_arg_pages(struct bsd_binprm *bprm, struct image_info *info,
      */
     size = target_dflssiz;
     stack_base = TARGET_USRSTACK - size;
-    addr = target_mmap(stack_base , size + qemu_host_page_size,
+    addr = target_mmap(stack_base , size + HOST_PAGE_SIZE,
             PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
     if (addr == -1) {
         perror("stk mmap");
         exit(-1);
     }
     /* we reserve one extra page at the top of the stack as guard */
-    target_mprotect(addr + size, qemu_host_page_size, PROT_NONE);
+    target_mprotect(addr + size, HOST_PAGE_SIZE, PROT_NONE);
 
     target_stksiz = size;
     target_stkbas = addr;
@@ -239,27 +239,10 @@ static void padzero(abi_ulong elf_bss, abi_ulong last_bss)
         return;
     }
 
-    /*
-     * XXX: this is really a hack : if the real host page size is
-     * smaller than the target page size, some pages after the end
-     * of the file may not be mapped. A better fix would be to
-     * patch target_mmap(), but it is more complicated as the file
-     * size must be known.
-     */
-    if (qemu_real_host_page_size() < qemu_host_page_size) {
-        abi_ulong end_addr, end_addr1;
-        end_addr1 = REAL_HOST_PAGE_ALIGN(elf_bss);
-        end_addr = HOST_PAGE_ALIGN(elf_bss);
-        if (end_addr1 < end_addr) {
-            mmap((void *)g2h_untagged(end_addr1), end_addr - end_addr1,
-                 PROT_READ | PROT_WRITE | PROT_EXEC,
-                 MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0);
-        }
-    }
 
-    nbyte = elf_bss & (qemu_host_page_size - 1);
+    nbyte = elf_bss & (HOST_PAGE_SIZE - 1);
     if (nbyte) {
-        nbyte = qemu_host_page_size - nbyte;
+        nbyte = HOST_PAGE_SIZE - nbyte;
         do {
             /* FIXME - what to do if put_user() fails? */
             put_user_u8(0, elf_bss);
diff --git a/bsd-user/main.c b/bsd-user/main.c
index 73aae8c327..3f5141e794 100644
--- a/bsd-user/main.c
+++ b/bsd-user/main.c
@@ -54,11 +54,6 @@
 #include "target_arch_cpu.h"
 
 
-/*
- * TODO: Remove these and rely only on qemu_real_host_page_size().
- */
-uintptr_t qemu_host_page_size;
-intptr_t qemu_host_page_mask;
 
 static bool opt_one_insn_per_tb;
 static unsigned long opt_tb_size;
@@ -302,8 +297,6 @@ int main(int argc, char **argv)
         (void) envlist_setenv(envlist, *wrk);
     }
 
-    qemu_host_page_size = getpagesize();
-    qemu_host_page_size = MAX(qemu_host_page_size, TARGET_PAGE_SIZE);
 
     cpu_model = NULL;
 
@@ -405,7 +398,6 @@ int main(int argc, char **argv)
         }
     }
 
-    qemu_host_page_mask = -qemu_host_page_size;
 
     /* init debug */
     {
@@ -452,7 +444,7 @@ int main(int argc, char **argv)
 
     cpu_type = parse_cpu_option(cpu_model);
 
-    /* init tcg before creating CPUs and to get qemu_host_page_size */
+    /* init tcg before creating CPUs */
     {
         AccelState *accel = current_accel();
         AccelClass *ac = ACCEL_GET_CLASS(accel);
@@ -534,7 +526,7 @@ int main(int argc, char **argv)
      * proper page alignment for guest_base.
      */
     if (have_guest_base) {
-        if (guest_base & ~qemu_host_page_mask) {
+        if (guest_base & ~HOST_PAGE_MASK) {
             error_report("Selected guest base not host page aligned");
             exit(1);
         }
@@ -573,7 +565,7 @@ int main(int argc, char **argv)
         /* 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;
+                              & TARGET_PAGE_MASK & HOST_PAGE_MASK;
         }
     }
 
diff --git a/bsd-user/mmap.c b/bsd-user/mmap.c
index fe77eceb48..59c70083a4 100644
--- a/bsd-user/mmap.c
+++ b/bsd-user/mmap.c
@@ -84,7 +84,7 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
         return 0;
 
     mmap_lock();
-    host_start = start & qemu_host_page_mask;
+    host_start = start & HOST_PAGE_MASK;
     host_end = HOST_PAGE_ALIGN(end);
     if (start > host_start) {
         /* handle host page containing start */
@@ -92,28 +92,28 @@ int target_mprotect(abi_ulong start, abi_ulong len, int prot)
         for (addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot1 |= page_get_flags(addr);
         }
-        if (host_end == host_start + qemu_host_page_size) {
+        if (host_end == host_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
                 prot1 |= page_get_flags(addr);
             }
             end = host_end;
         }
         ret = mprotect(g2h_untagged(host_start),
-                       qemu_host_page_size, prot1 & PAGE_RWX);
+                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
         if (ret != 0)
             goto error;
-        host_start += qemu_host_page_size;
+        host_start += HOST_PAGE_SIZE;
     }
     if (end < host_end) {
         prot1 = prot;
         for (addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) {
             prot1 |= page_get_flags(addr);
         }
-        ret = mprotect(g2h_untagged(host_end - qemu_host_page_size),
-                       qemu_host_page_size, prot1 & PAGE_RWX);
+        ret = mprotect(g2h_untagged(host_end - HOST_PAGE_SIZE),
+                       HOST_PAGE_SIZE, prot1 & PAGE_RWX);
         if (ret != 0)
             goto error;
-        host_end -= qemu_host_page_size;
+        host_end -= HOST_PAGE_SIZE;
     }
 
     /* handle the pages in the middle */
@@ -193,7 +193,7 @@ static int mmap_frag(abi_ulong real_start,
     void *host_start;
     int prot1, prot_new;
 
-    real_end = real_start + qemu_host_page_size;
+    real_end = real_start + HOST_PAGE_SIZE;
     host_start = g2h_untagged(real_start);
 
     /* get the protection of the target pages outside the mapping */
@@ -205,7 +205,7 @@ static int mmap_frag(abi_ulong real_start,
 
     if (prot1 == 0) {
         /* no page was there, so we allocate one. See also above. */
-        void *p = mmap(host_start, qemu_host_page_size, prot,
+        void *p = mmap(host_start, HOST_PAGE_SIZE, prot,
                        flags | ((fd != -1) ? MAP_ANON : 0), -1, 0);
         if (p == MAP_FAILED)
             return -1;
@@ -223,7 +223,7 @@ static int mmap_frag(abi_ulong real_start,
 
         /* adjust protection to be able to read */
         if (!(prot1 & PROT_WRITE))
-            mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE);
+            mprotect(host_start, HOST_PAGE_SIZE, prot1 | PROT_WRITE);
 
         /* read the corresponding file data */
         if (!mmap_pread(fd, g2h_untagged(start), end - start, offset, true)) {
@@ -232,10 +232,10 @@ static int mmap_frag(abi_ulong real_start,
 
         /* put final protection */
         if (prot_new != (prot1 | PROT_WRITE))
-            mprotect(host_start, qemu_host_page_size, prot_new);
+            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
     } else {
         if (prot_new != prot1) {
-            mprotect(host_start, qemu_host_page_size, prot_new);
+            mprotect(host_start, HOST_PAGE_SIZE, prot_new);
         }
         if (prot_new & PROT_WRITE) {
             memset(g2h_untagged(start), 0, end - start);
@@ -289,7 +289,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment)
     if (start == 0) {
         start = mmap_next_start;
     } else {
-        start &= qemu_host_page_mask;
+        start &= HOST_PAGE_MASK;
     }
 
     size = HOST_PAGE_ALIGN(size);
@@ -297,7 +297,7 @@ abi_ulong mmap_find_vma(abi_ulong start, abi_ulong size, abi_ulong alignment)
     if (reserved_va) {
         return mmap_find_vma_reserved(start, size,
             (alignment != 0 ? 1 << alignment :
-             MAX(qemu_host_page_size, TARGET_PAGE_SIZE)));
+             MAX(HOST_PAGE_SIZE, TARGET_PAGE_SIZE)));
     }
 
     addr = start;
@@ -478,8 +478,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         goto fail;
     }
 
-    real_start = start & qemu_host_page_mask;
-    host_offset = offset & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
+    host_offset = offset & HOST_PAGE_MASK;
 
     /*
      * If the user is asking for the kernel to find a location, do that
@@ -498,38 +498,6 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
         }
     }
 
-    /*
-     * When mapping files into a memory area larger than the file, accesses
-     * to pages beyond the file size will cause a SIGBUS.
-     *
-     * For example, if mmaping a file of 100 bytes on a host with 4K pages
-     * emulating a target with 8K pages, the target expects to be able to
-     * access the first 8K. But the host will trap us on any access beyond
-     * 4K.
-     *
-     * When emulating a target with a larger page-size than the hosts, we
-     * may need to truncate file maps at EOF and add extra anonymous pages
-     * up to the targets page boundary.
-     */
-
-    if ((qemu_real_host_page_size() < qemu_host_page_size) && fd != -1) {
-        struct stat sb;
-
-        if (fstat(fd, &sb) == -1) {
-            goto fail;
-        }
-
-        /* Are we trying to create a map beyond EOF?.  */
-        if (offset + len > sb.st_size) {
-            /*
-             * If so, truncate the file map at eof aligned with
-             * the hosts real pagesize. Additional anonymous maps
-             * will be created beyond EOF.
-             */
-            len = REAL_HOST_PAGE_ALIGN(sb.st_size - offset);
-        }
-    }
-
     if (!(flags & MAP_FIXED)) {
         unsigned long host_start;
         void *p;
@@ -539,8 +507,8 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
 
         /*
          * Note: we prefer to control the mapping address. It is
-         * especially important if qemu_host_page_size >
-         * qemu_real_host_page_size
+         * especially important if HOST_PAGE_SIZE >
+         * TARGET_PAGE_SIZE
          */
         p = mmap(g2h_untagged(start), host_len, prot,
                  flags | MAP_FIXED | ((fd != -1) ? MAP_ANON : 0), -1, 0);
@@ -581,7 +549,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
          * aligned, so we read it
          */
         if (fd != -1 &&
-            (offset & ~qemu_host_page_mask) != (start & ~qemu_host_page_mask)) {
+            (offset & ~HOST_PAGE_MASK) != (start & ~HOST_PAGE_MASK)) {
             /*
              * msync() won't work here, so we return an error if write is
              * possible while it is a shared mapping
@@ -614,7 +582,7 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
 
         /* handle the start of the mapping */
         if (start > real_start) {
-            if (real_end == real_start + qemu_host_page_size) {
+            if (real_end == real_start + HOST_PAGE_SIZE) {
                 /* one single host page */
                 ret = mmap_frag(real_start, start, end,
                                 prot, flags, fd, offset);
@@ -622,21 +590,21 @@ abi_long target_mmap(abi_ulong start, abi_ulong len, int prot,
                     goto fail;
                 goto the_end1;
             }
-            ret = mmap_frag(real_start, start, real_start + qemu_host_page_size,
+            ret = mmap_frag(real_start, start, real_start + HOST_PAGE_SIZE,
                             prot, flags, fd, offset);
             if (ret == -1)
                 goto fail;
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
         }
         /* handle the end of the mapping */
         if (end < real_end) {
-            ret = mmap_frag(real_end - qemu_host_page_size,
-                            real_end - qemu_host_page_size, end,
+            ret = mmap_frag(real_end - HOST_PAGE_SIZE,
+                            real_end - HOST_PAGE_SIZE, end,
                             prot, flags, fd,
-                            offset + real_end - qemu_host_page_size - start);
+                            offset + real_end - HOST_PAGE_SIZE - start);
             if (ret == -1)
                 goto fail;
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
         }
 
         /* map the middle (easier) */
@@ -676,7 +644,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
     abi_ulong end;
     int prot;
 
-    real_start = start & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
     real_end = HOST_PAGE_ALIGN(start + size);
     end = start + size;
     if (start > real_start) {
@@ -685,14 +653,14 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
         for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot |= page_get_flags(addr);
         }
-        if (real_end == real_start + qemu_host_page_size) {
+        if (real_end == real_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
                 prot |= page_get_flags(addr);
             }
             end = real_end;
         }
         if (prot != 0) {
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
         }
     }
     if (end < real_end) {
@@ -701,7 +669,7 @@ void mmap_reserve(abi_ulong start, abi_ulong size)
             prot |= page_get_flags(addr);
         }
         if (prot != 0) {
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
         }
     }
     if (real_start != real_end) {
@@ -727,7 +695,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
         return -EINVAL;
     mmap_lock();
     end = start + len;
-    real_start = start & qemu_host_page_mask;
+    real_start = start & HOST_PAGE_MASK;
     real_end = HOST_PAGE_ALIGN(end);
 
     if (start > real_start) {
@@ -736,14 +704,14 @@ int target_munmap(abi_ulong start, abi_ulong len)
         for (addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) {
             prot |= page_get_flags(addr);
         }
-        if (real_end == real_start + qemu_host_page_size) {
+        if (real_end == real_start + HOST_PAGE_SIZE) {
             for (addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) {
                 prot |= page_get_flags(addr);
             }
             end = real_end;
         }
         if (prot != 0)
-            real_start += qemu_host_page_size;
+            real_start += HOST_PAGE_SIZE;
     }
     if (end < real_end) {
         prot = 0;
@@ -751,7 +719,7 @@ int target_munmap(abi_ulong start, abi_ulong len)
             prot |= page_get_flags(addr);
         }
         if (prot != 0)
-            real_end -= qemu_host_page_size;
+            real_end -= HOST_PAGE_SIZE;
     }
 
     ret = 0;
@@ -784,6 +752,6 @@ int target_msync(abi_ulong start, abi_ulong len, int flags)
     if (end == start)
         return 0;
 
-    start &= qemu_host_page_mask;
+    start &= HOST_PAGE_MASK;
     return msync(g2h_untagged(start), end - start, flags);
 }
diff --git a/bsd-user/qemu.h b/bsd-user/qemu.h
index b0b2c249fb..7553ac154c 100644
--- a/bsd-user/qemu.h
+++ b/bsd-user/qemu.h
@@ -44,12 +44,10 @@ extern char **environ;
 #include "accel/tcg/vcpu-state.h"
 
 #include "qemu-os.h"
-/*
- * TODO: Remove these and rely only on qemu_real_host_page_size().
- */
-extern uintptr_t qemu_host_page_size;
-extern intptr_t qemu_host_page_mask;
-#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), qemu_host_page_size)
+
+#define HOST_PAGE_SIZE        MAX(qemu_real_host_page_size(), TARGET_PAGE_SIZE)
+#define HOST_PAGE_MASK        ((intptr_t)~(HOST_PAGE_SIZE - 1))
+#define HOST_PAGE_ALIGN(addr) ROUND_UP((addr), HOST_PAGE_SIZE)
 
 /*
  * This struct is used to hold certain information about the image.  Basically,
-- 
2.34.1