Patchwork [RFC,7/9] Implement memslot command-line option and memslot hmp command

login
register
mail settings
Submitter Vasilis Liaskovitis
Date April 19, 2012, 2:08 p.m.
Message ID <1334844527-18869-8-git-send-email-vasilis.liaskovitis@profitbricks.com>
Download mbox | patch
Permalink /patch/153772/
State New
Headers show

Comments

Vasilis Liaskovitis - April 19, 2012, 2:08 p.m.
Implement -memslot qemu-kvm command line option to define hotplug-able memory
 slots.
 Syntax: "-memslot id=name,start=addr,size=sz,node=nodeid"

 e.g. "-memslot id=hot1,start=4294967296,size=1073741824,node=0"
 will define a 1G memory slot starting at physical address 4G, belonging to numa
 node 0. Defining no node will automatically add a memslot to node 0.

 Also implement a new hmp monitor command for hot-add and hot-remove of memory slots
 Syntax: "memslot slotname action"
 where action is add/delete and slotname is the qdev-id of the memory slot.

 Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis@profitbricks.com>
---
 Makefile.objs   |    2 +-
 hmp-commands.hx |   15 +++++++++++++++
 monitor.c       |    8 ++++++++
 monitor.h       |    1 +
 qemu-config.c   |   25 +++++++++++++++++++++++++
 qemu-options.hx |    8 ++++++++
 sysemu.h        |    1 +
 vl.c            |   40 ++++++++++++++++++++++++++++++++++++++++
 8 files changed, 99 insertions(+), 1 deletions(-)
Avi Kivity - April 19, 2012, 2:22 p.m.
On 04/19/2012 05:08 PM, Vasilis Liaskovitis wrote:
>  Implement -memslot qemu-kvm command line option to define hotplug-able memory
>  slots.
>  Syntax: "-memslot id=name,start=addr,size=sz,node=nodeid"
>
>  e.g. "-memslot id=hot1,start=4294967296,size=1073741824,node=0"
>  will define a 1G memory slot starting at physical address 4G, belonging to numa
>  node 0. Defining no node will automatically add a memslot to node 0.

start=4G,size=1G ought to work too, no?
Vasilis Liaskovitis - April 19, 2012, 6:10 p.m.
Hi,

On Thu, Apr 19, 2012 at 05:22:52PM +0300, Avi Kivity wrote:
> On 04/19/2012 05:08 PM, Vasilis Liaskovitis wrote:
> >  Implement -memslot qemu-kvm command line option to define hotplug-able memory
> >  slots.
> >  Syntax: "-memslot id=name,start=addr,size=sz,node=nodeid"
> >
> >  e.g. "-memslot id=hot1,start=4294967296,size=1073741824,node=0"
> >  will define a 1G memory slot starting at physical address 4G, belonging to numa
> >  node 0. Defining no node will automatically add a memslot to node 0.
> 
> start=4G,size=1G ought to work too, no?

it should, but it didn't when I tried. Probably some silliness on my part, I
will retry.

thanks,

- Vasilis

Patch

diff --git a/Makefile.objs b/Makefile.objs
index 5c3bcda..98ce865 100644
--- a/Makefile.objs
+++ b/Makefile.objs
@@ -240,7 +240,7 @@  hw-obj-$(CONFIG_USB_OHCI) += usb/hcd-ohci.o
 hw-obj-$(CONFIG_USB_EHCI) += usb/hcd-ehci.o
 hw-obj-$(CONFIG_USB_XHCI) += usb/hcd-xhci.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 memslot.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/hmp-commands.hx b/hmp-commands.hx
index a6f5a84..cadf4ca 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -618,6 +618,21 @@  Add device.
 ETEXI
 
     {
+        .name       = "memslot",
+        .args_type  = "id:s,action:s",
+        .params     = "id,action",
+        .help       = "add memslot device",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = do_memslot_add,
+    },
+
+STEXI
+@item memslot_add @var{config}
+@findex memslot_add
+
+Add memslot.
+ETEXI
+    {
         .name       = "device_del",
         .args_type  = "id:s",
         .params     = "device",
diff --git a/monitor.c b/monitor.c
index 8946a10..f672186 100644
--- a/monitor.c
+++ b/monitor.c
@@ -30,6 +30,7 @@ 
 #include "hw/pci.h"
 #include "hw/watchdog.h"
 #include "hw/loader.h"
+#include "hw/memslot.h"
 #include "gdbstub.h"
 #include "net.h"
 #include "net/slirp.h"
@@ -4675,3 +4676,10 @@  int monitor_read_block_device_key(Monitor *mon, const char *device,
 
     return monitor_read_bdrv_key_start(mon, bs, completion_cb, opaque);
 }
+
+int do_memslot_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+#if defined(TARGET_I386) || defined(TARGET_X86_64)
+    return memslot_do(mon, qdict);
+#endif
+}
diff --git a/monitor.h b/monitor.h
index 0d49800..1e14a63 100644
--- a/monitor.h
+++ b/monitor.h
@@ -80,5 +80,6 @@  int monitor_read_password(Monitor *mon, ReadLineFunc *readline_func,
 int qmp_qom_set(Monitor *mon, const QDict *qdict, QObject **ret);
 
 int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret);
+int do_memslot_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #endif /* !MONITOR_H */
diff --git a/qemu-config.c b/qemu-config.c
index be84a03..1f26187 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -613,6 +613,30 @@  QemuOptsList qemu_boot_opts = {
     },
 };
 
+static QemuOptsList qemu_memslot_opts = {
+    .name = "memslot",
+    .head = QTAILQ_HEAD_INITIALIZER(qemu_memslot_opts.head),
+    .desc = {
+        {
+            .name = "id",
+            .type = QEMU_OPT_STRING,
+        },{
+            .name = "start",
+            .type = QEMU_OPT_SIZE,
+            .help = "physical address start for this memslot",
+        },{
+            .name = "size",
+            .type = QEMU_OPT_SIZE,
+            .help = "memory size for this memslot",
+        },{
+            .name = "node",
+            .type = QEMU_OPT_NUMBER,
+            .help = "NUMA node number (i.e. proximity) for this memslot",
+        },
+        { /* end of list */ }
+    },
+};
+
 static QemuOptsList *vm_config_groups[32] = {
     &qemu_drive_opts,
     &qemu_chardev_opts,
@@ -628,6 +652,7 @@  static QemuOptsList *vm_config_groups[32] = {
     &qemu_machine_opts,
     &qemu_boot_opts,
     &qemu_iscsi_opts,
+    &qemu_memslot_opts,
     NULL,
 };
 
diff --git a/qemu-options.hx b/qemu-options.hx
index a169792..aff0546 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -2728,3 +2728,11 @@  HXCOMM This is the last statement. Insert new options before this line!
 STEXI
 @end table
 ETEXI
+
+DEF("memslot", HAS_ARG, QEMU_OPTION_memslot,
+        "-memslot start=num,size=num,id=name\n"
+        "specify unpopulated memory slot",
+        QEMU_ARCH_ALL)
+
+
+
diff --git a/sysemu.h b/sysemu.h
index bc2c788..7247099 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_memslots;
 
 #define MAX_OPTION_ROMS 16
 typedef struct QEMUOptionRom {
diff --git a/vl.c b/vl.c
index 50df453..85ac0f9 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/memslot.h"
 #include "bt-host.h"
 #include "net.h"
 #include "net/slirp.h"
@@ -247,6 +248,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_memslots;
 
 uint8_t qemu_uuid[16];
 
@@ -512,6 +514,36 @@  static void configure_rtc_date_offset(const char *startdate, int legacy)
     }
 }
 
+static void configure_memslot(QemuOpts *opts)
+{
+    const char *value, *id;
+    uint64_t start, size, node;
+
+    id = qemu_opts_id(opts);
+    value = qemu_opt_get(opts, "start");
+    if (!value) {
+        fprintf(stderr, "qemu: invalid start address for memslot '%s'\n", id);
+        exit(1);
+    }
+    start = atoll(value);
+    value = qemu_opt_get(opts, "size");
+    if (!value) {
+        fprintf(stderr, "qemu: invalid size for memslot '%s'\n", id);
+        exit(1);
+    }
+    size = atoi(value);
+    value = qemu_opt_get(opts, "node");
+    if (!value) {
+        fprintf(stderr, "qemu: no node proximity defined for memslot '%s'\n", id);
+        node = 0;
+    }
+    else node = atoi(value);
+    fprintf(stderr, "qemu: memslot %s start %lu size %lu node %lu \n", id,
+            start, size, node);
+    memslot_create((char*)id, start, size, node, nb_hp_memslots);
+    nb_hp_memslots++;
+}
+
 static void configure_rtc(QemuOpts *opts)
 {
     const char *value;
@@ -2330,6 +2362,7 @@  int main(int argc, char **argv, char **envp)
 
     nb_numa_nodes = 0;
     nb_nics = 0;
+    nb_hp_memslots = 0;
 
     autostart= 1;
 
@@ -2521,6 +2554,13 @@  int main(int argc, char **argv, char **envp)
             case QEMU_OPTION_kernel:
                 qemu_opts_set(qemu_find_opts("machine"), 0, "kernel", optarg);
                 break;
+            case QEMU_OPTION_memslot:
+                opts = qemu_opts_parse(qemu_find_opts("memslot"), optarg, 0);
+                if (!opts) {
+                    exit(1);
+                }
+                configure_memslot(opts);
+                break;
             case QEMU_OPTION_initrd:
                 qemu_opts_set(qemu_find_opts("machine"), 0, "initrd", optarg);
                 break;