diff options
author | Juergen Lock <nox@jelal.kn-bremen.de> | 2010-03-25 22:32:16 +0100 |
---|---|---|
committer | Blue Swirl <blauwirbel@gmail.com> | 2010-03-30 17:45:10 +0000 |
commit | f01576f18569fac675671a81bf931901050c3a73 (patch) | |
tree | b4510ebcd89d56ba7c148077085272b7be995d6c /exec.c | |
parent | b035ffd11813524d7c0e44354f5c4bdd281f4b37 (diff) |
Get bsd-user host page protection code working on FreeBSD hosts
Use kinfo_getvmmap(3) on FeeBSD >= 7.x and /compat/linux/proc on older
FreeBSD. (kinfo_getvmmap is preferred since /compat/linux/proc is
usually only mounted on hosts also using the Linuxolator.)
This patch is a bit hacky because the includes needed for kinfo_getvmmap
conflict with other definitions in exec.c by default so I had to `trick
around' a little, but I built the result in FreeBSD 6.4-stable and
7.2-stable tbs and on 8-stable on the host so the hacks at least
should be stable. (If this is a problem maybe we could also move the
kinfo_getvmmap invocations into a seperate source file but that would
be more work...)
Signed-off-by: Juergen Lock <nox@jelal.kn-bremen.de>
Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
Diffstat (limited to 'exec.c')
-rw-r--r-- | exec.c | 50 |
1 files changed, 50 insertions, 0 deletions
@@ -42,6 +42,21 @@ #if defined(CONFIG_USER_ONLY) #include <qemu.h> #include <signal.h> +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) +#include <sys/param.h> +#if __FreeBSD_version >= 700104 +#define HAVE_KINFO_GETVMMAP +#define sigqueue sigqueue_freebsd /* avoid redefinition */ +#include <sys/time.h> +#include <sys/proc.h> +#include <machine/profile.h> +#define _KERNEL +#include <sys/user.h> +#undef _KERNEL +#undef sigqueue +#include <libutil.h> +#endif +#endif #endif //#define DEBUG_TB_INVALIDATE @@ -275,11 +290,45 @@ static void page_init(void) #if !defined(_WIN32) && defined(CONFIG_USER_ONLY) { +#ifdef HAVE_KINFO_GETVMMAP + struct kinfo_vmentry *freep; + int i, cnt; + + freep = kinfo_getvmmap(getpid(), &cnt); + if (freep) { + mmap_lock(); + for (i = 0; i < cnt; i++) { + unsigned long startaddr, endaddr; + + startaddr = freep[i].kve_start; + endaddr = freep[i].kve_end; + if (h2g_valid(startaddr)) { + startaddr = h2g(startaddr) & TARGET_PAGE_MASK; + + if (h2g_valid(endaddr)) { + endaddr = h2g(endaddr); + page_set_flags(startaddr, endaddr, PAGE_RESERVED); + } else { +#if TARGET_ABI_BITS <= L1_MAP_ADDR_SPACE_BITS + endaddr = ~0ul; + page_set_flags(startaddr, endaddr, PAGE_RESERVED); +#endif + } + } + } + free(freep); + mmap_unlock(); + } +#else FILE *f; last_brk = (unsigned long)sbrk(0); +#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) + f = fopen("/compat/linux/proc/self/maps", "r"); +#else f = fopen("/proc/self/maps", "r"); +#endif if (f) { mmap_lock(); @@ -304,6 +353,7 @@ static void page_init(void) fclose(f); mmap_unlock(); } +#endif } #endif } |