aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarcelo Tosatti <mtosatti@redhat.com>2013-10-28 18:51:46 -0200
committerPaolo Bonzini <pbonzini@redhat.com>2013-11-25 11:28:56 +0100
commitef36fa1492e9105f3fa607b56edc63df513d7da1 (patch)
tree3224e7e3b980f4ed42e89ac825fd21bfed93fcc9
parentfb541ca59c8b55911821c9f794c3dbe5de9ba9d8 (diff)
qemu: mempath: prefault pages manually (v4)
v4: s/fail/failed/ (Peter Maydell) Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
-rw-r--r--exec.c59
-rw-r--r--qemu-options.hx2
-rw-r--r--vl.c4
3 files changed, 47 insertions, 18 deletions
diff --git a/exec.c b/exec.c
index 95c4356c65..f4b9ef25f5 100644
--- a/exec.c
+++ b/exec.c
@@ -904,6 +904,13 @@ static long gethugepagesize(const char *path)
return fs.f_bsize;
}
+static sigjmp_buf sigjump;
+
+static void sigbus_handler(int signal)
+{
+ siglongjmp(sigjump, 1);
+}
+
static void *file_ram_alloc(RAMBlock *block,
ram_addr_t memory,
const char *path)
@@ -913,9 +920,6 @@ static void *file_ram_alloc(RAMBlock *block,
char *c;
void *area;
int fd;
-#ifdef MAP_POPULATE
- int flags;
-#endif
unsigned long hpagesize;
hpagesize = gethugepagesize(path);
@@ -963,21 +967,52 @@ static void *file_ram_alloc(RAMBlock *block,
if (ftruncate(fd, memory))
perror("ftruncate");
-#ifdef MAP_POPULATE
- /* NB: MAP_POPULATE won't exhaustively alloc all phys pages in the case
- * MAP_PRIVATE is requested. For mem_prealloc we mmap as MAP_SHARED
- * to sidestep this quirk.
- */
- flags = mem_prealloc ? MAP_POPULATE | MAP_SHARED : MAP_PRIVATE;
- area = mmap(0, memory, PROT_READ | PROT_WRITE, flags, fd, 0);
-#else
area = mmap(0, memory, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
-#endif
if (area == MAP_FAILED) {
perror("file_ram_alloc: can't mmap RAM pages");
close(fd);
return (NULL);
}
+
+ if (mem_prealloc) {
+ int ret, i;
+ struct sigaction act, oldact;
+ sigset_t set, oldset;
+
+ memset(&act, 0, sizeof(act));
+ act.sa_handler = &sigbus_handler;
+ act.sa_flags = 0;
+
+ ret = sigaction(SIGBUS, &act, &oldact);
+ if (ret) {
+ perror("file_ram_alloc: failed to install signal handler");
+ exit(1);
+ }
+
+ /* unblock SIGBUS */
+ sigemptyset(&set);
+ sigaddset(&set, SIGBUS);
+ pthread_sigmask(SIG_UNBLOCK, &set, &oldset);
+
+ if (sigsetjmp(sigjump, 1)) {
+ fprintf(stderr, "file_ram_alloc: failed to preallocate pages\n");
+ exit(1);
+ }
+
+ /* MAP_POPULATE silently ignores failures */
+ for (i = 0; i < (memory/hpagesize)-1; i++) {
+ memset(area + (hpagesize*i), 0, 1);
+ }
+
+ ret = sigaction(SIGBUS, &oldact, NULL);
+ if (ret) {
+ perror("file_ram_alloc: failed to reinstall signal handler");
+ exit(1);
+ }
+
+ pthread_sigmask(SIG_SETMASK, &oldset, NULL);
+ }
+
block->fd = fd;
return area;
}
diff --git a/qemu-options.hx b/qemu-options.hx
index 8b9426484d..eafc022ad0 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -228,7 +228,6 @@ STEXI
Allocate guest RAM from a temporarily created file in @var{path}.
ETEXI
-#ifdef MAP_POPULATE
DEF("mem-prealloc", 0, QEMU_OPTION_mem_prealloc,
"-mem-prealloc preallocate guest memory (use with -mem-path)\n",
QEMU_ARCH_ALL)
@@ -237,7 +236,6 @@ STEXI
@findex -mem-prealloc
Preallocate memory when using -mem-path.
ETEXI
-#endif
DEF("k", HAS_ARG, QEMU_OPTION_k,
"-k language use keyboard layout (for example 'fr' for French)\n",
diff --git a/vl.c b/vl.c
index 8d5d874e68..d191f518d9 100644
--- a/vl.c
+++ b/vl.c
@@ -188,9 +188,7 @@ static int display_remote;
const char* keyboard_layout = NULL;
ram_addr_t ram_size;
const char *mem_path = NULL;
-#ifdef MAP_POPULATE
int mem_prealloc = 0; /* force preallocation of physical target memory */
-#endif
int nb_nics;
NICInfo nd_table[MAX_NICS];
int autostart;
@@ -3206,11 +3204,9 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_mempath:
mem_path = optarg;
break;
-#ifdef MAP_POPULATE
case QEMU_OPTION_mem_prealloc:
mem_prealloc = 1;
break;
-#endif
case QEMU_OPTION_d:
log_mask = optarg;
break;