| 1 | /* |
| 2 | * Utility function to get the minimum mmap address. |
| 3 | * SPDX-License-Identifier: GPL-2.0-or-later |
| 4 | */ |
| 5 | |
| 6 | #include "qemu/osdep.h" |
| 7 | #include "user/mmap-min-addr.h" |
| 8 | #ifdef __FreeBSD__ |
| 9 | #include <sys/sysctl.h> |
| 10 | #include <sys/user.h> |
| 11 | #endif |
| 12 | |
| 13 | uintptr_t mmap_min_addr; |
| 14 | |
| 15 | static void __attribute__((constructor)) init(void) |
| 16 | { |
| 17 | #ifdef __linux__ |
| 18 | /* |
| 19 | * We prefer to not make NULL pointers accessible to QEMU. |
| 20 | * If something goes wrong below, fall back to 1 page. |
| 21 | */ |
| 22 | size_t min_addr = qemu_real_host_page_size(); |
| 23 | /* |
| 24 | * Read in mmap_min_addr kernel parameter. This value is used |
| 25 | * When loading the ELF image to determine whether guest_base |
| 26 | * is needed. It is also used in mmap_find_vma. |
| 27 | */ |
| 28 | FILE *fp = fopen("/proc/sys/vm/mmap_min_addr", "r"); |
| 29 | |
| 30 | if (fp) { |
| 31 | unsigned long tmp; |
| 32 | if (fscanf(fp, "%lu", &tmp) == 1 && tmp != 0) { |
| 33 | min_addr = MAX(min_addr, tmp); |
| 34 | } |
| 35 | fclose(fp); |
| 36 | } |
| 37 | mmap_min_addr = min_addr; |
| 38 | #elif defined(__FreeBSD__) |
| 39 | int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_VM_LAYOUT, getpid() }; |
| 40 | struct kinfo_vm_layout info; |
| 41 | size_t info_len = sizeof(info); |
| 42 | |
| 43 | mmap_min_addr = |
| 44 | (sysctl(mib, ARRAY_SIZE(mib), &info, &info_len, NULL, 0) < 0 |
| 45 | ? qemu_real_host_page_size() |
| 46 | : info.kvm_min_user_addr); |
| 47 | #else |
| 48 | # error |
| 49 | #endif |
| 50 | } |