Syntax: "-dimm id=name,size=sz,node=pxm,populated=on|off"
The starting physical address for all dimms is calculated automatically from top
of memory, skipping the pci hole at [PCI_HOLE_START, 4G).
"populated=on" means the dimm is populated at machine startup. Default is off.
"node" is defining numa proximity for this dimm. Default is node zero.
Example:
"-dimm id=dimm0,size=512M,node=0,populated=off"
will define a 512M memory slot belonging to numa node 0.
Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis(a)profitbricks.com>
---
qemu-config.c | 25 +++++++++++++++++++++++++
qemu-options.hx | 5 +++++
sysemu.h | 1 +
vl.c | 35 +++++++++++++++++++++++++++++++++++
4 files changed, 66 insertions(+), 0 deletions(-)
diff --git a/qemu-config.c b/qemu-config.c
index 5c3296b..4abc31b 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -626,6 +626,30 @@ QemuOptsList qemu_boot_opts = {
},
};
+static QemuOptsList qemu_dimm_opts = {
+ .name = "dimm",
+ .head = QTAILQ_HEAD_INITIALIZER(qemu_dimm_opts.head),
+ .desc = {
+ {
+ .name = "id",
+ .type = QEMU_OPT_STRING,
+ .help = "id of this dimm device",
+ },{
+ .name = "size",
+ .type = QEMU_OPT_SIZE,
+ .help = "memory size for this dimm",
+ },{
+ .name = "populated",
+ .type = QEMU_OPT_BOOL,
+ .help = "populated for this dimm",
+ },{
+ .name = "node",
+ .type = QEMU_OPT_NUMBER,
+ .help = "NUMA node number (i.e. proximity) for this dimm",
+ },
+ { /* end of list */ }
+ },
+};
static QemuOptsList *vm_config_groups[32] = {
&qemu_drive_opts,
&qemu_chardev_opts,
@@ -641,6 +665,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_machine_opts,
&qemu_boot_opts,
&qemu_iscsi_opts,
+ &qemu_dimm_opts,
NULL,
};
diff --git a/qemu-options.hx b/qemu-options.hx
index 8b66264..61909f7 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2747,3 +2747,8 @@ HXCOMM This is the last statement. Insert new options before this line!
STEXI
@end table
ETEXI
+
+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)
diff --git a/sysemu.h b/sysemu.h
index bc2c788..3e21a22 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -136,6 +136,7 @@ extern QEMUClock *rtc_clock;
extern int nb_numa_nodes;
extern uint64_t node_mem[MAX_NODES];
extern uint64_t node_cpumask[MAX_NODES];
+extern int nb_hp_dimms;
#define MAX_OPTION_ROMS 16
typedef struct QEMUOptionRom {
diff --git a/vl.c b/vl.c
index 0ff8818..efe915e 100644
--- a/vl.c
+++ b/vl.c
@@ -120,6 +120,7 @@ int main(int argc, char **argv)
#include "hw/xen.h"
#include "hw/qdev.h"
#include "hw/loader.h"
+#include "hw/dimm.h"
#include "bt-host.h"
#include "net.h"
#include "net/slirp.h"
@@ -242,6 +243,7 @@ QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order
int nb_numa_nodes;
uint64_t node_mem[MAX_NODES];
uint64_t node_cpumask[MAX_NODES];
+int nb_hp_dimms;
uint8_t qemu_uuid[16];
@@ -518,6 +520,23 @@ static void configure_rtc_date_offset(const char *startdate, int legacy)
rtc_date_offset = time(NULL) - rtc_start_date;
}
}
+static void configure_dimm(QemuOpts *opts)
+{
+ const char *id;
+ uint64_t size, node;
+ bool populated;
+ if (nb_hp_dimms == MAX_DIMMS) {
+ fprintf(stderr, "qemu: maximum number of DIMMs (%d) exceeded\n",
+ MAX_DIMMS);
+ exit(1);
+ }
+ id = qemu_opts_id(opts);
+ size = qemu_opt_get_size(opts, "size", DEFAULT_DIMMSIZE);
+ populated = qemu_opt_get_bool(opts, "populated", 0);
+ node = qemu_opt_get_number(opts, "node", 0);
+ dimm_create((char*)id, size, node, nb_hp_dimms, populated);
+ nb_hp_dimms++;
+}
static void configure_rtc(QemuOpts *opts)
{
@@ -2273,6 +2292,8 @@ int main(int argc, char **argv, char **envp)
DisplayChangeListener *dcl;
int cyls, heads, secs, translation;
QemuOpts *hda_opts = NULL, *opts, *machine_opts;
+ QemuOpts *dimm_opts[MAX_DIMMS];
+ int nb_dimm_opts = 0;
QemuOptsList *olist;
int optind;
const char *optarg;
@@ -3200,6 +3221,18 @@ int main(int argc, char **argv, char **envp)
case QEMU_OPTION_qtest_log:
qtest_log = optarg;
break;
+ case QEMU_OPTION_dimm:
+ if (nb_dimm_opts == MAX_DIMMS) {
+ fprintf(stderr, "qemu: maximum number of DIMMs (%d) exceeded\n",
+ MAX_DIMMS);
+ }
+ dimm_opts[nb_dimm_opts] =
+ qemu_opts_parse(qemu_find_opts("dimm"), optarg, 0);
+ if (!dimm_opts[nb_dimm_opts]) {
+ exit(1);
+ }
+ nb_dimm_opts++;
+ break;
default:
os_parse_cmd_args(popt->index, optarg);
}
@@ -3517,6 +3550,8 @@ int main(int argc, char **argv, char **envp)
}
qemu_add_globals();
+ for (i = 0; i < nb_dimm_opts; i++)
+ configure_dimm(dimm_opts[i]);
qdev_machine_init();
machine->init(ram_size, boot_devices,
--
1.7.9