]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Get bsd-user host page protection code working on FreeBSD hosts
authorJuergen Lock <nox@jelal.kn-bremen.de>
Thu, 25 Mar 2010 21:32:16 +0000 (22:32 +0100)
committerBlue Swirl <blauwirbel@gmail.com>
Tue, 30 Mar 2010 17:45:10 +0000 (17:45 +0000)
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>
configure
exec.c

index 664c920b1e272ab644640d31d001897282c0097b..30c6753eb6b599509b01502b622d71818893776f 100755 (executable)
--- a/configure
+++ b/configure
@@ -332,6 +332,8 @@ FreeBSD)
   make="gmake"
   audio_drv_list="oss"
   audio_possible_drivers="oss sdl esd pa"
+  # needed for kinfo_getvmmap(3) in libutil.h
+  LIBS="-lutil $LIBS"
 ;;
 DragonFly)
   bsd="yes"
diff --git a/exec.c b/exec.c
index 8274ec2d0fa9e0e995fb0bbdc8cdf327213951ab..a999edf89148940de5f5bf148fc281b071231c3f 100644 (file)
--- a/exec.c
+++ b/exec.c
 #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
 }