Implement batch dimm creation command line options. These could be useful for not bloating the command line with a large number of dimms.
syntax: -dimms pfx=poolid,size=sz,num=n Will create numdimms dimms with ids poolid0, ..., poolidn-1. Each dimm has a size of sz.
Implement -dimmpop option to populate dimms at bootup syntax: -dimmpop pfx=poolid,num=n This will populate n dimms with ids poolid0, ..., poolidn-1.
(live-migration could break here without patch 12/21: -dimmspop needs to be reworked to support populating of individual dimms with same prefix, and not only a range of dimms starting from 0)
Signed-off-by: Vasilis Liaskovitis vasilis.liaskovitis@profitbricks.com --- hw/dimm.c | 9 ++++++ hw/dimm.h | 2 +- qemu-config.c | 45 ++++++++++++++++++++++++++++ qemu-options.hx | 10 ++++++ vl.c | 86 ++++++++++++++++++++++++++++++++++++++++++++++++++++++- 5 files changed, 150 insertions(+), 2 deletions(-)
diff --git a/hw/dimm.c b/hw/dimm.c index 2115567..6e324d3 100644 --- a/hw/dimm.c +++ b/hw/dimm.c @@ -187,6 +187,15 @@ void dimm_calc_offsets(dimm_calcoffset_fn calcfn) } }
+int dimm_set_populated(DimmState *s) +{ + if (s) { + s->populated = true; + return 0; + } + else return -1; +} + /* used to populate and activate dimms at boot time */ void dimm_scan_populated(void) { diff --git a/hw/dimm.h b/hw/dimm.h index b563e3f..0fdf59b 100644 --- a/hw/dimm.h +++ b/hw/dimm.h @@ -60,6 +60,6 @@ void dimm_activate(DimmState *slot); void dimm_deactivate(DimmState *slot); void dimm_scan_populated(void); void dimm_notify(uint32_t idx, uint32_t event); - +int dimm_set_populated(DimmState *s);
#endif diff --git a/qemu-config.c b/qemu-config.c index 4abc31b..7f63186 100644 --- a/qemu-config.c +++ b/qemu-config.c @@ -650,6 +650,49 @@ static QemuOptsList qemu_dimm_opts = { { /* end of list */ } }, }; + +static QemuOptsList qemu_dimms_opts = { + .name = "dimms", + .head = QTAILQ_HEAD_INITIALIZER(qemu_dimms_opts.head), + .desc = { + { + .name = "pfx", + .type = QEMU_OPT_STRING, + .help = "prefix of ids for these dimm devices", + },{ + .name = "size", + .type = QEMU_OPT_SIZE, + .help = "memory size for these dimm", + },{ + .name = "num", + .type = QEMU_OPT_NUMBER, + .help = "number of dimm devices in this pool", + },{ + .name = "node", + .type = QEMU_OPT_NUMBER, + .help = "NUMA node number (i.e. proximity) for these dimms", + }, + { /* end of list */ } + }, +}; + +static QemuOptsList qemu_dimmspop_opts = { + .name = "dimmspop", + .head = QTAILQ_HEAD_INITIALIZER(qemu_dimmspop_opts.head), + .desc = { + { + .name = "pfx", + .type = QEMU_OPT_STRING, + .help = "pool prefix for this dimm device", + },{ + .name = "num", + .type = QEMU_OPT_SIZE, + .help = "number of dimm devices to populate", + }, + { /* end of list */ } + }, +}; + static QemuOptsList *vm_config_groups[32] = { &qemu_drive_opts, &qemu_chardev_opts, @@ -666,6 +709,8 @@ static QemuOptsList *vm_config_groups[32] = { &qemu_boot_opts, &qemu_iscsi_opts, &qemu_dimm_opts, + &qemu_dimms_opts, + &qemu_dimmspop_opts, NULL, };
diff --git a/qemu-options.hx b/qemu-options.hx index 61909f7..0a9326e 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -2752,3 +2752,13 @@ DEF("dimm", HAS_ARG, QEMU_OPTION_dimm, "-dimm id=dimmid,size=sz,node=nd,populated=on|off\n" "specify memory dimm device with name dimmid, size sz on node nd", QEMU_ARCH_ALL) + +DEF("dimms", HAS_ARG, QEMU_OPTION_dimms, + "-dimms pfx=id,size=sz,node=nd\n" + "specify pool of num memory dimm devices of size sz each on node nd", + QEMU_ARCH_ALL) + +DEF("dimmspop", HAS_ARG, QEMU_OPTION_dimmspop, + "-dimmspop pfx=id,num=n\n" + "populate n dimms of pool id (dimms with ids id0,...,idn-1) at system startup", + QEMU_ARCH_ALL) diff --git a/vl.c b/vl.c index efe915e..37752be 100644 --- a/vl.c +++ b/vl.c @@ -538,6 +538,65 @@ static void configure_dimm(QemuOpts *opts) nb_hp_dimms++; }
+static void configure_dimms(QemuOpts *opts) +{ + const char *value, *pfx, *id; + uint64_t size, node; + int num, dimm; + char buf[32]; + + id = qemu_opts_id(opts); + value = qemu_opt_get(opts, "pfx"); + if (!value) { + fprintf(stderr, "qemu: invalid prefix for dimm pool '%s'\n", id); + exit(1); + } + pfx = value; + + size = qemu_opt_get_size(opts, "size", DEFAULT_DIMMSIZE); + num = qemu_opt_get_number(opts, "num", 1); + node = qemu_opt_get_number(opts, "node", 0); + + for (dimm = 0; dimm < num; dimm++) { + if (nb_hp_dimms == MAX_DIMMS) { + fprintf(stderr, "qemu: maximum number of DIMMs (%d) exceeded\n", + MAX_DIMMS); + exit(1); + } + sprintf(buf, "%s%d", pfx, dimm); + dimm_create(g_strdup(buf), size, node, nb_hp_dimms, false); + nb_hp_dimms++; + } +} + +/* populate dimms at startup */ +static void configure_dimmspop(QemuOpts *opts) +{ + const char *value, *pfx, *id; + int num, dimm; + char buf[32]; + + id = qemu_opts_id(opts); + value = qemu_opt_get(opts, "pfx"); + if (!value) { + fprintf(stderr, "qemu: invalid prefix for dimm pool '%s'\n", id); + exit(1); + } + pfx = value; + value = qemu_opt_get(opts, "num"); + if (!value) { + fprintf(stderr, "qemu: number not defined for dimm pool '%s'\n", pfx); + exit(1); + } + else num = atoi(value); + for (dimm = 0; dimm < num; dimm++) { + sprintf(buf, "%s%d", pfx, dimm); + if (dimm_set_populated(dimm_find_from_name(buf)) < 0) { + fprintf(stderr, "qemu: dimm %s not defined for dimm pool '%s'\n", + buf, pfx); + } + } +} static void configure_rtc(QemuOpts *opts) { const char *value; @@ -2293,7 +2352,9 @@ int main(int argc, char **argv, char **envp) int cyls, heads, secs, translation; QemuOpts *hda_opts = NULL, *opts, *machine_opts; QemuOpts *dimm_opts[MAX_DIMMS]; - int nb_dimm_opts = 0; + QemuOpts *dimms_opts[MAX_DIMMS]; + QemuOpts *dimmspop_opts[MAX_DIMMS]; + int nb_dimm_opts = 0, nb_dimms_opts = 0, nb_dimmspop_opts = 0; QemuOptsList *olist; int optind; const char *optarg; @@ -3233,6 +3294,22 @@ int main(int argc, char **argv, char **envp) } nb_dimm_opts++; break; + case QEMU_OPTION_dimms: + dimms_opts[nb_dimms_opts] = + qemu_opts_parse(qemu_find_opts("dimms"), optarg, 0); + if (!dimms_opts[nb_dimms_opts]) { + exit(1); + } + nb_dimms_opts++; + break; + case QEMU_OPTION_dimmspop: + dimmspop_opts[nb_dimmspop_opts] = + qemu_opts_parse(qemu_find_opts("dimmspop"), optarg, 0); + if (!dimmspop_opts[nb_dimmspop_opts]) { + exit(1); + } + nb_dimmspop_opts++; + break; default: os_parse_cmd_args(popt->index, optarg); } @@ -3552,6 +3629,13 @@ int main(int argc, char **argv, char **envp)
for (i = 0; i < nb_dimm_opts; i++) configure_dimm(dimm_opts[i]); + + for (i = 0; i < nb_dimms_opts; i++) + configure_dimms(dimms_opts[i]); + + for (i = 0; i < nb_dimmspop_opts; i++) + configure_dimmspop(dimmspop_opts[i]); + qdev_machine_init();
machine->init(ram_size, boot_devices,