summaryrefslogtreecommitdiff
path: root/exec.c
diff options
context:
space:
mode:
authorJuergen Lock <nox@jelal.kn-bremen.de>2010-03-25 22:32:16 +0100
committerBlue Swirl <blauwirbel@gmail.com>2010-03-30 17:45:10 +0000
commitf01576f18569fac675671a81bf931901050c3a73 (patch)
treeb4510ebcd89d56ba7c148077085272b7be995d6c /exec.c
parentb035ffd11813524d7c0e44354f5c4bdd281f4b37 (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.c50
1 files changed, 50 insertions, 0 deletions
diff --git a/exec.c b/exec.c
index 8274ec2d0f..a999edf891 100644
--- a/exec.c
+++ b/exec.c
@@ -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
}