Commit ef36fa14 authored by Marcelo Tosatti's avatar Marcelo Tosatti Committed by Paolo Bonzini
Browse files

qemu: mempath: prefault pages manually (v4)



v4: s/fail/failed/  (Peter Maydell)

Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
parent fb541ca5
Loading
Loading
Loading
Loading
+47 −12
Original line number Diff line number Diff line
@@ -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;
}
+0 −2
Original line number Diff line number Diff line
@@ -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",
+0 −4
Original line number Diff line number Diff line
@@ -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;