common-user: Move mmap_min_addr from linux-user

Introduce user/mmap-min-addr.h.  Initialize the variable
from a constructor instead of main.

Reviewed-by: Helge Deller <deller@gmx.de>
Reviewed-by: Warner Losh <imp@bsdimp.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
Richard Henderson
2026-05-29 18:12:25 -07:00
parent 6fe7a5bba7
commit c56da35d5d
7 changed files with 55 additions and 31 deletions

View File

@@ -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',
))

View File

@@ -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
}

View File

@@ -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

View File

@@ -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"

View File

@@ -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.

View File

@@ -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"

View File

@@ -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;