[SeaBIOS] [RFC PATCH v2 21/21] Implement mem_increase, mem_decrease hmp/qmp commands
Vasilis Liaskovitis
vasilis.liaskovitis at profitbricks.com
Wed Jul 11 12:32:06 CEST 2012
This implements batch monitor operations for hot-add and hot-remove. These are
probably better suited for a higher-level management layer, but are useful for
testing. Let me know if there is interest for such commands upstream.
syntax: mem_increase poolid num
will hotplug num dimms from pool poolid. This starts from lowest unpopulated
physical memory (dimm) and trying to cover any existing physical holes.
syntax: mem_decrease poolid num
will hot-unplug num dimms from pool poolid, This starts from highest populated
physical memory (dimm).
Respective qmp commands are "mem-increase", "mem-decrease".
Signed-off-by: Vasilis Liaskovitis <vasilis.liaskovitis at profitbricks.com>
---
hmp-commands.hx | 31 ++++++++++++++++
hw/dimm.c | 104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
hw/dimm.h | 7 ++++
monitor.c | 10 +++++
monitor.h | 2 +
qmp-commands.hx | 40 +++++++++++++++++++++
6 files changed, 194 insertions(+), 0 deletions(-)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 016062e..e0c1cf4 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -648,6 +648,37 @@ STEXI
Hot-add dimm.
ETEXI
+ {
+ .name = "mem_increase",
+ .args_type = "pfx:s,num:s",
+ .params = "pfx num",
+ .help = "hot-plug num dimms of memory pool pfx",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_dimm_add_range,
+ },
+
+STEXI
+ at item mem_increase @var{config}
+ at findex mem_increase
+
+Hotplug dimms.
+ETEXI
+
+ {
+ .name = "mem_decrease",
+ .args_type = "pfx:s,num:s",
+ .params = "pfx num",
+ .help = "hot-unplug num dimms of memory pool pfx",
+ .user_print = monitor_user_noop,
+ .mhandler.cmd_new = do_dimm_del_range,
+ },
+
+STEXI
+ at item mem_decrease @var{config}
+ at findex mem_decrease
+
+Hot-unplug dimms.
+ETEXI
{
.name = "device_del",
diff --git a/hw/dimm.c b/hw/dimm.c
index b544173..48542ba 100644
--- a/hw/dimm.c
+++ b/hw/dimm.c
@@ -166,6 +166,110 @@ int dimm_do(Monitor *mon, const QDict *qdict, bool add)
return 0;
}
+/* Find for dimm_do_range operation
+ DIMM_MIN_UNPOPULATED: used for finding next DIMM to hotplug
+ DIMM_MAX_POPULATED: used for finding next DIMM for hot-unplug
+ */
+
+DimmState *dimm_find_next(char *pfx, uint32_t mode)
+{
+ DeviceState *dev;
+ DimmState *slot, *ret;
+ const char *type;
+ uint32_t idx;
+
+ Error *err = NULL;
+ BusChild *kid;
+ BusState *bus = sysbus_get_default();
+ ret = NULL;
+
+ if (mode == DIMM_MIN_UNPOPULATED)
+ idx = MAX_DIMMS;
+ else if (mode == DIMM_MAX_POPULATED)
+ idx = 0;
+ else
+ return false;
+
+ QTAILQ_FOREACH(kid, &bus->children, sibling) {
+ dev = kid->child;
+ type = object_property_get_str(OBJECT(dev), "type", &err);
+ if (err) {
+ error_free(err);
+ fprintf(stderr, "error getting device type\n");
+ exit(1);
+ }
+
+ if (!strcmp(type, "dimm")) {
+ slot = DIMM(dev);
+ if (strstr(dev->id, pfx) && strcmp(dev->id, pfx)) {
+ if (mode == DIMM_MIN_UNPOPULATED &&
+ (slot->populated == false) &&
+ (slot->pending == false) &&
+ (idx > slot->idx)) {
+ idx = slot->idx;
+ ret = slot;
+ }
+ else if (mode == DIMM_MAX_POPULATED &&
+ (slot->populated == true) &&
+ (slot->pending == false) &&
+ (idx <= slot->idx)) {
+ idx = slot->idx;
+ ret = slot;
+ }
+ }
+ }
+ }
+ return ret;
+}
+
+int dimm_do_range(Monitor *mon, const QDict *qdict, bool add)
+{
+ DimmState *slot = NULL;
+ uint32_t mode;
+ uint32_t idx;
+ int num, ndimms;
+
+ char *pfx = (char*) qdict_get_try_str(qdict, "pfx");
+ if (!pfx) {
+ fprintf(stderr, "ERROR %s invalid pfx\n",__FUNCTION__);
+ return 1;
+ }
+
+ char *value = (char*) qdict_get_try_str(qdict, "num");
+ if (!value) {
+ fprintf(stderr, "ERROR %s invalid pfx\n",__FUNCTION__);
+ return 1;
+ }
+ num = atoi(value);
+
+ if (add)
+ mode = DIMM_MIN_UNPOPULATED;
+ else
+ mode = DIMM_MAX_POPULATED;
+
+ ndimms = 0;
+ while (ndimms < num) {
+ slot = dimm_find_next(pfx, mode);
+ if (slot == NULL) {
+ fprintf(stderr, "%s no further slot found for pool %s\n",
+ __FUNCTION__, pfx);
+ fprintf(stderr, "%s operated on %d / %d requested dimms\n",
+ __FUNCTION__, ndimms, num);
+ return 1;
+ }
+
+ if (add) {
+ dimm_activate(slot);
+ }
+ else {
+ dimm_deactivate(slot);
+ }
+ ndimms++;
+ idx++;
+ }
+
+ return 0;
+}
DimmState *dimm_find_from_idx(uint32_t idx)
{
DimmState *slot;
diff --git a/hw/dimm.h b/hw/dimm.h
index 0fdf59b..7c456fa 100644
--- a/hw/dimm.h
+++ b/hw/dimm.h
@@ -11,6 +11,11 @@
#define DIMM_BITMAP_BYTES (MAX_DIMMS + 7) / 8
#define DEFAULT_DIMMSIZE 1024*1024*1024
+enum {
+ DIMM_MIN_UNPOPULATED= 0,
+ DIMM_MAX_POPULATED = 1
+};
+
typedef enum {
DIMM_REMOVE_SUCCESS = 0,
DIMM_REMOVE_FAIL = 1,
@@ -61,5 +66,7 @@ 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);
+DimmState *dimm_find_next(char *pfx, uint32_t mode);
+int dimm_do_range(Monitor *mon, const QDict *qdict, bool add);
#endif
diff --git a/monitor.c b/monitor.c
index 1dd646c..2e0ce1f 100644
--- a/monitor.c
+++ b/monitor.c
@@ -4838,3 +4838,13 @@ int do_dimm_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
{
return dimm_do(mon, qdict, false);
}
+
+int do_dimm_add_range(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ return dimm_do_range(mon, qdict, true);
+}
+
+int do_dimm_del_range(Monitor *mon, const QDict *qdict, QObject **ret_data)
+{
+ return dimm_do_range(mon, qdict, false);
+}
diff --git a/monitor.h b/monitor.h
index afdd721..8224301 100644
--- a/monitor.h
+++ b/monitor.h
@@ -88,5 +88,7 @@ int qmp_qom_get(Monitor *mon, const QDict *qdict, QObject **ret);
int do_dimm_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
int do_dimm_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_dimm_add_range(Monitor *mon, const QDict *qdict, QObject **ret_data);
+int do_dimm_del_range(Monitor *mon, const QDict *qdict, QObject **ret_data);
#endif /* !MONITOR_H */
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 6c71696..c3f74ea 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -2306,3 +2306,43 @@ Example:
}
EQMP
+
+ {
+ .name = "mem-increase",
+ .args_type = "pfx:s,num:s",
+ .mhandler.cmd_new = do_dimm_add_range,
+ },
+SQMP
+mem-increase
+-------------
+
+Hotplug memory DIMMs from memory pool
+
+Will hotplug num memory DIMMs from pool with name pfx.
+
+Example:
+
+-> { "execute": "mem-increase", "arguments": { "pfx" : "pool", "num": "10" } }
+<- { "return": {} }
+
+EQMP
+
+ {
+ .name = "mem-decrease",
+ .args_type = "pfx:s,num:s",
+ .mhandler.cmd_new = do_dimm_del_range,
+ },
+SQMP
+mem-decrease
+-------------
+
+Hot-unplug memory DIMMs from memory pool
+
+Will hot-unplug num memory DIMMs from pool with name pfx.
+
+Example:
+
+-> { "execute": "mem-decrease", "arguments": { "pfx" : "pool", "num": "10" } }
+<- { "return": {} }
+
+EQMP
--
1.7.9
More information about the SeaBIOS
mailing list