Example:
"-dimm id=dimm0,size=512M,node=0,populated=off"
will define a 512M memory slot belonging to numa node 0.
When "populated=on", a DimmDevice is created and hot-plugged at system startup.
Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis(a)profitbricks.com>
---
hw/Makefile.objs | 2 +-
qemu-config.c | 25 +++++++++++++++++++++++++
qemu-options.hx | 5 +++++
sysemu.h | 1 +
vl.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++
5 files changed, 82 insertions(+), 1 deletions(-)
diff --git a/hw/Makefile.objs b/hw/Makefile.objs
index 6dfebd2..8c5c39a 100644
--- a/hw/Makefile.objs
+++ b/hw/Makefile.objs
@@ -26,7 +26,7 @@ hw-obj-$(CONFIG_I8254) += i8254_common.o i8254.o
hw-obj-$(CONFIG_PCSPK) += pcspk.o
hw-obj-$(CONFIG_PCKBD) += pckbd.o
hw-obj-$(CONFIG_FDC) += fdc.o
-hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o
+hw-obj-$(CONFIG_ACPI) += acpi.o acpi_piix4.o dimm.o
hw-obj-$(CONFIG_APM) += pm_smbus.o apm.o
hw-obj-$(CONFIG_DMA) += dma.o
hw-obj-$(CONFIG_I82374) += i82374.o
diff --git a/qemu-config.c b/qemu-config.c
index eba977e..4022d64 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -646,6 +646,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,
@@ -662,6 +686,7 @@ static QemuOptsList *vm_config_groups[32] = {
&qemu_boot_opts,
&qemu_iscsi_opts,
&qemu_sandbox_opts,
+ &qemu_dimm_opts,
NULL,
};
diff --git a/qemu-options.hx b/qemu-options.hx
index 804a2d1..3687722 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2842,3 +2842,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 65552ac..7baf9c9 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -139,6 +139,7 @@ extern QEMUClock *rtc_clock;
extern int nb_numa_nodes;
extern uint64_t node_mem[MAX_NODES];
extern unsigned long *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 7c577fa..af1745c 100644
--- a/vl.c
+++ b/vl.c
@@ -126,6 +126,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"
@@ -248,6 +249,7 @@ QTAILQ_HEAD(, FWBootEntry) fw_boot_order = QTAILQ_HEAD_INITIALIZER(fw_boot_order
int nb_numa_nodes;
uint64_t node_mem[MAX_NODES];
unsigned long *node_cpumask[MAX_NODES];
+int nb_hp_dimms;
uint8_t qemu_uuid[16];
@@ -530,6 +532,37 @@ static void configure_rtc_date_offset(const char *startdate, int legacy)
}
}
+static void configure_dimm(QemuOpts *opts)
+{
+ const char *id;
+ uint64_t size, node;
+ bool populated;
+ QemuOpts *devopts;
+ char buf[256];
+ 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_config_create((char*)id, size, node, nb_hp_dimms, 0);
+
+ if (populated) {
+ devopts = qemu_opts_create(qemu_find_opts("device"), id, 0, NULL);
+ qemu_opt_set(devopts, "driver", "dimm");
+ snprintf(buf, sizeof(buf), "%lu", size);
+ qemu_opt_set(devopts, "size", buf);
+ snprintf(buf, sizeof(buf), "%lu", node);
+ qemu_opt_set(devopts, "node", buf);
+ qemu_opt_set(devopts, "bus", "membus");
+ }
+ nb_hp_dimms++;
+}
+
static void configure_rtc(QemuOpts *opts)
{
const char *value;
@@ -2354,6 +2387,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;
@@ -3288,6 +3323,18 @@ int main(int argc, char **argv, char **envp)
exit(0);
}
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);
}
@@ -3611,6 +3658,9 @@ 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