Adds option to -m "mem" - startup memory amount For compatibility with legacy CLI if suffix-less number is passed, it assumes amount in Mb.
Otherwise user is free to use suffixed number using suffixes b,k/K,M,G Signed-off-by: Igor Mammedov <imamm...@redhat.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- v2: - various fixes suggested by Laszlo Ersek <ler...@redhat.com> - check for overflow - check for empty mem="" case - reshuffle code to avoid conflicts with another series on list - some style/typo fixes --- qemu-options.hx | 12 ++++++--- vl.c | 68 ++++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 65 insertions(+), 15 deletions(-) diff --git a/qemu-options.hx b/qemu-options.hx index 56e5fdf..42f7b64 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -210,14 +210,18 @@ use is discouraged as it may be removed from future versions. ETEXI DEF("m", HAS_ARG, QEMU_OPTION_m, - "-m megs set virtual RAM size to megs MB [default=" - stringify(DEFAULT_RAM_SIZE) "]\n", QEMU_ARCH_ALL) + "-m [mem=]size\n" + " configure guest RAM size\n" + " mem: initial amount of guest memory (default: " + stringify(DEFAULT_RAM_SIZE) "MB)\n", + QEMU_ARCH_ALL) STEXI @item -m @var{megs} @findex -m -Set virtual RAM size to @var{megs} megabytes. Default is 128 MiB. Optionally, +Set virtual RAM size to @var{size} megabytes. Default is 128 MiB. Optionally, a suffix of ``M'' or ``G'' can be used to signify a value in megabytes or -gigabytes respectively. +gigabytes respectively. If @var{size} is provided without unit suffix then MB +is assumed. ETEXI DEF("mem-path", HAS_ARG, QEMU_OPTION_mempath, diff --git a/vl.c b/vl.c index 7f2595c..410059d 100644 --- a/vl.c +++ b/vl.c @@ -302,6 +302,21 @@ static struct { { .driver = "qxl-vga", .flag = &default_vga }, }; +#define MEMORY_OPTS "memory-opts" +static QemuOptsList qemu_mem_opts = { + .name = MEMORY_OPTS, + .implied_opt_name = "mem", + .head = QTAILQ_HEAD_INITIALIZER(qemu_mem_opts.head), + .merge_lists = true, + .desc = { + { + .name = "mem", + .type = QEMU_OPT_SIZE, + }, + { /* end of list */ } + }, +}; + static QemuOptsList qemu_rtc_opts = { .name = "rtc", .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head), @@ -2868,6 +2883,8 @@ int main(int argc, char **argv, char **envp) }; const char *trace_events = NULL; const char *trace_file = NULL; + const ram_addr_t default_ram_size = (ram_addr_t)DEFAULT_RAM_SIZE * + 1024 * 1024; atexit(qemu_run_exit_notifiers); error_set_progname(argv[0]); @@ -2884,6 +2901,7 @@ int main(int argc, char **argv, char **envp) module_call_init(MODULE_INIT_QOM); + qemu_add_opts(&qemu_mem_opts); qemu_add_opts(&qemu_drive_opts); qemu_add_drive_opts(&qemu_legacy_drive_opts); qemu_add_drive_opts(&qemu_common_drive_opts); @@ -2921,7 +2939,7 @@ int main(int argc, char **argv, char **envp) module_call_init(MODULE_INIT_MACHINE); machine = find_default_machine(); cpu_model = NULL; - ram_size = 0; + ram_size = default_ram_size; snapshot = 0; cyls = heads = secs = 0; translation = BIOS_ATA_TRANSLATION_AUTO; @@ -3198,16 +3216,45 @@ int main(int argc, char **argv, char **envp) exit(0); break; case QEMU_OPTION_m: { - int64_t value; uint64_t sz; - char *end; + const char *mem_str; + + opts = qemu_opts_parse(qemu_find_opts(MEMORY_OPTS), + optarg, 1); + if (!opts) { + exit(1); + } - value = strtosz(optarg, &end); - if (value < 0 || *end) { - fprintf(stderr, "qemu: invalid ram size: %s\n", optarg); + mem_str = qemu_opt_get(opts, "mem"); + if (!mem_str) { + fprintf(stderr, "qemu: invalid -m option, missing " + "'mem' option\n"); + exit(1); + } + if (!strlen(mem_str)) { + fprintf(stderr, "qemu: missing 'mem' option value\n"); exit(1); } - sz = QEMU_ALIGN_UP((uint64_t)value, 8192); + + sz = qemu_opt_get_size(opts, "mem", ram_size); + + /* Fix up legacy suffix-less format */ + if (g_ascii_isdigit(mem_str[strlen(mem_str) - 1])) { + uint64_t overflow_check = sz; + + sz <<= 20; + if ((sz >> 20) != overflow_check) { + fprintf(stderr, "qemu: too large 'mem' option " + "value\n"); + } + } + + /* backward compatibility behaviour for case "-m 0" */ + if (sz == 0) { + sz = default_ram_size; + } + + sz = QEMU_ALIGN_UP(sz, 8192); ram_size = sz; if (ram_size != sz) { fprintf(stderr, "qemu: ram size too large\n"); @@ -4056,10 +4103,9 @@ int main(int argc, char **argv, char **envp) exit(1); } - /* init the memory */ - if (ram_size == 0) { - ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; - } + /* store value for the future use */ + qemu_opt_set_number(qemu_find_opts_singleton(MEMORY_OPTS), + "mem", ram_size); if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, 0) != 0) { -- 1.7.1