On Sat, May 30, 2026 at 3:12 PM Richard Henderson <
[email protected]> wrote:

> Introduce user/mmap-min-addr.h.  Initialize the variable
> from a constructor instead of main.
>
> Signed-off-by: Richard Henderson <[email protected]>
> ---
>  include/user/mmap-min-addr.h | 12 ++++++++++++
>  linux-user/user-internals.h  |  1 -
>  common-user/mmap-min-addr.c  | 37 ++++++++++++++++++++++++++++++++++++
>  linux-user/elfload.c         |  1 +
>  linux-user/main.c            | 33 +++-----------------------------
>  linux-user/mmap.c            |  1 +
>  common-user/meson.build      |  1 +
>  7 files changed, 55 insertions(+), 31 deletions(-)
>  create mode 100644 include/user/mmap-min-addr.h
>  create mode 100644 common-user/mmap-min-addr.c
>

Reviewed-by: Warner Losh <[email protected]>


> diff --git a/include/user/mmap-min-addr.h b/include/user/mmap-min-addr.h
> new file mode 100644
> index 0000000000..ded0b6909d
> --- /dev/null
> +++ b/include/user/mmap-min-addr.h
> @@ -0,0 +1,12 @@
> +/* SPDX-License-Identifier: GPL-2.0-or-later */
> +
> +#ifndef USER_MMAP_MIN_ADDR_H
> +#define USER_MMAP_MIN_ADDR_H
> +
> +#ifndef CONFIG_USER_ONLY
> +#error Cannot include this header from system emulation
> +#endif
> +
> +extern uintptr_t mmap_min_addr;
> +
> +#endif
> diff --git a/linux-user/user-internals.h b/linux-user/user-internals.h
> index 3f41d3f33c..bc6b9f44e6 100644
> --- a/linux-user/user-internals.h
> +++ b/linux-user/user-internals.h
> @@ -29,7 +29,6 @@ void init_task_state(TaskState *ts);
>  void task_settid(TaskState *);
>  void stop_all_tasks(void);
>  extern const char *qemu_uname_release;
> -extern unsigned long mmap_min_addr;
>
>  typedef struct IOCTLEntry IOCTLEntry;
>
> diff --git a/common-user/mmap-min-addr.c b/common-user/mmap-min-addr.c
> new file mode 100644
> index 0000000000..b2b3762386
> --- /dev/null
> +++ b/common-user/mmap-min-addr.c
> @@ -0,0 +1,37 @@
> +/*
> + * Utility function to get the minimum mmap address.
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "user/mmap-min-addr.h"
> +
> +uintptr_t mmap_min_addr;
> +
> +static void __attribute__((constructor)) init(void)
> +{
> +#ifdef __linux__
> +    /*
> +     * We prefer to not make NULL pointers accessible to QEMU.
> +     * If something goes wrong below, fall back to 1 page.
> +     */
> +    size_t min_addr = qemu_real_host_page_size();
> +    /*
> +     * Read in mmap_min_addr kernel parameter.  This value is used
> +     * When loading the ELF image to determine whether guest_base
> +     * is needed.  It is also used in mmap_find_vma.
> +     */
> +    FILE *fp = fopen("/proc/sys/vm/mmap_min_addr", "r");
> +
> +    if (fp) {
> +        unsigned long tmp;
> +        if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
> +            min_addr = MAX(min_addr, tmp);
> +        }
> +        fclose(fp);
> +    }
> +    mmap_min_addr = min_addr;
> +#else
> +# error
> +#endif
> +}
> diff --git a/linux-user/elfload.c b/linux-user/elfload.c
> index 5a30cebcc3..93ab2661e3 100644
> --- a/linux-user/elfload.c
> +++ b/linux-user/elfload.c
> @@ -14,6 +14,7 @@
>  #include "exec/translation-block.h"
>  #include "exec/tswap.h"
>  #include "user/guest-base.h"
> +#include "user/mmap-min-addr.h"
>  #include "user-internals.h"
>  #include "signal-common.h"
>  #include "loader.h"
> diff --git a/linux-user/main.c b/linux-user/main.c
> index c08c73fd80..01cf5bf079 100644
> --- a/linux-user/main.c
> +++ b/linux-user/main.c
> @@ -39,6 +39,7 @@
>  #include "qemu/module.h"
>  #include "qemu/plugin.h"
>  #include "user/guest-base.h"
> +#include "user/mmap-min-addr.h"
>  #include "user/page-protection.h"
>  #include "exec/gdbstub.h"
>  #include "gdbstub/user.h"
> @@ -78,7 +79,6 @@ static envlist_t *envlist;
>  static const char *cpu_model;
>  static const char *cpu_type;
>  static const char *seed_optarg;
> -unsigned long mmap_min_addr;
>  uintptr_t guest_base;
>  bool have_guest_base;
>
> @@ -914,35 +914,8 @@ int main(int argc, char **argv, char **envp)
>      target_environ = envlist_to_environ(envlist, NULL);
>      envlist_free(envlist);
>
> -    /*
> -     * Read in mmap_min_addr kernel parameter.  This value is used
> -     * When loading the ELF image to determine whether guest_base
> -     * is needed.  It is also used in mmap_find_vma.
> -     */
> -    {
> -        FILE *fp;
> -
> -        if ((fp = fopen("/proc/sys/vm/mmap_min_addr", "r")) != NULL) {
> -            unsigned long tmp;
> -            if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) {
> -                mmap_min_addr = MAX(tmp, host_page_size);
> -                qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%lx\n",
> -                              mmap_min_addr);
> -            }
> -            fclose(fp);
> -        }
> -    }
> -
> -    /*
> -     * We prefer to not make NULL pointers accessible to QEMU.
> -     * If we're in a chroot with no /proc, fall back to 1 page.
> -     */
> -    if (mmap_min_addr == 0) {
> -        mmap_min_addr = host_page_size;
> -        qemu_log_mask(CPU_LOG_PAGE,
> -                      "host mmap_min_addr=0x%lx (fallback)\n",
> -                      mmap_min_addr);
> -    }
> +    qemu_log_mask(CPU_LOG_PAGE, "host mmap_min_addr=0x%" PRIxPTR "\n",
> +                  mmap_min_addr);
>
>      /*
>       * Prepare copy of argv vector for target.
> diff --git a/linux-user/mmap.c b/linux-user/mmap.c
> index b4b7b3e5cc..f81417182e 100644
> --- a/linux-user/mmap.c
> +++ b/linux-user/mmap.c
> @@ -24,6 +24,7 @@
>  #include "exec/mmap-lock.h"
>  #include "qemu.h"
>  #include "user/page-protection.h"
> +#include "user/mmap-min-addr.h"
>  #include "user-internals.h"
>  #include "user-mmap.h"
>  #include "target_mman.h"
> diff --git a/common-user/meson.build b/common-user/meson.build
> index ac9de5b9e3..f9e2e83f9a 100644
> --- a/common-user/meson.build
> +++ b/common-user/meson.build
> @@ -5,6 +5,7 @@ endif
>  common_user_inc += include_directories('host/' / host_arch)
>
>  user_ss.add(files(
> +  'mmap-min-addr.c',
>    'safe-syscall.S',
>    'safe-syscall-error.c',
>  ))
> --
> 2.43.0
>
>

Reply via email to