9ae3a8
From 0de3b24dc9428a37330f9065bc3626a3a07a9200 Mon Sep 17 00:00:00 2001
9ae3a8
Message-Id: <0de3b24dc9428a37330f9065bc3626a3a07a9200.1387382496.git.minovotn@redhat.com>
9ae3a8
In-Reply-To: <c5386144fbf09f628148101bc674e2421cdd16e3.1387382496.git.minovotn@redhat.com>
9ae3a8
References: <c5386144fbf09f628148101bc674e2421cdd16e3.1387382496.git.minovotn@redhat.com>
9ae3a8
From: Marcelo Tosatti <mtosatti@redhat.com>
9ae3a8
Date: Thu, 12 Dec 2013 01:36:44 +0100
9ae3a8
Subject: [PATCH 46/46] mempath: prefault pages manually (v4)
9ae3a8
9ae3a8
RH-Author: Marcelo Tosatti <mtosatti@redhat.com>
9ae3a8
Message-id: <20131212013644.GA8646@amt.cnet>
9ae3a8
Patchwork-id: 56243
9ae3a8
O-Subject: [RHEL7 qemu-kvm PATCH] mempath: prefault pages manually (v4)
9ae3a8
Bugzilla: 1026554
9ae3a8
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
RH-Acked-by: Igor Mammedov <imammedo@redhat.com>
9ae3a8
RH-Acked-by: Andrew Jones <drjones@redhat.com>
9ae3a8
9ae3a8
commit ef36fa1492e9105f3fa607b56edc63df513d7da1 upstream
9ae3a8
9ae3a8
v4: s/fail/failed/  (Peter Maydell)
9ae3a8
9ae3a8
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
9ae3a8
Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
9ae3a8
BZ: 1026554
9ae3a8
Signed-off-by: Michal Novotny <minovotn@redhat.com>
9ae3a8
---
9ae3a8
 exec.c          | 59 +++++++++++++++++++++++++++++++++++++++++++++------------
9ae3a8
 qemu-options.hx |  2 --
9ae3a8
 vl.c            |  4 ----
9ae3a8
 3 files changed, 47 insertions(+), 18 deletions(-)
9ae3a8
9ae3a8
diff --git a/exec.c b/exec.c
9ae3a8
index 64af205..571cea4 100644
9ae3a8
--- a/exec.c
9ae3a8
+++ b/exec.c
9ae3a8
@@ -865,6 +865,13 @@ static long gethugepagesize(const char *path)
9ae3a8
     return fs.f_bsize;
9ae3a8
 }
9ae3a8
 
9ae3a8
+static sigjmp_buf sigjump;
9ae3a8
+
9ae3a8
+static void sigbus_handler(int signal)
9ae3a8
+{
9ae3a8
+    siglongjmp(sigjump, 1);
9ae3a8
+}
9ae3a8
+
9ae3a8
 static void *file_ram_alloc(RAMBlock *block,
9ae3a8
                             ram_addr_t memory,
9ae3a8
                             const char *path)
9ae3a8
@@ -874,9 +881,6 @@ static void *file_ram_alloc(RAMBlock *block,
9ae3a8
     char *c;
9ae3a8
     void *area;
9ae3a8
     int fd;
9ae3a8
-#ifdef MAP_POPULATE
9ae3a8
-    int flags;
9ae3a8
-#endif
9ae3a8
     unsigned long hpagesize;
9ae3a8
 
9ae3a8
     hpagesize = gethugepagesize(path);
9ae3a8
@@ -924,21 +928,52 @@ static void *file_ram_alloc(RAMBlock *block,
9ae3a8
     if (ftruncate(fd, memory))
9ae3a8
         perror("ftruncate");
9ae3a8
 
9ae3a8
-#ifdef MAP_POPULATE
9ae3a8
-    /* NB: MAP_POPULATE won't exhaustively alloc all phys pages in the case
9ae3a8
-     * MAP_PRIVATE is requested.  For mem_prealloc we mmap as MAP_SHARED
9ae3a8
-     * to sidestep this quirk.
9ae3a8
-     */
9ae3a8
-    flags = mem_prealloc ? MAP_POPULATE | MAP_SHARED : MAP_PRIVATE;
9ae3a8
-    area = mmap(0, memory, PROT_READ | PROT_WRITE, flags, fd, 0);
9ae3a8
-#else
9ae3a8
     area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
9ae3a8
-#endif
9ae3a8
     if (area == MAP_FAILED) {
9ae3a8
         perror("file_ram_alloc: can't mmap RAM pages");
9ae3a8
         close(fd);
9ae3a8
         return (NULL);
9ae3a8
     }
9ae3a8
+
9ae3a8
+    if (mem_prealloc) {
9ae3a8
+        int ret, i;
9ae3a8
+        struct sigaction act, oldact;
9ae3a8
+        sigset_t set, oldset;
9ae3a8
+
9ae3a8
+        memset(&act, 0, sizeof(act));
9ae3a8
+        act.sa_handler = &sigbus_handler;
9ae3a8
+        act.sa_flags = 0;
9ae3a8
+
9ae3a8
+        ret = sigaction(SIGBUS, &act, &oldact);
9ae3a8
+        if (ret) {
9ae3a8
+            perror("file_ram_alloc: failed to install signal handler");
9ae3a8
+            exit(1);
9ae3a8
+        }
9ae3a8
+
9ae3a8
+        /* unblock SIGBUS */
9ae3a8
+        sigemptyset(&set);
9ae3a8
+        sigaddset(&set, SIGBUS);
9ae3a8
+        pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
9ae3a8
+
9ae3a8
+        if (sigsetjmp(sigjump, 1)) {
9ae3a8
+            fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
9ae3a8
+            exit(1);
9ae3a8
+        }
9ae3a8
+
9ae3a8
+        /* MAP_POPULATE silently ignores failures */
9ae3a8
+        for (i = 0; i < (memory/hpagesize)-1; i++) {
9ae3a8
+            memset(area + (hpagesize*i), 0, 1);
9ae3a8
+        }
9ae3a8
+
9ae3a8
+        ret = sigaction(SIGBUS, &oldact, NULL);
9ae3a8
+        if (ret) {
9ae3a8
+            perror("file_ram_alloc: failed to reinstall signal handler");
9ae3a8
+            exit(1);
9ae3a8
+        }
9ae3a8
+
9ae3a8
+        pthread_sigmask(SIG_SETMASK, &oldset, NULL);
9ae3a8
+    }
9ae3a8
+
9ae3a8
     block->fd = fd;
9ae3a8
     return area;
9ae3a8
 }
9ae3a8
diff --git a/qemu-options.hx b/qemu-options.hx
9ae3a8
index e3c5d67..d9320b5 100644
9ae3a8
--- a/qemu-options.hx
9ae3a8
+++ b/qemu-options.hx
9ae3a8
@@ -228,7 +228,6 @@ STEXI
9ae3a8
 Allocate guest RAM from a temporarily created file in @var{path}.
9ae3a8
 ETEXI
9ae3a8
 
9ae3a8
-#ifdef MAP_POPULATE
9ae3a8
 DEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
9ae3a8
     "-mem-prealloc   preallocate guest memory (use with -mem-path)\n",
9ae3a8
     QEMU_ARCH_ALL)
9ae3a8
@@ -237,7 +236,6 @@ STEXI
9ae3a8
 @findex -mem-prealloc
9ae3a8
 Preallocate memory when using -mem-path.
9ae3a8
 ETEXI
9ae3a8
-#endif
9ae3a8
 
9ae3a8
 DEF("k", HAS_ARG, QEMU_OPTION_k,
9ae3a8
     "-k language     use keyboard layout (for example 'fr' for French)\n",
9ae3a8
diff --git a/vl.c b/vl.c
9ae3a8
index 0cbbdf0..da12b90 100644
9ae3a8
--- a/vl.c
9ae3a8
+++ b/vl.c
9ae3a8
@@ -188,9 +188,7 @@ static int display_remote;
9ae3a8
 const char* keyboard_layout = NULL;
9ae3a8
 ram_addr_t ram_size;
9ae3a8
 const char *mem_path = NULL;
9ae3a8
-#ifdef MAP_POPULATE
9ae3a8
 int mem_prealloc = 0; /* force preallocation of physical target memory */
9ae3a8
-#endif
9ae3a8
 int nb_nics;
9ae3a8
 NICInfo nd_table[MAX_NICS];
9ae3a8
 int autostart;
9ae3a8
@@ -3174,11 +3172,9 @@ int main(int argc, char **argv, char **envp)
9ae3a8
             case QEMU_OPTION_mempath:
9ae3a8
                 mem_path = optarg;
9ae3a8
                 break;
9ae3a8
-#ifdef MAP_POPULATE
9ae3a8
             case QEMU_OPTION_mem_prealloc:
9ae3a8
                 mem_prealloc = 1;
9ae3a8
                 break;
9ae3a8
-#endif
9ae3a8
             case QEMU_OPTION_d:
9ae3a8
                 log_mask = optarg;
9ae3a8
                 break;
9ae3a8
-- 
9ae3a8
1.7.11.7
9ae3a8