diff --git a/hw/boards.h b/hw/boards.h
index 6f0f0d7..2f6003d 100644
--- a/hw/boards.h
+++ b/hw/boards.h
@@ -32,6 +32,7 @@ typedef struct QEMUMachine {
 } QEMUMachine;
 
 int qemu_register_machine(QEMUMachine *m);
+void do_info_machines(Monitor *mon, QObject **data);
 
 extern QEMUMachine *current_machine;
 
diff --git a/monitor.c b/monitor.c
index f0406e8..b6aa2b4 100644
--- a/monitor.c
+++ b/monitor.c
@@ -55,6 +55,7 @@
 #include "json-streamer.h"
 #include "json-parser.h"
 #include "osdep.h"
+#include "hw/boards.h"
 
 //#define DEBUG
 //#define DEBUG_COMPLETION
@@ -2449,6 +2450,14 @@ static const mon_cmd_t info_cmds[] = {
         .mhandler.info_new = do_info_version,
     },
     {
+        .name       = "machines",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show the machine boards",
+        .user_print = monitor_user_noop,
+        .mhandler.info_new = do_info_machines,
+    },
+    {
         .name       = "commands",
         .args_type  = "",
         .params     = "",
diff --git a/vl.c b/vl.c
index 0b38d62..8043fac 100644
--- a/vl.c
+++ b/vl.c
@@ -1537,6 +1537,76 @@ static QEMUMachine *find_default_machine(void)
     return NULL;
 }
 
+
+/**
+ * do_info_machines(): Show machine boards
+ *
+ * Returns a QList object listing all machine boards
+ * available with this QEMU target. Each element in
+ * the list is a QDict object containing the following
+ * keys
+ *
+ *  - "name": short name for the machine board
+ *  - "description": long description of the board
+ *  - "alias": name of an alias
+ *
+ * Example:
+ *
+ *  [
+ *     {
+ *       "name": "pc-0.13",
+ *        "description": "Standard PC",
+ *        "default": 0
+ *     },
+ *     {
+ *       "name": "pc",
+ *       "description": "Standard PC",
+ *       "canonical": "pc-0.13",
+ *       "default": 1
+ *     },
+ *     {
+ *       "name": "pc-0.12",
+ *       "description": "Standard PC",
+ *       "default": 0
+ *     },
+ *     ....
+ *  ]
+ *
+ */
+/* XXX probably better in a hw/boards.c file, but 'first_machine'
+ * and all accessors are defined in this file already
+ */
+void do_info_machines(Monitor *mon, QObject **data)
+{
+    QList *machines = qlist_new();
+    QEMUMachine *m;
+
+    for (m = first_machine; m != NULL; m = m->next) {
+        QObject *entry;
+
+	entry = qobject_from_jsonf("{ 'name': %s, 'description': %s, 'default': %d}",
+				   m->name, m->desc,
+				   !m->alias && m->is_default ? 1 : 0);
+
+	qlist_append_obj(machines, entry);
+
+	if (m->alias) {
+	    QObject *alias;
+
+	    alias = qobject_from_jsonf("{ 'name': %s, 'description': %s, 'default': %d, 'canonical': %s}",
+				       m->alias, m->desc,
+				       m->is_default ? 1 : 0, m->name);
+
+	    qlist_append_obj(machines, alias);
+	}
+
+	/* XXX list the default devices for each machine type here too ? */
+    }
+
+    *data = QOBJECT(machines);
+}
+
+
 /***********************************************************/
 /* main execution loop */
 
