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(a)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,
--
1.7.9