diff --git a/include/system/system.h b/include/system/system.h index dc7628357a..a7effe7dfd 100644 --- a/include/system/system.h +++ b/include/system/system.h @@ -50,9 +50,11 @@ extern QEMUClockType rtc_clock; typedef enum { MLOCK_OFF = 0, MLOCK_ON, + MLOCK_ON_FAULT, } MlockState; bool should_mlock(MlockState); +bool is_mlock_on_fault(MlockState); extern MlockState mlock_state; diff --git a/migration/postcopy-ram.c b/migration/postcopy-ram.c index 04068ee039..5d3edfcfec 100644 --- a/migration/postcopy-ram.c +++ b/migration/postcopy-ram.c @@ -652,7 +652,7 @@ int postcopy_ram_incoming_cleanup(MigrationIncomingState *mis) } if (should_mlock(mlock_state)) { - if (os_mlock(false) < 0) { + if (os_mlock(is_mlock_on_fault(mlock_state)) < 0) { error_report("mlock: %s", strerror(errno)); /* * It doesn't feel right to fail at this point, we have a valid diff --git a/qemu-options.hx b/qemu-options.hx index 1b26ad53bd..61270e3206 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4632,21 +4632,25 @@ SRST ERST DEF("overcommit", HAS_ARG, QEMU_OPTION_overcommit, - "-overcommit [mem-lock=on|off][cpu-pm=on|off]\n" + "-overcommit [mem-lock=on|off|on-fault][cpu-pm=on|off]\n" " run qemu with overcommit hints\n" - " mem-lock=on|off controls memory lock support (default: off)\n" + " mem-lock=on|off|on-fault controls memory lock support (default: off)\n" " cpu-pm=on|off controls cpu power management (default: off)\n", QEMU_ARCH_ALL) SRST -``-overcommit mem-lock=on|off`` +``-overcommit mem-lock=on|off|on-fault`` \ ``-overcommit cpu-pm=on|off`` Run qemu with hints about host resource overcommit. The default is to assume that host overcommits all resources. Locking qemu and guest memory can be enabled via ``mem-lock=on`` - (disabled by default). This works when host memory is not - overcommitted and reduces the worst-case latency for guest. + or ``mem-lock=on-fault`` (disabled by default). This works when + host memory is not overcommitted and reduces the worst-case latency for + guest. The on-fault option is better for reducing the memory footprint + since it makes allocations lazy, but the pages still get locked in place + once faulted by the guest or QEMU. Note that the two options are mutually + exclusive. Guest ability to manage power state of host cpus (increasing latency for other processes on the same host cpu, but decreasing latency for diff --git a/system/globals.c b/system/globals.c index adeff38348..316623bd20 100644 --- a/system/globals.c +++ b/system/globals.c @@ -33,7 +33,12 @@ bool should_mlock(MlockState state) { - return state == MLOCK_ON; + return state == MLOCK_ON || state == MLOCK_ON_FAULT; +} + +bool is_mlock_on_fault(MlockState state) +{ + return state == MLOCK_ON_FAULT; } enum vga_retrace_method vga_retrace_method = VGA_RETRACE_DUMB; diff --git a/system/vl.c b/system/vl.c index 2895824c1a..3c0fa2ff64 100644 --- a/system/vl.c +++ b/system/vl.c @@ -351,7 +351,7 @@ static QemuOptsList qemu_overcommit_opts = { .desc = { { .name = "mem-lock", - .type = QEMU_OPT_BOOL, + .type = QEMU_OPT_STRING, }, { .name = "cpu-pm", @@ -797,7 +797,7 @@ static QemuOptsList qemu_run_with_opts = { static void realtime_init(void) { if (should_mlock(mlock_state)) { - if (os_mlock(false) < 0) { + if (os_mlock(is_mlock_on_fault(mlock_state)) < 0) { error_report("locking memory failed"); exit(1); } @@ -1878,7 +1878,7 @@ static void object_option_parse(const char *str) static void overcommit_parse(const char *str) { QemuOpts *opts; - bool enable_mlock; + const char *mem_lock_opt; opts = qemu_opts_parse_noisily(qemu_find_opts("overcommit"), str, false); @@ -1886,11 +1886,31 @@ static void overcommit_parse(const char *str) exit(1); } - enable_mlock = qemu_opt_get_bool(opts, "mem-lock", - should_mlock(mlock_state)); - mlock_state = enable_mlock ? MLOCK_ON : MLOCK_OFF; - enable_cpu_pm = qemu_opt_get_bool(opts, "cpu-pm", enable_cpu_pm); + + mem_lock_opt = qemu_opt_get(opts, "mem-lock"); + if (!mem_lock_opt) { + return; + } + + if (strcmp(mem_lock_opt, "on") == 0) { + mlock_state = MLOCK_ON; + return; + } + + if (strcmp(mem_lock_opt, "off") == 0) { + mlock_state = MLOCK_OFF; + return; + } + + if (strcmp(mem_lock_opt, "on-fault") == 0) { + mlock_state = MLOCK_ON_FAULT; + return; + } + + error_report("parameter 'mem-lock' expects one of " + "'on', 'off', 'on-fault'"); + exit(1); } /*