All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/29]: QMP queue
@ 2012-06-05 17:24 Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 01/29] Add API to create memory mapping list Luiz Capitulino
                   ` (29 more replies)
  0 siblings, 30 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Contains the new commands dump-guest-memory and query-events; and the
netdev_add/netdev_del conversion to the QAPI.

The changes (since 8cc9b43f7c5f826b39af4b012ad89bb55faac29c) are available
in the following repository:

    git://repo.or.cz/qemu/qmp-unstable.git queue/qmp

Daniel P. Berrange (1):
      Add 'query-events' command to QMP to query async events

Luiz Capitulino (16):
      qemu-option: qemu_opts_create(): use error_set()
      qemu-option: parse_option_number(): use error_set()
      qemu-option: parse_option_bool(): use error_set()
      qemu-option: parse_option_size(): use error_set()
      qemu-option: qemu_opt_parse(): use error_set()
      qemu-option: qemu_opts_validate(): use error_set()
      qemu-option: opt_set(): use error_set()
      qemu-option: introduce qemu_opt_set_err()
      qemu-option: qemu_opts_from_qdict(): use error_set()
      qerror: introduce QERR_INVALID_OPTION_GROUP
      qemu-config: find_list(): use error_set()
      qemu-config: introduce qemu_find_opts_err()
      net: purge the monitor object from all init functions
      net: net_client_init(): use error_set()
      qapi: convert netdev_add
      qapi: convert netdev_del

Wen Congyang (12):
      Add API to create memory mapping list
      Add API to check whether a physical address is I/O address
      implement cpu_get_memory_mapping()
      Add API to check whether paging mode is enabled
      Add API to get memory mapping
      Add API to get memory mapping without do paging
      target-i386: Add API to write elf notes to core file
      target-i386: Add API to write cpu status to core file
      target-i386: add API to get dump info
      target-i386: Add API to get note's size
      make gdb_id() generally avialable and rename it to cpu_index()
      introduce a new monitor command 'dump-guest-memory' to dump guest's memory

 Makefile.target                   |   5 +
 blockdev.c                        |   2 +-
 configure                         |   8 +
 cpu-all.h                         |  70 +++
 cpu-common.h                      |   4 +
 dump.c                            | 883 ++++++++++++++++++++++++++++++++++++++
 dump.h                            |  23 +
 elf.h                             |   5 +
 exec.c                            |  12 +
 gdbstub.c                         |  19 +-
 gdbstub.h                         |   9 +
 hmp-commands.hx                   |  34 +-
 hmp.c                             |  52 +++
 hmp.h                             |   3 +
 hw/pci-hotplug.c                  |   8 +-
 hw/qdev-monitor.c                 |   7 +-
 hw/usb/dev-network.c              |   7 +-
 hw/usb/dev-storage.c              |   2 +-
 hw/watchdog.c                     |   2 +-
 memory_mapping.c                  | 249 +++++++++++
 memory_mapping.h                  |  74 ++++
 monitor.c                         | 107 ++---
 monitor.h                         |   4 +
 net.c                             | 104 +++--
 net.h                             |   6 +-
 net/dump.c                        |   2 +-
 net/dump.h                        |   3 +-
 net/slirp.c                       |   5 +-
 net/slirp.h                       |   5 +-
 net/socket.c                      |   8 +-
 net/socket.h                      |   3 +-
 net/tap-win32.c                   |   2 +-
 net/tap.c                         |   9 +-
 net/tap.h                         |   5 +-
 net/vde.c                         |   2 +-
 net/vde.h                         |   2 +-
 qapi-schema.json                  | 107 +++++
 qemu-char.c                       |   8 +-
 qemu-config.c                     |  43 +-
 qemu-config.h                     |   3 +
 qemu-option.c                     | 175 +++++---
 qemu-option.h                     |  11 +-
 qemu-sockets.c                    |   8 +-
 qerror.c                          |   4 +
 qerror.h                          |   3 +
 qmp-commands.hx                   |  83 +++-
 target-i386/arch_dump.c           | 449 +++++++++++++++++++
 target-i386/arch_memory_mapping.c | 271 ++++++++++++
 vl.c                              |  22 +-
 49 files changed, 2685 insertions(+), 247 deletions(-)

^ permalink raw reply	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 01/29] Add API to create memory mapping list
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 02/29] Add API to check whether a physical address is I/O address Luiz Capitulino
                   ` (28 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

The memory mapping list stores virtual address and physical address mapping.
The virtual address and physical address are contiguous in the mapping.
The folloing patch will use this information to create PT_LOAD in the vmcore.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile.target  |   1 +
 memory_mapping.c | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |  47 ++++++++++++++++
 3 files changed, 214 insertions(+)
 create mode 100644 memory_mapping.c
 create mode 100644 memory_mapping.h

diff --git a/Makefile.target b/Makefile.target
index 1582904..005fc49 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -192,6 +192,7 @@ obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
+obj-y += memory_mapping.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/memory_mapping.c b/memory_mapping.c
new file mode 100644
index 0000000..718f271
--- /dev/null
+++ b/memory_mapping.c
@@ -0,0 +1,166 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "memory_mapping.h"
+
+static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list,
+                                                   MemoryMapping *mapping)
+{
+    MemoryMapping *p;
+
+    QTAILQ_FOREACH(p, &list->head, next) {
+        if (p->phys_addr >= mapping->phys_addr) {
+            QTAILQ_INSERT_BEFORE(p, mapping, next);
+            return;
+        }
+    }
+    QTAILQ_INSERT_TAIL(&list->head, mapping, next);
+}
+
+static void create_new_memory_mapping(MemoryMappingList *list,
+                                      target_phys_addr_t phys_addr,
+                                      target_phys_addr_t virt_addr,
+                                      ram_addr_t length)
+{
+    MemoryMapping *memory_mapping;
+
+    memory_mapping = g_malloc(sizeof(MemoryMapping));
+    memory_mapping->phys_addr = phys_addr;
+    memory_mapping->virt_addr = virt_addr;
+    memory_mapping->length = length;
+    list->last_mapping = memory_mapping;
+    list->num++;
+    memory_mapping_list_add_mapping_sorted(list, memory_mapping);
+}
+
+static inline bool mapping_contiguous(MemoryMapping *map,
+                                      target_phys_addr_t phys_addr,
+                                      target_phys_addr_t virt_addr)
+{
+    return phys_addr == map->phys_addr + map->length &&
+           virt_addr == map->virt_addr + map->length;
+}
+
+/*
+ * [map->phys_addr, map->phys_addr + map->length) and
+ * [phys_addr, phys_addr + length) have intersection?
+ */
+static inline bool mapping_have_same_region(MemoryMapping *map,
+                                            target_phys_addr_t phys_addr,
+                                            ram_addr_t length)
+{
+    return !(phys_addr + length < map->phys_addr ||
+             phys_addr >= map->phys_addr + map->length);
+}
+
+/*
+ * [map->phys_addr, map->phys_addr + map->length) and
+ * [phys_addr, phys_addr + length) have intersection. The virtual address in the
+ * intersection are the same?
+ */
+static inline bool mapping_conflict(MemoryMapping *map,
+                                    target_phys_addr_t phys_addr,
+                                    target_phys_addr_t virt_addr)
+{
+    return virt_addr - map->virt_addr != phys_addr - map->phys_addr;
+}
+
+/*
+ * [map->virt_addr, map->virt_addr + map->length) and
+ * [virt_addr, virt_addr + length) have intersection. And the physical address
+ * in the intersection are the same.
+ */
+static inline void mapping_merge(MemoryMapping *map,
+                                 target_phys_addr_t virt_addr,
+                                 ram_addr_t length)
+{
+    if (virt_addr < map->virt_addr) {
+        map->length += map->virt_addr - virt_addr;
+        map->virt_addr = virt_addr;
+    }
+
+    if ((virt_addr + length) >
+        (map->virt_addr + map->length)) {
+        map->length = virt_addr + length - map->virt_addr;
+    }
+}
+
+void memory_mapping_list_add_merge_sorted(MemoryMappingList *list,
+                                          target_phys_addr_t phys_addr,
+                                          target_phys_addr_t virt_addr,
+                                          ram_addr_t length)
+{
+    MemoryMapping *memory_mapping, *last_mapping;
+
+    if (QTAILQ_EMPTY(&list->head)) {
+        create_new_memory_mapping(list, phys_addr, virt_addr, length);
+        return;
+    }
+
+    last_mapping = list->last_mapping;
+    if (last_mapping) {
+        if (mapping_contiguous(last_mapping, phys_addr, virt_addr)) {
+            last_mapping->length += length;
+            return;
+        }
+    }
+
+    QTAILQ_FOREACH(memory_mapping, &list->head, next) {
+        if (mapping_contiguous(memory_mapping, phys_addr, virt_addr)) {
+            memory_mapping->length += length;
+            list->last_mapping = memory_mapping;
+            return;
+        }
+
+        if (phys_addr + length < memory_mapping->phys_addr) {
+            /* create a new region before memory_mapping */
+            break;
+        }
+
+        if (mapping_have_same_region(memory_mapping, phys_addr, length)) {
+            if (mapping_conflict(memory_mapping, phys_addr, virt_addr)) {
+                continue;
+            }
+
+            /* merge this region into memory_mapping */
+            mapping_merge(memory_mapping, virt_addr, length);
+            list->last_mapping = memory_mapping;
+            return;
+        }
+    }
+
+    /* this region can not be merged into any existed memory mapping. */
+    create_new_memory_mapping(list, phys_addr, virt_addr, length);
+}
+
+void memory_mapping_list_free(MemoryMappingList *list)
+{
+    MemoryMapping *p, *q;
+
+    QTAILQ_FOREACH_SAFE(p, &list->head, next, q) {
+        QTAILQ_REMOVE(&list->head, p, next);
+        g_free(p);
+    }
+
+    list->num = 0;
+    list->last_mapping = NULL;
+}
+
+void memory_mapping_list_init(MemoryMappingList *list)
+{
+    list->num = 0;
+    list->last_mapping = NULL;
+    QTAILQ_INIT(&list->head);
+}
diff --git a/memory_mapping.h b/memory_mapping.h
new file mode 100644
index 0000000..836b047
--- /dev/null
+++ b/memory_mapping.h
@@ -0,0 +1,47 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef MEMORY_MAPPING_H
+#define MEMORY_MAPPING_H
+
+#include "qemu-queue.h"
+
+/* The physical and virtual address in the memory mapping are contiguous. */
+typedef struct MemoryMapping {
+    target_phys_addr_t phys_addr;
+    target_ulong virt_addr;
+    ram_addr_t length;
+    QTAILQ_ENTRY(MemoryMapping) next;
+} MemoryMapping;
+
+typedef struct MemoryMappingList {
+    unsigned int num;
+    MemoryMapping *last_mapping;
+    QTAILQ_HEAD(, MemoryMapping) head;
+} MemoryMappingList;
+
+/*
+ * add or merge the memory region [phys_addr, phys_addr + length) into the
+ * memory mapping's list. The region's virtual address starts with virt_addr,
+ * and is contiguous. The list is sorted by phys_addr.
+ */
+void memory_mapping_list_add_merge_sorted(MemoryMappingList *list,
+                                          target_phys_addr_t phys_addr,
+                                          target_phys_addr_t virt_addr,
+                                          ram_addr_t length);
+
+void memory_mapping_list_free(MemoryMappingList *list);
+
+void memory_mapping_list_init(MemoryMappingList *list);
+
+#endif
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 02/29] Add API to check whether a physical address is I/O address
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 01/29] Add API to create memory mapping list Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 03/29] implement cpu_get_memory_mapping() Luiz Capitulino
                   ` (27 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

This API will be used in the following patch.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpu-common.h |  4 ++++
 exec.c       | 12 ++++++++++++
 2 files changed, 16 insertions(+)

diff --git a/cpu-common.h b/cpu-common.h
index dca5175..1fe3280 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -71,6 +71,10 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
 void cpu_unregister_map_client(void *cookie);
 
+#ifndef CONFIG_USER_ONLY
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr);
+#endif
+
 /* Coalesced MMIO regions are areas where write operations can be reordered.
  * This usually implies that write operations are side-effect free.  This allows
  * batching which can make a major impact on performance when using
diff --git a/exec.c b/exec.c
index a0494c7..1b65859 100644
--- a/exec.c
+++ b/exec.c
@@ -4336,3 +4336,15 @@ bool virtio_is_big_endian(void)
 }
 
 #endif
+
+#ifndef CONFIG_USER_ONLY
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr)
+{
+    MemoryRegionSection *section;
+
+    section = phys_page_find(phys_addr >> TARGET_PAGE_BITS);
+
+    return !(memory_region_is_ram(section->mr) ||
+             memory_region_is_romd(section->mr));
+}
+#endif
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 03/29] implement cpu_get_memory_mapping()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 01/29] Add API to create memory mapping list Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 02/29] Add API to check whether a physical address is I/O address Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 04/29] Add API to check whether paging mode is enabled Luiz Capitulino
                   ` (26 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

Walk cpu's page table and collect all virtual address and physical address mapping.
Then, add these mapping into memory mapping list. If the guest does not use paging,
it will do nothing. Note: the I/O memory will be skipped.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile.target                   |   1 +
 configure                         |   4 +
 cpu-all.h                         |  11 ++
 memory_mapping.h                  |   6 +
 target-i386/arch_memory_mapping.c | 266 ++++++++++++++++++++++++++++++++++++++
 5 files changed, 288 insertions(+)
 create mode 100644 target-i386/arch_memory_mapping.c

diff --git a/Makefile.target b/Makefile.target
index 005fc49..18ffaef 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -193,6 +193,7 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
 obj-y += memory_mapping.o
+obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/configure b/configure
index 1f338f8..20608c5 100755
--- a/configure
+++ b/configure
@@ -3729,6 +3729,10 @@ case "$target_arch2" in
       fi
     fi
 esac
+case "$target_arch2" in
+  i386|x86_64)
+    echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
+esac
 if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
   echo "CONFIG_PSERIES=y" >> $config_target_mak
 fi
diff --git a/cpu-all.h b/cpu-all.h
index 028528f..2688bac 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -22,6 +22,7 @@
 #include "qemu-common.h"
 #include "qemu-tls.h"
 #include "cpu-common.h"
+#include "memory_mapping.h"
 
 /* some important defines:
  *
@@ -524,4 +525,14 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
+#else
+static inline int cpu_get_memory_mapping(MemoryMappingList *list,
+                                         CPUArchState *env)
+{
+    return -1;
+}
+#endif
+
 #endif /* CPU_ALL_H */
diff --git a/memory_mapping.h b/memory_mapping.h
index 836b047..e486d10 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -16,6 +16,7 @@
 
 #include "qemu-queue.h"
 
+#ifndef CONFIG_USER_ONLY
 /* The physical and virtual address in the memory mapping are contiguous. */
 typedef struct MemoryMapping {
     target_phys_addr_t phys_addr;
@@ -44,4 +45,9 @@ void memory_mapping_list_free(MemoryMappingList *list);
 
 void memory_mapping_list_init(MemoryMappingList *list);
 
+#else
+
+/* We use MemoryMappingList* in cpu-all.h */
+typedef struct MemoryMappingList MemoryMappingList;
+#endif
 #endif
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
new file mode 100644
index 0000000..dd64bec
--- /dev/null
+++ b/target-i386/arch_memory_mapping.c
@@ -0,0 +1,266 @@
+/*
+ * i386 memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+
+/* PAE Paging or IA-32e Paging */
+static void walk_pte(MemoryMappingList *list, target_phys_addr_t pte_start_addr,
+                     int32_t a20_mask, target_ulong start_line_addr)
+{
+    target_phys_addr_t pte_addr, start_paddr;
+    uint64_t pte;
+    target_ulong start_vaddr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pte_addr = (pte_start_addr + i * 8) & a20_mask;
+        pte = ldq_phys(pte_addr);
+        if (!(pte & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        start_paddr = (pte & ~0xfff) & ~(0x1ULL << 63);
+        if (cpu_physical_memory_is_io(start_paddr)) {
+            /* I/O region */
+            continue;
+        }
+
+        start_vaddr = start_line_addr | ((i & 0x1fff) << 12);
+        memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                             start_vaddr, 1 << 12);
+    }
+}
+
+/* 32-bit Paging */
+static void walk_pte2(MemoryMappingList *list,
+                      target_phys_addr_t pte_start_addr, int32_t a20_mask,
+                      target_ulong start_line_addr)
+{
+    target_phys_addr_t pte_addr, start_paddr;
+    uint32_t pte;
+    target_ulong start_vaddr;
+    int i;
+
+    for (i = 0; i < 1024; i++) {
+        pte_addr = (pte_start_addr + i * 4) & a20_mask;
+        pte = ldl_phys(pte_addr);
+        if (!(pte & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        start_paddr = pte & ~0xfff;
+        if (cpu_physical_memory_is_io(start_paddr)) {
+            /* I/O region */
+            continue;
+        }
+
+        start_vaddr = start_line_addr | ((i & 0x3ff) << 12);
+        memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                             start_vaddr, 1 << 12);
+    }
+}
+
+/* PAE Paging or IA-32e Paging */
+static void walk_pde(MemoryMappingList *list, target_phys_addr_t pde_start_addr,
+                     int32_t a20_mask, target_ulong start_line_addr)
+{
+    target_phys_addr_t pde_addr, pte_start_addr, start_paddr;
+    uint64_t pde;
+    target_ulong line_addr, start_vaddr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pde_addr = (pde_start_addr + i * 8) & a20_mask;
+        pde = ldq_phys(pde_addr);
+        if (!(pde & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = start_line_addr | ((i & 0x1ff) << 21);
+        if (pde & PG_PSE_MASK) {
+            /* 2 MB page */
+            start_paddr = (pde & ~0x1fffff) & ~(0x1ULL << 63);
+            if (cpu_physical_memory_is_io(start_paddr)) {
+                /* I/O region */
+                continue;
+            }
+            start_vaddr = line_addr;
+            memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                                 start_vaddr, 1 << 21);
+            continue;
+        }
+
+        pte_start_addr = (pde & ~0xfff) & a20_mask;
+        walk_pte(list, pte_start_addr, a20_mask, line_addr);
+    }
+}
+
+/* 32-bit Paging */
+static void walk_pde2(MemoryMappingList *list,
+                      target_phys_addr_t pde_start_addr, int32_t a20_mask,
+                      bool pse)
+{
+    target_phys_addr_t pde_addr, pte_start_addr, start_paddr;
+    uint32_t pde;
+    target_ulong line_addr, start_vaddr;
+    int i;
+
+    for (i = 0; i < 1024; i++) {
+        pde_addr = (pde_start_addr + i * 4) & a20_mask;
+        pde = ldl_phys(pde_addr);
+        if (!(pde & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = (((unsigned int)i & 0x3ff) << 22);
+        if ((pde & PG_PSE_MASK) && pse) {
+            /* 4 MB page */
+            start_paddr = (pde & ~0x3fffff) | ((pde & 0x1fe000) << 19);
+            if (cpu_physical_memory_is_io(start_paddr)) {
+                /* I/O region */
+                continue;
+            }
+            start_vaddr = line_addr;
+            memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                                 start_vaddr, 1 << 22);
+            continue;
+        }
+
+        pte_start_addr = (pde & ~0xfff) & a20_mask;
+        walk_pte2(list, pte_start_addr, a20_mask, line_addr);
+    }
+}
+
+/* PAE Paging */
+static void walk_pdpe2(MemoryMappingList *list,
+                       target_phys_addr_t pdpe_start_addr, int32_t a20_mask)
+{
+    target_phys_addr_t pdpe_addr, pde_start_addr;
+    uint64_t pdpe;
+    target_ulong line_addr;
+    int i;
+
+    for (i = 0; i < 4; i++) {
+        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
+        pdpe = ldq_phys(pdpe_addr);
+        if (!(pdpe & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = (((unsigned int)i & 0x3) << 30);
+        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
+        walk_pde(list, pde_start_addr, a20_mask, line_addr);
+    }
+}
+
+#ifdef TARGET_X86_64
+/* IA-32e Paging */
+static void walk_pdpe(MemoryMappingList *list,
+                      target_phys_addr_t pdpe_start_addr, int32_t a20_mask,
+                      target_ulong start_line_addr)
+{
+    target_phys_addr_t pdpe_addr, pde_start_addr, start_paddr;
+    uint64_t pdpe;
+    target_ulong line_addr, start_vaddr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pdpe_addr = (pdpe_start_addr + i * 8) & a20_mask;
+        pdpe = ldq_phys(pdpe_addr);
+        if (!(pdpe & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = start_line_addr | ((i & 0x1ffULL) << 30);
+        if (pdpe & PG_PSE_MASK) {
+            /* 1 GB page */
+            start_paddr = (pdpe & ~0x3fffffff) & ~(0x1ULL << 63);
+            if (cpu_physical_memory_is_io(start_paddr)) {
+                /* I/O region */
+                continue;
+            }
+            start_vaddr = line_addr;
+            memory_mapping_list_add_merge_sorted(list, start_paddr,
+                                                 start_vaddr, 1 << 30);
+            continue;
+        }
+
+        pde_start_addr = (pdpe & ~0xfff) & a20_mask;
+        walk_pde(list, pde_start_addr, a20_mask, line_addr);
+    }
+}
+
+/* IA-32e Paging */
+static void walk_pml4e(MemoryMappingList *list,
+                       target_phys_addr_t pml4e_start_addr, int32_t a20_mask)
+{
+    target_phys_addr_t pml4e_addr, pdpe_start_addr;
+    uint64_t pml4e;
+    target_ulong line_addr;
+    int i;
+
+    for (i = 0; i < 512; i++) {
+        pml4e_addr = (pml4e_start_addr + i * 8) & a20_mask;
+        pml4e = ldq_phys(pml4e_addr);
+        if (!(pml4e & PG_PRESENT_MASK)) {
+            /* not present */
+            continue;
+        }
+
+        line_addr = ((i & 0x1ffULL) << 39) | (0xffffULL << 48);
+        pdpe_start_addr = (pml4e & ~0xfff) & a20_mask;
+        walk_pdpe(list, pdpe_start_addr, a20_mask, line_addr);
+    }
+}
+#endif
+
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
+{
+    if (!(env->cr[0] & CR0_PG_MASK)) {
+        /* paging is disabled */
+        return 0;
+    }
+
+    if (env->cr[4] & CR4_PAE_MASK) {
+#ifdef TARGET_X86_64
+        if (env->hflags & HF_LMA_MASK) {
+            target_phys_addr_t pml4e_addr;
+
+            pml4e_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
+            walk_pml4e(list, pml4e_addr, env->a20_mask);
+        } else
+#endif
+        {
+            target_phys_addr_t pdpe_addr;
+
+            pdpe_addr = (env->cr[3] & ~0x1f) & env->a20_mask;
+            walk_pdpe2(list, pdpe_addr, env->a20_mask);
+        }
+    } else {
+        target_phys_addr_t pde_addr;
+        bool pse;
+
+        pde_addr = (env->cr[3] & ~0xfff) & env->a20_mask;
+        pse = !!(env->cr[4] & CR4_PSE_MASK);
+        walk_pde2(list, pde_addr, env->a20_mask, pse);
+    }
+
+    return 0;
+}
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 04/29] Add API to check whether paging mode is enabled
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (2 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 03/29] implement cpu_get_memory_mapping() Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 05/29] Add API to get memory mapping Luiz Capitulino
                   ` (25 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

This API will be used in the following patch.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpu-all.h                         | 6 ++++++
 target-i386/arch_memory_mapping.c | 7 ++++++-
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/cpu-all.h b/cpu-all.h
index 2688bac..76439b4 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -527,12 +527,18 @@ int cpu_memory_rw_debug(CPUArchState *env, target_ulong addr,
 
 #if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
 int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env);
+bool cpu_paging_enabled(CPUArchState *env);
 #else
 static inline int cpu_get_memory_mapping(MemoryMappingList *list,
                                          CPUArchState *env)
 {
     return -1;
 }
+
+static inline bool cpu_paging_enabled(CPUArchState *env)
+{
+    return true;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_memory_mapping.c b/target-i386/arch_memory_mapping.c
index dd64bec..bd50e11 100644
--- a/target-i386/arch_memory_mapping.c
+++ b/target-i386/arch_memory_mapping.c
@@ -233,7 +233,7 @@ static void walk_pml4e(MemoryMappingList *list,
 
 int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
 {
-    if (!(env->cr[0] & CR0_PG_MASK)) {
+    if (!cpu_paging_enabled(env)) {
         /* paging is disabled */
         return 0;
     }
@@ -264,3 +264,8 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUArchState *env)
 
     return 0;
 }
+
+bool cpu_paging_enabled(CPUArchState *env)
+{
+    return env->cr[0] & CR0_PG_MASK;
+}
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 05/29] Add API to get memory mapping
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (3 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 04/29] Add API to check whether paging mode is enabled Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 06/29] Add API to get memory mapping without do paging Luiz Capitulino
                   ` (24 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

Add API to get all virtual address and physical address mapping.
If the guest doesn't use paging, the virtual address is equal to the phyical
address. The virtual address and physical address mapping is for gdb's user, and
it does not include the memory that is not referenced by the page table. So if
you want to use crash to anaylze the vmcore, please do not specify -p option.
the reason why the -p option is not default explicitly: guest machine in a
catastrophic state can have corrupted memory, which we cannot trust.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 memory_mapping.c | 47 +++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h | 15 +++++++++++++++
 2 files changed, 62 insertions(+)

diff --git a/memory_mapping.c b/memory_mapping.c
index 718f271..627397a 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -164,3 +164,50 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+
+static CPUArchState *find_paging_enabled_cpu(CPUArchState *start_cpu)
+{
+    CPUArchState *env;
+
+    for (env = start_cpu; env != NULL; env = env->next_cpu) {
+        if (cpu_paging_enabled(env)) {
+            return env;
+        }
+    }
+
+    return NULL;
+}
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUArchState *env, *first_paging_enabled_cpu;
+    RAMBlock *block;
+    ram_addr_t offset, length;
+    int ret;
+
+    first_paging_enabled_cpu = find_paging_enabled_cpu(first_cpu);
+    if (first_paging_enabled_cpu) {
+        for (env = first_paging_enabled_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+        return 0;
+    }
+
+    /*
+     * If the guest doesn't use paging, the virtual address is equal to physical
+     * address.
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        offset = block->offset;
+        length = block->length;
+        create_new_memory_mapping(list, offset, offset, length);
+    }
+
+    return 0;
+}
+#endif
diff --git a/memory_mapping.h b/memory_mapping.h
index e486d10..7f3c256 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -45,6 +45,21 @@ void memory_mapping_list_free(MemoryMappingList *list);
 
 void memory_mapping_list_init(MemoryMappingList *list);
 
+/*
+ * Return value:
+ *    0: success
+ *   -1: failed
+ *   -2: unsupported
+ */
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+#else
+static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    return -2;
+}
+#endif
+
 #else
 
 /* We use MemoryMappingList* in cpu-all.h */
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 06/29] Add API to get memory mapping without do paging
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (4 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 05/29] Add API to get memory mapping Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 07/29] target-i386: Add API to write elf notes to core file Luiz Capitulino
                   ` (23 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

crash does not need the virtual address and physical address mapping, and the
mapping does not include the memory that is not referenced by the page table.
crash does not use the virtual address, so we can create the mapping for all
physical memory(virtual address is always 0). This patch provides a API to do
this thing, and it will be used in the following patch.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 memory_mapping.c | 9 +++++++++
 memory_mapping.h | 3 +++
 2 files changed, 12 insertions(+)

diff --git a/memory_mapping.c b/memory_mapping.c
index 627397a..adb1595 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -211,3 +211,12 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)
     return 0;
 }
 #endif
+
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
+{
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        create_new_memory_mapping(list, block->offset, 0, block->length);
+    }
+}
diff --git a/memory_mapping.h b/memory_mapping.h
index 7f3c256..190de12 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -60,6 +60,9 @@ static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
 }
 #endif
 
+/* get guest's memory mapping without do paging(virtual address is 0). */
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
+
 #else
 
 /* We use MemoryMappingList* in cpu-all.h */
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 07/29] target-i386: Add API to write elf notes to core file
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (5 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 06/29] Add API to get memory mapping without do paging Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 08/29] target-i386: Add API to write cpu status " Luiz Capitulino
                   ` (22 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

The core file contains register's value. These APIs write registers to
core file, and them will be called in the following patch.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile.target         |   1 +
 configure               |   4 +
 cpu-all.h               |  22 +++++
 target-i386/arch_dump.c | 233 ++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 260 insertions(+)
 create mode 100644 target-i386/arch_dump.c

diff --git a/Makefile.target b/Makefile.target
index 18ffaef..cf05831 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -194,6 +194,7 @@ obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o cputlb.o
 obj-y += memory_mapping.o
 obj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
diff --git a/configure b/configure
index 20608c5..76dd57f 100755
--- a/configure
+++ b/configure
@@ -3748,6 +3748,10 @@ if test "$target_softmmu" = "yes" ; then
   if test "$smartcard_nss" = "yes" ; then
     echo "subdir-$target: subdir-libcacard" >> $config_host_mak
   fi
+  case "$target_arch2" in
+    i386|x86_64)
+      echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
+  esac
 fi
 if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=y" >> $config_target_mak
diff --git a/cpu-all.h b/cpu-all.h
index 76439b4..a71e887 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -541,4 +541,26 @@ static inline bool cpu_paging_enabled(CPUArchState *env)
 }
 #endif
 
+typedef int (*write_core_dump_function)(void *buf, size_t size, void *opaque);
+#if defined(CONFIG_HAVE_CORE_DUMP)
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque);
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque);
+#else
+static inline int cpu_write_elf64_note(write_core_dump_function f,
+                                       CPUArchState *env, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+
+static inline int cpu_write_elf32_note(write_core_dump_function f,
+                                       CPUArchState *env, int cpuid,
+                                       void *opaque)
+{
+    return -1;
+}
+#endif
+
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
new file mode 100644
index 0000000..d55c2ce
--- /dev/null
+++ b/target-i386/arch_dump.c
@@ -0,0 +1,233 @@
+/*
+ * i386 memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "cpu.h"
+#include "cpu-all.h"
+#include "elf.h"
+
+#ifdef TARGET_X86_64
+typedef struct {
+    target_ulong r15, r14, r13, r12, rbp, rbx, r11, r10;
+    target_ulong r9, r8, rax, rcx, rdx, rsi, rdi, orig_rax;
+    target_ulong rip, cs, eflags;
+    target_ulong rsp, ss;
+    target_ulong fs_base, gs_base;
+    target_ulong ds, es, fs, gs;
+} x86_64_user_regs_struct;
+
+typedef struct {
+    char pad1[32];
+    uint32_t pid;
+    char pad2[76];
+    x86_64_user_regs_struct regs;
+    char pad3[8];
+} x86_64_elf_prstatus;
+
+static int x86_64_write_elf64_note(write_core_dump_function f,
+                                   CPUArchState *env, int id,
+                                   void *opaque)
+{
+    x86_64_user_regs_struct regs;
+    Elf64_Nhdr *note;
+    char *buf;
+    int descsz, note_size, name_size = 5;
+    const char *name = "CORE";
+    int ret;
+
+    regs.r15 = env->regs[15];
+    regs.r14 = env->regs[14];
+    regs.r13 = env->regs[13];
+    regs.r12 = env->regs[12];
+    regs.r11 = env->regs[11];
+    regs.r10 = env->regs[10];
+    regs.r9  = env->regs[9];
+    regs.r8  = env->regs[8];
+    regs.rbp = env->regs[R_EBP];
+    regs.rsp = env->regs[R_ESP];
+    regs.rdi = env->regs[R_EDI];
+    regs.rsi = env->regs[R_ESI];
+    regs.rdx = env->regs[R_EDX];
+    regs.rcx = env->regs[R_ECX];
+    regs.rbx = env->regs[R_EBX];
+    regs.rax = env->regs[R_EAX];
+    regs.rip = env->eip;
+    regs.eflags = env->eflags;
+
+    regs.orig_rax = 0; /* FIXME */
+    regs.cs = env->segs[R_CS].selector;
+    regs.ss = env->segs[R_SS].selector;
+    regs.fs_base = env->segs[R_FS].base;
+    regs.gs_base = env->segs[R_GS].base;
+    regs.ds = env->segs[R_DS].selector;
+    regs.es = env->segs[R_ES].selector;
+    regs.fs = env->segs[R_FS].selector;
+    regs.gs = env->segs[R_GS].selector;
+
+    descsz = sizeof(x86_64_elf_prstatus);
+    note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    note->n_namesz = cpu_to_le32(name_size);
+    note->n_descsz = cpu_to_le32(descsz);
+    note->n_type = cpu_to_le32(NT_PRSTATUS);
+    buf = (char *)note;
+    buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf + 32, &id, 4); /* pr_pid */
+    buf += descsz - sizeof(x86_64_user_regs_struct)-sizeof(target_ulong);
+    memcpy(buf, &regs, sizeof(x86_64_user_regs_struct));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+#endif
+
+typedef struct {
+    uint32_t ebx, ecx, edx, esi, edi, ebp, eax;
+    unsigned short ds, __ds, es, __es;
+    unsigned short fs, __fs, gs, __gs;
+    uint32_t orig_eax, eip;
+    unsigned short cs, __cs;
+    uint32_t eflags, esp;
+    unsigned short ss, __ss;
+} x86_user_regs_struct;
+
+typedef struct {
+    char pad1[24];
+    uint32_t pid;
+    char pad2[44];
+    x86_user_regs_struct regs;
+    char pad3[4];
+} x86_elf_prstatus;
+
+static void x86_fill_elf_prstatus(x86_elf_prstatus *prstatus, CPUArchState *env,
+                                  int id)
+{
+    memset(prstatus, 0, sizeof(x86_elf_prstatus));
+    prstatus->regs.ebp = env->regs[R_EBP] & 0xffffffff;
+    prstatus->regs.esp = env->regs[R_ESP] & 0xffffffff;
+    prstatus->regs.edi = env->regs[R_EDI] & 0xffffffff;
+    prstatus->regs.esi = env->regs[R_ESI] & 0xffffffff;
+    prstatus->regs.edx = env->regs[R_EDX] & 0xffffffff;
+    prstatus->regs.ecx = env->regs[R_ECX] & 0xffffffff;
+    prstatus->regs.ebx = env->regs[R_EBX] & 0xffffffff;
+    prstatus->regs.eax = env->regs[R_EAX] & 0xffffffff;
+    prstatus->regs.eip = env->eip & 0xffffffff;
+    prstatus->regs.eflags = env->eflags & 0xffffffff;
+
+    prstatus->regs.cs = env->segs[R_CS].selector;
+    prstatus->regs.ss = env->segs[R_SS].selector;
+    prstatus->regs.ds = env->segs[R_DS].selector;
+    prstatus->regs.es = env->segs[R_ES].selector;
+    prstatus->regs.fs = env->segs[R_FS].selector;
+    prstatus->regs.gs = env->segs[R_GS].selector;
+
+    prstatus->pid = id;
+}
+
+static int x86_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                                int id, void *opaque)
+{
+    x86_elf_prstatus prstatus;
+    Elf64_Nhdr *note;
+    char *buf;
+    int descsz, note_size, name_size = 5;
+    const char *name = "CORE";
+    int ret;
+
+    x86_fill_elf_prstatus(&prstatus, env, id);
+    descsz = sizeof(x86_elf_prstatus);
+    note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    note->n_namesz = cpu_to_le32(name_size);
+    note->n_descsz = cpu_to_le32(descsz);
+    note->n_type = cpu_to_le32(NT_PRSTATUS);
+    buf = (char *)note;
+    buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf, &prstatus, sizeof(prstatus));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque)
+{
+    int ret;
+#ifdef TARGET_X86_64
+    bool lma = !!(first_cpu->hflags & HF_LMA_MASK);
+
+    if (lma) {
+        ret = x86_64_write_elf64_note(f, env, cpuid, opaque);
+    } else {
+#endif
+        ret = x86_write_elf64_note(f, env, cpuid, opaque);
+#ifdef TARGET_X86_64
+    }
+#endif
+
+    return ret;
+}
+
+int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
+                         int cpuid, void *opaque)
+{
+    x86_elf_prstatus prstatus;
+    Elf32_Nhdr *note;
+    char *buf;
+    int descsz, note_size, name_size = 5;
+    const char *name = "CORE";
+    int ret;
+
+    x86_fill_elf_prstatus(&prstatus, env, cpuid);
+    descsz = sizeof(x86_elf_prstatus);
+    note_size = ((sizeof(Elf32_Nhdr) + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    note->n_namesz = cpu_to_le32(name_size);
+    note->n_descsz = cpu_to_le32(descsz);
+    note->n_type = cpu_to_le32(NT_PRSTATUS);
+    buf = (char *)note;
+    buf += ((sizeof(Elf32_Nhdr) + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf, &prstatus, sizeof(prstatus));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 08/29] target-i386: Add API to write cpu status to core file
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (6 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 07/29] target-i386: Add API to write elf notes to core file Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 09/29] target-i386: add API to get dump info Luiz Capitulino
                   ` (21 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

The core file has register's value. But it does not include all registers value.
Store the cpu status into QEMU note, and the user can get more information
from vmcore. If you change QEMUCPUState, please count up QEMUCPUSTATE_VERSION.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpu-all.h               |  18 ++++++
 target-i386/arch_dump.c | 149 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 167 insertions(+)

diff --git a/cpu-all.h b/cpu-all.h
index a71e887..a167bac 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -547,6 +547,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUArchState *env,
                          int cpuid, void *opaque);
 int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
                          int cpuid, void *opaque);
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque);
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -561,6 +565,20 @@ static inline int cpu_write_elf32_note(write_core_dump_function f,
 {
     return -1;
 }
+
+static inline int cpu_write_elf64_qemunote(write_core_dump_function f,
+                                           CPUArchState *env,
+                                           void *opaque)
+{
+    return -1;
+}
+
+static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
+                                           CPUArchState *env,
+                                           void *opaque)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index d55c2ce..ddbe20c 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -231,3 +231,152 @@ int cpu_write_elf32_note(write_core_dump_function f, CPUArchState *env,
 
     return 0;
 }
+
+/*
+ * please count up QEMUCPUSTATE_VERSION if you have changed definition of
+ * QEMUCPUState, and modify the tools using this information accordingly.
+ */
+#define QEMUCPUSTATE_VERSION (1)
+
+struct QEMUCPUSegment {
+    uint32_t selector;
+    uint32_t limit;
+    uint32_t flags;
+    uint32_t pad;
+    uint64_t base;
+};
+
+typedef struct QEMUCPUSegment QEMUCPUSegment;
+
+struct QEMUCPUState {
+    uint32_t version;
+    uint32_t size;
+    uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp;
+    uint64_t r8, r9, r10, r11, r12, r13, r14, r15;
+    uint64_t rip, rflags;
+    QEMUCPUSegment cs, ds, es, fs, gs, ss;
+    QEMUCPUSegment ldt, tr, gdt, idt;
+    uint64_t cr[5];
+};
+
+typedef struct QEMUCPUState QEMUCPUState;
+
+static void copy_segment(QEMUCPUSegment *d, SegmentCache *s)
+{
+    d->pad = 0;
+    d->selector = s->selector;
+    d->limit = s->limit;
+    d->flags = s->flags;
+    d->base = s->base;
+}
+
+static void qemu_get_cpustate(QEMUCPUState *s, CPUArchState *env)
+{
+    memset(s, 0, sizeof(QEMUCPUState));
+
+    s->version = QEMUCPUSTATE_VERSION;
+    s->size = sizeof(QEMUCPUState);
+
+    s->rax = env->regs[R_EAX];
+    s->rbx = env->regs[R_EBX];
+    s->rcx = env->regs[R_ECX];
+    s->rdx = env->regs[R_EDX];
+    s->rsi = env->regs[R_ESI];
+    s->rdi = env->regs[R_EDI];
+    s->rsp = env->regs[R_ESP];
+    s->rbp = env->regs[R_EBP];
+#ifdef TARGET_X86_64
+    s->r8  = env->regs[8];
+    s->r9  = env->regs[9];
+    s->r10 = env->regs[10];
+    s->r11 = env->regs[11];
+    s->r12 = env->regs[12];
+    s->r13 = env->regs[13];
+    s->r14 = env->regs[14];
+    s->r15 = env->regs[15];
+#endif
+    s->rip = env->eip;
+    s->rflags = env->eflags;
+
+    copy_segment(&s->cs, &env->segs[R_CS]);
+    copy_segment(&s->ds, &env->segs[R_DS]);
+    copy_segment(&s->es, &env->segs[R_ES]);
+    copy_segment(&s->fs, &env->segs[R_FS]);
+    copy_segment(&s->gs, &env->segs[R_GS]);
+    copy_segment(&s->ss, &env->segs[R_SS]);
+    copy_segment(&s->ldt, &env->ldt);
+    copy_segment(&s->tr, &env->tr);
+    copy_segment(&s->gdt, &env->gdt);
+    copy_segment(&s->idt, &env->idt);
+
+    s->cr[0] = env->cr[0];
+    s->cr[1] = env->cr[1];
+    s->cr[2] = env->cr[2];
+    s->cr[3] = env->cr[3];
+    s->cr[4] = env->cr[4];
+}
+
+static inline int cpu_write_qemu_note(write_core_dump_function f,
+                                      CPUArchState *env,
+                                      void *opaque,
+                                      int type)
+{
+    QEMUCPUState state;
+    Elf64_Nhdr *note64;
+    Elf32_Nhdr *note32;
+    void *note;
+    char *buf;
+    int descsz, note_size, name_size = 5, note_head_size;
+    const char *name = "QEMU";
+    int ret;
+
+    qemu_get_cpustate(&state, env);
+
+    descsz = sizeof(state);
+    if (type == 0) {
+        note_head_size = sizeof(Elf32_Nhdr);
+    } else {
+        note_head_size = sizeof(Elf64_Nhdr);
+    }
+    note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+                (descsz + 3) / 4) * 4;
+    note = g_malloc(note_size);
+
+    memset(note, 0, note_size);
+    if (type == 0) {
+        note32 = note;
+        note32->n_namesz = cpu_to_le32(name_size);
+        note32->n_descsz = cpu_to_le32(descsz);
+        note32->n_type = 0;
+    } else {
+        note64 = note;
+        note64->n_namesz = cpu_to_le32(name_size);
+        note64->n_descsz = cpu_to_le32(descsz);
+        note64->n_type = 0;
+    }
+    buf = note;
+    buf += ((note_head_size + 3) / 4) * 4;
+    memcpy(buf, name, name_size);
+    buf += ((name_size + 3) / 4) * 4;
+    memcpy(buf, &state, sizeof(state));
+
+    ret = f(note, note_size, opaque);
+    g_free(note);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque)
+{
+    return cpu_write_qemu_note(f, env, opaque, 1);
+}
+
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
+                             void *opaque)
+{
+    return cpu_write_qemu_note(f, env, opaque, 0);
+}
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 09/29] target-i386: add API to get dump info
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (7 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 08/29] target-i386: Add API to write cpu status " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 10/29] target-i386: Add API to get note's size Luiz Capitulino
                   ` (20 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

Dump info contains: endian, class and architecture. The next
patch will use these information to create vmcore. Note: on
x86 box, the  class is ELFCLASS64 if the memory is larger than 4G.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpu-all.h               |  7 +++++++
 dump.h                  | 23 +++++++++++++++++++++++
 target-i386/arch_dump.c | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+)
 create mode 100644 dump.h

diff --git a/cpu-all.h b/cpu-all.h
index a167bac..7e07c91 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -23,6 +23,7 @@
 #include "qemu-tls.h"
 #include "cpu-common.h"
 #include "memory_mapping.h"
+#include "dump.h"
 
 /* some important defines:
  *
@@ -551,6 +552,7 @@ int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
 int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
+int cpu_get_dump_info(ArchDumpInfo *info);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -579,6 +581,11 @@ static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
 {
     return -1;
 }
+
+static inline int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/dump.h b/dump.h
new file mode 100644
index 0000000..28340cf
--- /dev/null
+++ b/dump.h
@@ -0,0 +1,23 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef DUMP_H
+#define DUMP_H
+
+typedef struct ArchDumpInfo {
+    int d_machine;  /* Architecture */
+    int d_endian;   /* ELFDATA2LSB or ELFDATA2MSB */
+    int d_class;    /* ELFCLASS32 or ELFCLASS64 */
+} ArchDumpInfo;
+
+#endif
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index ddbe20c..e378579 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -13,6 +13,7 @@
 
 #include "cpu.h"
 #include "cpu-all.h"
+#include "dump.h"
 #include "elf.h"
 
 #ifdef TARGET_X86_64
@@ -380,3 +381,36 @@ int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
 {
     return cpu_write_qemu_note(f, env, opaque, 0);
 }
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    bool lma = false;
+    RAMBlock *block;
+
+#ifdef TARGET_X86_64
+    lma = !!(first_cpu->hflags & HF_LMA_MASK);
+#endif
+
+    if (lma) {
+        info->d_machine = EM_X86_64;
+    } else {
+        info->d_machine = EM_386;
+    }
+    info->d_endian = ELFDATA2LSB;
+
+    if (lma) {
+        info->d_class = ELFCLASS64;
+    } else {
+        info->d_class = ELFCLASS32;
+
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            if (block->offset + block->length > UINT_MAX) {
+                /* The memory size is greater than 4G */
+                info->d_class = ELFCLASS64;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 10/29] target-i386: Add API to get note's size
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (8 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 09/29] target-i386: add API to get dump info Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 11/29] make gdb_id() generally avialable and rename it to cpu_index() Luiz Capitulino
                   ` (19 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

We should know where the note and memory is stored before writing
them to vmcore. If we know this, we can avoid using lseek() when
creating vmcore.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 cpu-all.h               |  6 ++++++
 target-i386/arch_dump.c | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/cpu-all.h b/cpu-all.h
index 7e07c91..2b77f66 100644
--- a/cpu-all.h
+++ b/cpu-all.h
@@ -553,6 +553,7 @@ int cpu_write_elf64_qemunote(write_core_dump_function f, CPUArchState *env,
 int cpu_write_elf32_qemunote(write_core_dump_function f, CPUArchState *env,
                              void *opaque);
 int cpu_get_dump_info(ArchDumpInfo *info);
+size_t cpu_get_note_size(int class, int machine, int nr_cpus);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUArchState *env, int cpuid,
@@ -586,6 +587,11 @@ static inline int cpu_get_dump_info(ArchDumpInfo *info)
 {
     return -1;
 }
+
+static inline int cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
diff --git a/target-i386/arch_dump.c b/target-i386/arch_dump.c
index e378579..135d855 100644
--- a/target-i386/arch_dump.c
+++ b/target-i386/arch_dump.c
@@ -414,3 +414,36 @@ int cpu_get_dump_info(ArchDumpInfo *info)
 
     return 0;
 }
+
+size_t cpu_get_note_size(int class, int machine, int nr_cpus)
+{
+    int name_size = 5; /* "CORE" or "QEMU" */
+    size_t elf_note_size = 0;
+    size_t qemu_note_size = 0;
+    int elf_desc_size = 0;
+    int qemu_desc_size = 0;
+    int note_head_size;
+
+    if (class == ELFCLASS32) {
+        note_head_size = sizeof(Elf32_Nhdr);
+    } else {
+        note_head_size = sizeof(Elf64_Nhdr);
+    }
+
+    if (machine == EM_386) {
+        elf_desc_size = sizeof(x86_elf_prstatus);
+    }
+#ifdef TARGET_X86_64
+    else {
+        elf_desc_size = sizeof(x86_64_elf_prstatus);
+    }
+#endif
+    qemu_desc_size = sizeof(QEMUCPUState);
+
+    elf_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+                     (elf_desc_size + 3) / 4) * 4;
+    qemu_note_size = ((note_head_size + 3) / 4 + (name_size + 3) / 4 +
+                      (qemu_desc_size + 3) / 4) * 4;
+
+    return (elf_note_size + qemu_note_size) * nr_cpus;
+}
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 11/29] make gdb_id() generally avialable and rename it to cpu_index()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (9 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 10/29] target-i386: Add API to get note's size Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 12/29] introduce a new monitor command 'dump-guest-memory' to dump guest's memory Luiz Capitulino
                   ` (18 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

The following patch also needs this API, so make it generally avialable.
The function gdb_id() will not be used in gdbstub.c now, so its name is
not suitable, and rename it to cpu_index()

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 gdbstub.c | 19 +++++--------------
 gdbstub.h |  9 +++++++++
 2 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/gdbstub.c b/gdbstub.c
index 6a77a66..08cf864 100644
--- a/gdbstub.c
+++ b/gdbstub.c
@@ -1937,21 +1937,12 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 #endif
 }
 
-static inline int gdb_id(CPUArchState *env)
-{
-#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
-    return env->host_tid;
-#else
-    return env->cpu_index + 1;
-#endif
-}
-
 static CPUArchState *find_cpu(uint32_t thread_id)
 {
     CPUArchState *env;
 
     for (env = first_cpu; env != NULL; env = env->next_cpu) {
-        if (gdb_id(env) == thread_id) {
+        if (cpu_index(env) == thread_id) {
             return env;
         }
     }
@@ -1979,7 +1970,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
     case '?':
         /* TODO: Make this return the correct value for user-mode.  */
         snprintf(buf, sizeof(buf), "T%02xthread:%02x;", GDB_SIGNAL_TRAP,
-                 gdb_id(s->c_cpu));
+                 cpu_index(s->c_cpu));
         put_packet(s, buf);
         /* Remove all the breakpoints when this query is issued,
          * because gdb is doing and initial connect and the state
@@ -2274,7 +2265,7 @@ static int gdb_handle_packet(GDBState *s, const char *line_buf)
         } else if (strcmp(p,"sThreadInfo") == 0) {
         report_cpuinfo:
             if (s->query_cpu) {
-                snprintf(buf, sizeof(buf), "m%x", gdb_id(s->query_cpu));
+                snprintf(buf, sizeof(buf), "m%x", cpu_index(s->query_cpu));
                 put_packet(s, buf);
                 s->query_cpu = s->query_cpu->next_cpu;
             } else
@@ -2422,7 +2413,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
             }
             snprintf(buf, sizeof(buf),
                      "T%02xthread:%02x;%swatch:" TARGET_FMT_lx ";",
-                     GDB_SIGNAL_TRAP, gdb_id(env), type,
+                     GDB_SIGNAL_TRAP, cpu_index(env), type,
                      env->watchpoint_hit->vaddr);
             env->watchpoint_hit = NULL;
             goto send_packet;
@@ -2455,7 +2446,7 @@ static void gdb_vm_state_change(void *opaque, int running, RunState state)
         ret = GDB_SIGNAL_UNKNOWN;
         break;
     }
-    snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, gdb_id(env));
+    snprintf(buf, sizeof(buf), "T%02xthread:%02x;", ret, cpu_index(env));
 
 send_packet:
     put_packet(s, buf);
diff --git a/gdbstub.h b/gdbstub.h
index b44e275..668de66 100644
--- a/gdbstub.h
+++ b/gdbstub.h
@@ -30,6 +30,15 @@ void gdb_register_coprocessor(CPUArchState *env,
                               gdb_reg_cb get_reg, gdb_reg_cb set_reg,
                               int num_regs, const char *xml, int g_pos);
 
+static inline int cpu_index(CPUArchState *env)
+{
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
+    return env->host_tid;
+#else
+    return env->cpu_index + 1;
+#endif
+}
+
 #endif
 
 #ifdef CONFIG_USER_ONLY
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 12/29] introduce a new monitor command 'dump-guest-memory' to dump guest's memory
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (10 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 11/29] make gdb_id() generally avialable and rename it to cpu_index() Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 13/29] qemu-option: qemu_opts_create(): use error_set() Luiz Capitulino
                   ` (17 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: Wen Congyang <wency@cn.fujitsu.com>

The command's usage:
   dump-guest-memory [-p] protocol [begin] [length]
The supported protocol can be file or fd:
1. file: the protocol starts with "file:", and the following string is
   the file's path.
2. fd: the protocol starts with "fd:", and the following string is the
   fd's name.

Note:
  1. If you want to use gdb to process the core, please specify -p option.
     The reason why the -p option is not default is:
       a. guest machine in a catastrophic state can have corrupted memory,
          which we cannot trust.
       b. The guest machine can be in read-mode even if paging is enabled.
          For example: the guest machine uses ACPI to sleep, and ACPI sleep
          state goes in real-mode.
  2. If you don't want to dump all guest's memory, please specify the start
     physical address and the length.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 Makefile.target  |   2 +
 dump.c           | 883 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 elf.h            |   5 +
 hmp-commands.hx  |  28 ++
 hmp.c            |  22 ++
 hmp.h            |   1 +
 memory_mapping.c |  27 ++
 memory_mapping.h |   3 +
 qapi-schema.json |  43 +++
 qmp-commands.hx  |  36 +++
 10 files changed, 1050 insertions(+)
 create mode 100644 dump.c

diff --git a/Makefile.target b/Makefile.target
index cf05831..c94abfd 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -405,6 +405,8 @@ obj-y += $(addprefix ../, $(trace-obj-y))
 
 endif # CONFIG_SOFTMMU
 
+obj-y += dump.o
+
 ifndef CONFIG_LINUX_USER
 ifndef CONFIG_BSD_USER
 # libcacard needs qemu-thread support, and besides is only needed by devices
diff --git a/dump.c b/dump.c
new file mode 100644
index 0000000..0ca14f8
--- /dev/null
+++ b/dump.c
@@ -0,0 +1,883 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <wency@cn.fujitsu.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#include "qemu-common.h"
+#include <unistd.h>
+#include "elf.h"
+#include <sys/procfs.h>
+#include <glib.h>
+#include "cpu.h"
+#include "cpu-all.h"
+#include "targphys.h"
+#include "monitor.h"
+#include "kvm.h"
+#include "dump.h"
+#include "sysemu.h"
+#include "bswap.h"
+#include "memory_mapping.h"
+#include "error.h"
+#include "qmp-commands.h"
+#include "gdbstub.h"
+
+#if defined(CONFIG_HAVE_CORE_DUMP)
+static uint16_t cpu_convert_to_target16(uint16_t val, int endian)
+{
+    if (endian == ELFDATA2LSB) {
+        val = cpu_to_le16(val);
+    } else {
+        val = cpu_to_be16(val);
+    }
+
+    return val;
+}
+
+static uint32_t cpu_convert_to_target32(uint32_t val, int endian)
+{
+    if (endian == ELFDATA2LSB) {
+        val = cpu_to_le32(val);
+    } else {
+        val = cpu_to_be32(val);
+    }
+
+    return val;
+}
+
+static uint64_t cpu_convert_to_target64(uint64_t val, int endian)
+{
+    if (endian == ELFDATA2LSB) {
+        val = cpu_to_le64(val);
+    } else {
+        val = cpu_to_be64(val);
+    }
+
+    return val;
+}
+
+typedef struct DumpState {
+    ArchDumpInfo dump_info;
+    MemoryMappingList list;
+    uint16_t phdr_num;
+    uint32_t sh_info;
+    bool have_section;
+    bool resume;
+    size_t note_size;
+    target_phys_addr_t memory_offset;
+    int fd;
+
+    RAMBlock *block;
+    ram_addr_t start;
+    bool has_filter;
+    int64_t begin;
+    int64_t length;
+    Error **errp;
+} DumpState;
+
+static int dump_cleanup(DumpState *s)
+{
+    int ret = 0;
+
+    memory_mapping_list_free(&s->list);
+    if (s->fd != -1) {
+        close(s->fd);
+    }
+    if (s->resume) {
+        vm_start();
+    }
+
+    return ret;
+}
+
+static void dump_error(DumpState *s, const char *reason)
+{
+    dump_cleanup(s);
+}
+
+static int fd_write_vmcore(void *buf, size_t size, void *opaque)
+{
+    DumpState *s = opaque;
+    int fd = s->fd;
+    size_t writen_size;
+
+    /* The fd may be passed from user, and it can be non-blocked */
+    while (size) {
+        writen_size = qemu_write_full(fd, buf, size);
+        if (writen_size != size && errno != EAGAIN) {
+            return -1;
+        }
+
+        buf += writen_size;
+        size -= writen_size;
+    }
+
+    return 0;
+}
+
+static int write_elf64_header(DumpState *s)
+{
+    Elf64_Ehdr elf_header;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&elf_header, 0, sizeof(Elf64_Ehdr));
+    memcpy(&elf_header, ELFMAG, SELFMAG);
+    elf_header.e_ident[EI_CLASS] = ELFCLASS64;
+    elf_header.e_ident[EI_DATA] = s->dump_info.d_endian;
+    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
+    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
+                                                   endian);
+    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
+    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
+    elf_header.e_phoff = cpu_convert_to_target64(sizeof(Elf64_Ehdr), endian);
+    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf64_Phdr),
+                                                     endian);
+    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
+    if (s->have_section) {
+        uint64_t shoff = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * s->sh_info;
+
+        elf_header.e_shoff = cpu_convert_to_target64(shoff, endian);
+        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf64_Shdr),
+                                                         endian);
+        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
+    }
+
+    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write elf header.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf32_header(DumpState *s)
+{
+    Elf32_Ehdr elf_header;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&elf_header, 0, sizeof(Elf32_Ehdr));
+    memcpy(&elf_header, ELFMAG, SELFMAG);
+    elf_header.e_ident[EI_CLASS] = ELFCLASS32;
+    elf_header.e_ident[EI_DATA] = endian;
+    elf_header.e_ident[EI_VERSION] = EV_CURRENT;
+    elf_header.e_type = cpu_convert_to_target16(ET_CORE, endian);
+    elf_header.e_machine = cpu_convert_to_target16(s->dump_info.d_machine,
+                                                   endian);
+    elf_header.e_version = cpu_convert_to_target32(EV_CURRENT, endian);
+    elf_header.e_ehsize = cpu_convert_to_target16(sizeof(elf_header), endian);
+    elf_header.e_phoff = cpu_convert_to_target32(sizeof(Elf32_Ehdr), endian);
+    elf_header.e_phentsize = cpu_convert_to_target16(sizeof(Elf32_Phdr),
+                                                     endian);
+    elf_header.e_phnum = cpu_convert_to_target16(s->phdr_num, endian);
+    if (s->have_section) {
+        uint32_t shoff = sizeof(Elf32_Ehdr) + sizeof(Elf32_Phdr) * s->sh_info;
+
+        elf_header.e_shoff = cpu_convert_to_target32(shoff, endian);
+        elf_header.e_shentsize = cpu_convert_to_target16(sizeof(Elf32_Shdr),
+                                                         endian);
+        elf_header.e_shnum = cpu_convert_to_target16(1, endian);
+    }
+
+    ret = fd_write_vmcore(&elf_header, sizeof(elf_header), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write elf header.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping,
+                            int phdr_index, target_phys_addr_t offset)
+{
+    Elf64_Phdr phdr;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&phdr, 0, sizeof(Elf64_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
+    phdr.p_offset = cpu_convert_to_target64(offset, endian);
+    phdr.p_paddr = cpu_convert_to_target64(memory_mapping->phys_addr, endian);
+    if (offset == -1) {
+        /* When the memory is not stored into vmcore, offset will be -1 */
+        phdr.p_filesz = 0;
+    } else {
+        phdr.p_filesz = cpu_convert_to_target64(memory_mapping->length, endian);
+    }
+    phdr.p_memsz = cpu_convert_to_target64(memory_mapping->length, endian);
+    phdr.p_vaddr = cpu_convert_to_target64(memory_mapping->virt_addr, endian);
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,
+                            int phdr_index, target_phys_addr_t offset)
+{
+    Elf32_Phdr phdr;
+    int ret;
+    int endian = s->dump_info.d_endian;
+
+    memset(&phdr, 0, sizeof(Elf32_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_LOAD, endian);
+    phdr.p_offset = cpu_convert_to_target32(offset, endian);
+    phdr.p_paddr = cpu_convert_to_target32(memory_mapping->phys_addr, endian);
+    if (offset == -1) {
+        /* When the memory is not stored into vmcore, offset will be -1 */
+        phdr.p_filesz = 0;
+    } else {
+        phdr.p_filesz = cpu_convert_to_target32(memory_mapping->length, endian);
+    }
+    phdr.p_memsz = cpu_convert_to_target32(memory_mapping->length, endian);
+    phdr.p_vaddr = cpu_convert_to_target32(memory_mapping->virt_addr, endian);
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf64_note(DumpState *s)
+{
+    Elf64_Phdr phdr;
+    int endian = s->dump_info.d_endian;
+    target_phys_addr_t begin = s->memory_offset - s->note_size;
+    int ret;
+
+    memset(&phdr, 0, sizeof(Elf64_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
+    phdr.p_offset = cpu_convert_to_target64(begin, endian);
+    phdr.p_paddr = 0;
+    phdr.p_filesz = cpu_convert_to_target64(s->note_size, endian);
+    phdr.p_memsz = cpu_convert_to_target64(s->note_size, endian);
+    phdr.p_vaddr = 0;
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf64_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf64_notes(DumpState *s)
+{
+    CPUArchState *env;
+    int ret;
+    int id;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        id = cpu_index(env);
+        ret = cpu_write_elf64_note(fd_write_vmcore, env, id, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write elf notes.\n");
+            return -1;
+        }
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        ret = cpu_write_elf64_qemunote(fd_write_vmcore, env, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write CPU status.\n");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int write_elf32_note(DumpState *s)
+{
+    target_phys_addr_t begin = s->memory_offset - s->note_size;
+    Elf32_Phdr phdr;
+    int endian = s->dump_info.d_endian;
+    int ret;
+
+    memset(&phdr, 0, sizeof(Elf32_Phdr));
+    phdr.p_type = cpu_convert_to_target32(PT_NOTE, endian);
+    phdr.p_offset = cpu_convert_to_target32(begin, endian);
+    phdr.p_paddr = 0;
+    phdr.p_filesz = cpu_convert_to_target32(s->note_size, endian);
+    phdr.p_memsz = cpu_convert_to_target32(s->note_size, endian);
+    phdr.p_vaddr = 0;
+
+    ret = fd_write_vmcore(&phdr, sizeof(Elf32_Phdr), s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write program header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_elf32_notes(DumpState *s)
+{
+    CPUArchState *env;
+    int ret;
+    int id;
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        id = cpu_index(env);
+        ret = cpu_write_elf32_note(fd_write_vmcore, env, id, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write elf notes.\n");
+            return -1;
+        }
+    }
+
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        ret = cpu_write_elf32_qemunote(fd_write_vmcore, env, s);
+        if (ret < 0) {
+            dump_error(s, "dump: failed to write CPU status.\n");
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+static int write_elf_section(DumpState *s, int type)
+{
+    Elf32_Shdr shdr32;
+    Elf64_Shdr shdr64;
+    int endian = s->dump_info.d_endian;
+    int shdr_size;
+    void *shdr;
+    int ret;
+
+    if (type == 0) {
+        shdr_size = sizeof(Elf32_Shdr);
+        memset(&shdr32, 0, shdr_size);
+        shdr32.sh_info = cpu_convert_to_target32(s->sh_info, endian);
+        shdr = &shdr32;
+    } else {
+        shdr_size = sizeof(Elf64_Shdr);
+        memset(&shdr64, 0, shdr_size);
+        shdr64.sh_info = cpu_convert_to_target32(s->sh_info, endian);
+        shdr = &shdr64;
+    }
+
+    ret = fd_write_vmcore(&shdr, shdr_size, s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to write section header table.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+static int write_data(DumpState *s, void *buf, int length)
+{
+    int ret;
+
+    ret = fd_write_vmcore(buf, length, s);
+    if (ret < 0) {
+        dump_error(s, "dump: failed to save memory.\n");
+        return -1;
+    }
+
+    return 0;
+}
+
+/* write the memroy to vmcore. 1 page per I/O. */
+static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
+                        int64_t size)
+{
+    int64_t i;
+    int ret;
+
+    for (i = 0; i < size / TARGET_PAGE_SIZE; i++) {
+        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+                         TARGET_PAGE_SIZE);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    if ((size % TARGET_PAGE_SIZE) != 0) {
+        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+                         size % TARGET_PAGE_SIZE);
+        if (ret < 0) {
+            return ret;
+        }
+    }
+
+    return 0;
+}
+
+/* get the memory's offset in the vmcore */
+static target_phys_addr_t get_offset(target_phys_addr_t phys_addr,
+                                     DumpState *s)
+{
+    RAMBlock *block;
+    target_phys_addr_t offset = s->memory_offset;
+    int64_t size_in_block, start;
+
+    if (s->has_filter) {
+        if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
+            return -1;
+        }
+    }
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (s->has_filter) {
+            if (block->offset >= s->begin + s->length ||
+                block->offset + block->length <= s->begin) {
+                /* This block is out of the range */
+                continue;
+            }
+
+            if (s->begin <= block->offset) {
+                start = block->offset;
+            } else {
+                start = s->begin;
+            }
+
+            size_in_block = block->length - (start - block->offset);
+            if (s->begin + s->length < block->offset + block->length) {
+                size_in_block -= block->offset + block->length -
+                                 (s->begin + s->length);
+            }
+        } else {
+            start = block->offset;
+            size_in_block = block->length;
+        }
+
+        if (phys_addr >= start && phys_addr < start + size_in_block) {
+            return phys_addr - start + offset;
+        }
+
+        offset += size_in_block;
+    }
+
+    return -1;
+}
+
+static int write_elf_loads(DumpState *s)
+{
+    target_phys_addr_t offset;
+    MemoryMapping *memory_mapping;
+    uint32_t phdr_index = 1;
+    int ret;
+    uint32_t max_index;
+
+    if (s->have_section) {
+        max_index = s->sh_info;
+    } else {
+        max_index = s->phdr_num;
+    }
+
+    QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
+        offset = get_offset(memory_mapping->phys_addr, s);
+        if (s->dump_info.d_class == ELFCLASS64) {
+            ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
+        } else {
+            ret = write_elf32_load(s, memory_mapping, phdr_index++, offset);
+        }
+
+        if (ret < 0) {
+            return -1;
+        }
+
+        if (phdr_index >= max_index) {
+            break;
+        }
+    }
+
+    return 0;
+}
+
+/* write elf header, PT_NOTE and elf note to vmcore. */
+static int dump_begin(DumpState *s)
+{
+    int ret;
+
+    /*
+     * the vmcore's format is:
+     *   --------------
+     *   |  elf header |
+     *   --------------
+     *   |  PT_NOTE    |
+     *   --------------
+     *   |  PT_LOAD    |
+     *   --------------
+     *   |  ......     |
+     *   --------------
+     *   |  PT_LOAD    |
+     *   --------------
+     *   |  sec_hdr    |
+     *   --------------
+     *   |  elf note   |
+     *   --------------
+     *   |  memory     |
+     *   --------------
+     *
+     * we only know where the memory is saved after we write elf note into
+     * vmcore.
+     */
+
+    /* write elf header to vmcore */
+    if (s->dump_info.d_class == ELFCLASS64) {
+        ret = write_elf64_header(s);
+    } else {
+        ret = write_elf32_header(s);
+    }
+    if (ret < 0) {
+        return -1;
+    }
+
+    if (s->dump_info.d_class == ELFCLASS64) {
+        /* write PT_NOTE to vmcore */
+        if (write_elf64_note(s) < 0) {
+            return -1;
+        }
+
+        /* write all PT_LOAD to vmcore */
+        if (write_elf_loads(s) < 0) {
+            return -1;
+        }
+
+        /* write section to vmcore */
+        if (s->have_section) {
+            if (write_elf_section(s, 1) < 0) {
+                return -1;
+            }
+        }
+
+        /* write notes to vmcore */
+        if (write_elf64_notes(s) < 0) {
+            return -1;
+        }
+
+    } else {
+        /* write PT_NOTE to vmcore */
+        if (write_elf32_note(s) < 0) {
+            return -1;
+        }
+
+        /* write all PT_LOAD to vmcore */
+        if (write_elf_loads(s) < 0) {
+            return -1;
+        }
+
+        /* write section to vmcore */
+        if (s->have_section) {
+            if (write_elf_section(s, 0) < 0) {
+                return -1;
+            }
+        }
+
+        /* write notes to vmcore */
+        if (write_elf32_notes(s) < 0) {
+            return -1;
+        }
+    }
+
+    return 0;
+}
+
+/* write PT_LOAD to vmcore */
+static int dump_completed(DumpState *s)
+{
+    dump_cleanup(s);
+    return 0;
+}
+
+static int get_next_block(DumpState *s, RAMBlock *block)
+{
+    while (1) {
+        block = QLIST_NEXT(block, next);
+        if (!block) {
+            /* no more block */
+            return 1;
+        }
+
+        s->start = 0;
+        s->block = block;
+        if (s->has_filter) {
+            if (block->offset >= s->begin + s->length ||
+                block->offset + block->length <= s->begin) {
+                /* This block is out of the range */
+                continue;
+            }
+
+            if (s->begin > block->offset) {
+                s->start = s->begin - block->offset;
+            }
+        }
+
+        return 0;
+    }
+}
+
+/* write all memory to vmcore */
+static int dump_iterate(DumpState *s)
+{
+    RAMBlock *block;
+    int64_t size;
+    int ret;
+
+    while (1) {
+        block = s->block;
+
+        size = block->length;
+        if (s->has_filter) {
+            size -= s->start;
+            if (s->begin + s->length < block->offset + block->length) {
+                size -= block->offset + block->length - (s->begin + s->length);
+            }
+        }
+        ret = write_memory(s, block, s->start, size);
+        if (ret == -1) {
+            return ret;
+        }
+
+        ret = get_next_block(s, block);
+        if (ret == 1) {
+            dump_completed(s);
+            return 0;
+        }
+    }
+}
+
+static int create_vmcore(DumpState *s)
+{
+    int ret;
+
+    ret = dump_begin(s);
+    if (ret < 0) {
+        return -1;
+    }
+
+    ret = dump_iterate(s);
+    if (ret < 0) {
+        return -1;
+    }
+
+    return 0;
+}
+
+static ram_addr_t get_start_block(DumpState *s)
+{
+    RAMBlock *block;
+
+    if (!s->has_filter) {
+        s->block = QLIST_FIRST(&ram_list.blocks);
+        return 0;
+    }
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (block->offset >= s->begin + s->length ||
+            block->offset + block->length <= s->begin) {
+            /* This block is out of the range */
+            continue;
+        }
+
+        s->block = block;
+        if (s->begin > block->offset) {
+            s->start = s->begin - block->offset;
+        } else {
+            s->start = 0;
+        }
+        return s->start;
+    }
+
+    return -1;
+}
+
+static int dump_init(DumpState *s, int fd, bool paging, bool has_filter,
+                     int64_t begin, int64_t length, Error **errp)
+{
+    CPUArchState *env;
+    int nr_cpus;
+    int ret;
+
+    if (runstate_is_running()) {
+        vm_stop(RUN_STATE_SAVE_VM);
+        s->resume = true;
+    } else {
+        s->resume = false;
+    }
+
+    s->errp = errp;
+    s->fd = fd;
+    s->has_filter = has_filter;
+    s->begin = begin;
+    s->length = length;
+    s->start = get_start_block(s);
+    if (s->start == -1) {
+        error_set(errp, QERR_INVALID_PARAMETER, "begin");
+        goto cleanup;
+    }
+
+    /*
+     * get dump info: endian, class and architecture.
+     * If the target architecture is not supported, cpu_get_dump_info() will
+     * return -1.
+     *
+     * if we use kvm, we should synchronize the register before we get dump
+     * info.
+     */
+    nr_cpus = 0;
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        cpu_synchronize_state(env);
+        nr_cpus++;
+    }
+
+    ret = cpu_get_dump_info(&s->dump_info);
+    if (ret < 0) {
+        error_set(errp, QERR_UNSUPPORTED);
+        goto cleanup;
+    }
+
+    /* get memory mapping */
+    memory_mapping_list_init(&s->list);
+    if (paging) {
+        qemu_get_guest_memory_mapping(&s->list);
+    } else {
+        qemu_get_guest_simple_memory_mapping(&s->list);
+    }
+
+    if (s->has_filter) {
+        memory_mapping_filter(&s->list, s->begin, s->length);
+    }
+
+    /*
+     * calculate phdr_num
+     *
+     * the type of ehdr->e_phnum is uint16_t, so we should avoid overflow
+     */
+    s->phdr_num = 1; /* PT_NOTE */
+    if (s->list.num < UINT16_MAX - 2) {
+        s->phdr_num += s->list.num;
+        s->have_section = false;
+    } else {
+        s->have_section = true;
+        s->phdr_num = PN_XNUM;
+        s->sh_info = 1; /* PT_NOTE */
+
+        /* the type of shdr->sh_info is uint32_t, so we should avoid overflow */
+        if (s->list.num <= UINT32_MAX - 1) {
+            s->sh_info += s->list.num;
+        } else {
+            s->sh_info = UINT32_MAX;
+        }
+    }
+
+    s->note_size = cpu_get_note_size(s->dump_info.d_class,
+                                     s->dump_info.d_machine, nr_cpus);
+    if (s->dump_info.d_class == ELFCLASS64) {
+        if (s->have_section) {
+            s->memory_offset = sizeof(Elf64_Ehdr) +
+                               sizeof(Elf64_Phdr) * s->sh_info +
+                               sizeof(Elf64_Shdr) + s->note_size;
+        } else {
+            s->memory_offset = sizeof(Elf64_Ehdr) +
+                               sizeof(Elf64_Phdr) * s->phdr_num + s->note_size;
+        }
+    } else {
+        if (s->have_section) {
+            s->memory_offset = sizeof(Elf32_Ehdr) +
+                               sizeof(Elf32_Phdr) * s->sh_info +
+                               sizeof(Elf32_Shdr) + s->note_size;
+        } else {
+            s->memory_offset = sizeof(Elf32_Ehdr) +
+                               sizeof(Elf32_Phdr) * s->phdr_num + s->note_size;
+        }
+    }
+
+    return 0;
+
+cleanup:
+    if (s->resume) {
+        vm_start();
+    }
+
+    return -1;
+}
+
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+                           int64_t begin, bool has_length, int64_t length,
+                           Error **errp)
+{
+    const char *p;
+    int fd = -1;
+    DumpState *s;
+    int ret;
+
+    if (has_begin && !has_length) {
+        error_set(errp, QERR_MISSING_PARAMETER, "length");
+        return;
+    }
+    if (!has_begin && has_length) {
+        error_set(errp, QERR_MISSING_PARAMETER, "begin");
+        return;
+    }
+
+#if !defined(WIN32)
+    if (strstart(file, "fd:", &p)) {
+        fd = monitor_get_fd(cur_mon, p);
+        if (fd == -1) {
+            error_set(errp, QERR_FD_NOT_FOUND, p);
+            return;
+        }
+    }
+#endif
+
+    if  (strstart(file, "file:", &p)) {
+        fd = qemu_open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY, S_IRUSR);
+        if (fd < 0) {
+            error_set(errp, QERR_OPEN_FILE_FAILED, p);
+            return;
+        }
+    }
+
+    if (fd == -1) {
+        error_set(errp, QERR_INVALID_PARAMETER, "protocol");
+        return;
+    }
+
+    s = g_malloc(sizeof(DumpState));
+
+    ret = dump_init(s, fd, paging, has_begin, begin, length, errp);
+    if (ret < 0) {
+        g_free(s);
+        return;
+    }
+
+    if (create_vmcore(s) < 0 && !error_is_set(s->errp)) {
+        error_set(errp, QERR_IO_ERROR);
+    }
+
+    g_free(s);
+}
+
+#else
+/* we need this function in hmp.c */
+void qmp_dump_guest_memory(bool paging, const char *file, bool has_begin,
+                           int64_t begin, bool has_length, int64_t length,
+                           Error **errp)
+{
+    error_set(errp, QERR_UNSUPPORTED);
+}
+#endif
diff --git a/elf.h b/elf.h
index e1422b8..9c9acfa 100644
--- a/elf.h
+++ b/elf.h
@@ -1037,6 +1037,11 @@ typedef struct elf64_sym {
 
 #define EI_NIDENT	16
 
+/* Special value for e_phnum.  This indicates that the real number of
+   program headers is too large to fit into e_phnum.  Instead the real
+   value is in the field sh_info of section 0.  */
+#define PN_XNUM         0xffff
+
 typedef struct elf32_hdr{
   unsigned char	e_ident[EI_NIDENT];
   Elf32_Half	e_type;
diff --git a/hmp-commands.hx b/hmp-commands.hx
index 18cb415..81723c8 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -878,6 +878,34 @@ server will ask the spice/vnc client to automatically reconnect using the
 new parameters (if specified) once the vm migration finished successfully.
 ETEXI
 
+#if defined(CONFIG_HAVE_CORE_DUMP)
+    {
+        .name       = "dump-guest-memory",
+        .args_type  = "paging:-p,protocol:s,begin:i?,length:i?",
+        .params     = "[-p] protocol [begin] [length]",
+        .help       = "dump guest memory to file"
+                      "\n\t\t\t begin(optional): the starting physical address"
+                      "\n\t\t\t length(optional): the memory size, in bytes",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd = hmp_dump_guest_memory,
+    },
+
+
+STEXI
+@item dump-guest-memory [-p] @var{protocol} @var{begin} @var{length}
+@findex dump-guest-memory
+Dump guest memory to @var{protocol}. The file can be processed with crash or
+gdb.
+  protocol: destination file(started with "file:") or destination file
+            descriptor (started with "fd:")
+    paging: do paging to get guest's memory mapping
+     begin: the starting physical address. It's optional, and should be
+            specified with length together.
+    length: the memory size, in bytes. It's optional, and should be specified
+            with begin together.
+ETEXI
+#endif
+
     {
         .name       = "snapshot_blkdev",
         .args_type  = "reuse:-n,device:B,snapshot-file:s?,format:s?",
diff --git a/hmp.c b/hmp.c
index bb0952e..42ced2a 100644
--- a/hmp.c
+++ b/hmp.c
@@ -947,3 +947,25 @@ void hmp_device_del(Monitor *mon, const QDict *qdict)
     qmp_device_del(id, &err);
     hmp_handle_error(mon, &err);
 }
+
+void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+    int paging = qdict_get_try_bool(qdict, "paging", 0);
+    const char *file = qdict_get_str(qdict, "protocol");
+    bool has_begin = qdict_haskey(qdict, "begin");
+    bool has_length = qdict_haskey(qdict, "length");
+    int64_t begin = 0;
+    int64_t length = 0;
+
+    if (has_begin) {
+        begin = qdict_get_int(qdict, "begin");
+    }
+    if (has_length) {
+        length = qdict_get_int(qdict, "length");
+    }
+
+    qmp_dump_guest_memory(paging, file, has_begin, begin, has_length, length,
+                          &errp);
+    hmp_handle_error(mon, &errp);
+}
diff --git a/hmp.h b/hmp.h
index 443b812..5cf3241 100644
--- a/hmp.h
+++ b/hmp.h
@@ -61,5 +61,6 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate(Monitor *mon, const QDict *qdict);
 void hmp_device_del(Monitor *mon, const QDict *qdict);
+void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/memory_mapping.c b/memory_mapping.c
index adb1595..8810bb0 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -220,3 +220,30 @@ void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
         create_new_memory_mapping(list, block->offset, 0, block->length);
     }
 }
+
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+                           int64_t length)
+{
+    MemoryMapping *cur, *next;
+
+    QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) {
+        if (cur->phys_addr >= begin + length ||
+            cur->phys_addr + cur->length <= begin) {
+            QTAILQ_REMOVE(&list->head, cur, next);
+            list->num--;
+            continue;
+        }
+
+        if (cur->phys_addr < begin) {
+            cur->length -= begin - cur->phys_addr;
+            if (cur->virt_addr) {
+                cur->virt_addr += begin - cur->phys_addr;
+            }
+            cur->phys_addr = begin;
+        }
+
+        if (cur->phys_addr + cur->length > begin + length) {
+            cur->length -= cur->phys_addr + cur->length - begin - length;
+        }
+    }
+}
diff --git a/memory_mapping.h b/memory_mapping.h
index 190de12..a1aa64f 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -63,6 +63,9 @@ static inline int qemu_get_guest_memory_mapping(MemoryMappingList *list)
 /* get guest's memory mapping without do paging(virtual address is 0). */
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
 
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+                           int64_t length);
+
 #else
 
 /* We use MemoryMappingList* in cpu-all.h */
diff --git a/qapi-schema.json b/qapi-schema.json
index 2ca7195..dfa0e1f 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1755,3 +1755,46 @@
 # Since: 0.14.0
 ##
 { 'command': 'device_del', 'data': {'id': 'str'} }
+
+##
+# @dump-guest-memory
+#
+# Dump guest's memory to vmcore. It is a synchronous operation that can take
+# very long depending on the amount of guest memory. This command is only
+# supported only on i386 and x86_64
+#
+# @paging: if true, do paging to get guest's memory mapping. The @paging's
+# default value of @paging is false, If you want to use gdb to process the
+# core, please set @paging to true. The reason why the @paging's value is
+# false:
+#   1. guest machine in a catastrophic state can have corrupted memory,
+#      which we cannot trust.
+#   2. The guest machine can be in read-mode even if paging is enabled.
+#      For example: the guest machine uses ACPI to sleep, and ACPI sleep
+#      state goes in real-mode
+# @protocol: the filename or file descriptor of the vmcore. The supported
+# protocol can be file or fd:
+#   1. file: the protocol starts with "file:", and the following string is
+#      the file's path.
+#   2. fd: the protocol starts with "fd:", and the following string is the
+#      fd's name.
+# @begin: #optional if specified, the starting physical address.
+# @length: #optional if specified, the memory size, in bytes. If you don't
+# want to dump all guest's memory, please specify the start @begin and
+# @length
+#
+# Returns: nothing on success
+#          If @begin contains an invalid address, InvalidParameter
+#          If only one of @begin and @length is specified, MissingParameter
+#          If @protocol stats with "fd:", and the fd cannot be found, FdNotFound
+#          If @protocol starts with "file:", and the file cannot be
+#          opened, OpenFileFailed
+#          If @protocol does not start with "fd:" or "file:", InvalidParameter
+#          If an I/O error occurs while writing the file, IOError
+#          If the target does not support this command, Unsupported
+#
+# Since: 1.2
+##
+{ 'command': 'dump-guest-memory',
+  'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
+            '*length': 'int' } }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index db980fa..2aa64ad 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -604,6 +604,42 @@ Example:
 EQMP
 
     {
+        .name       = "dump-guest-memory",
+        .args_type  = "paging:b,protocol:s,begin:i?,end:i?",
+        .params     = "-p protocol [begin] [length]",
+        .help       = "dump guest memory to file",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = qmp_marshal_input_dump_guest_memory,
+    },
+
+SQMP
+dump
+
+
+Dump guest memory to file. The file can be processed with crash or gdb.
+
+Arguments:
+
+- "paging": do paging to get guest's memory mapping (json-bool)
+- "protocol": destination file(started with "file:") or destination file
+              descriptor (started with "fd:") (json-string)
+- "begin": the starting physical address. It's optional, and should be specified
+           with length together (json-int)
+- "length": the memory size, in bytes. It's optional, and should be specified
+            with begin together (json-int)
+
+Example:
+
+-> { "execute": "dump-guest-memory", "arguments": { "protocol": "fd:dump" } }
+<- { "return": {} }
+
+Notes:
+
+(1) All boolean arguments default to false
+
+EQMP
+
+    {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
         .params     = "[user|tap|socket],id=str[,prop=value][,...]",
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 13/29] qemu-option: qemu_opts_create(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (11 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 12/29] introduce a new monitor command 'dump-guest-memory' to dump guest's memory Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 14/29] qemu-option: parse_option_number(): " Luiz Capitulino
                   ` (16 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This commit converts qemu_opts_create() from qerror_report() to
error_set().

Currently, most calls to qemu_opts_create() can't fail, so most
callers don't need any changes.

The two cases where code checks for qemu_opts_create() erros are:

 1. Initialization code in vl.c. All of them print their own
    error messages directly to stderr, no need to pass the Error
    object

 2. The functions opts_parse(), qemu_opts_from_qdict() and
    qemu_chr_parse_compat() make use of the error information and
    they can be called from HMP or QMP. In this case, to allow for
    incremental conversion, we propagate the error up using
    qerror_report_err(), which keeps the QError semantics

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 blockdev.c           |  2 +-
 hw/usb/dev-storage.c |  2 +-
 hw/watchdog.c        |  2 +-
 qemu-char.c          |  8 ++++++--
 qemu-config.c        |  6 +++---
 qemu-option.c        | 37 +++++++++++++++++++++++++++----------
 qemu-option.h        |  4 +++-
 qemu-sockets.c       |  8 ++++----
 vl.c                 | 22 +++++++++++++---------
 9 files changed, 59 insertions(+), 32 deletions(-)

diff --git a/blockdev.c b/blockdev.c
index 67895b2..622ecba 100644
--- a/blockdev.c
+++ b/blockdev.c
@@ -569,7 +569,7 @@ DriveInfo *drive_init(QemuOpts *opts, int default_to_scsi)
         break;
     case IF_VIRTIO:
         /* add virtio block device */
-        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+        opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
         if (arch_type == QEMU_ARCH_S390X) {
             qemu_opt_set(opts, "driver", "virtio-blk-s390");
         } else {
diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index ae22fb1..a96c0b9 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -584,7 +584,7 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 
     /* parse -usbdevice disk: syntax into drive opts */
     snprintf(id, sizeof(id), "usb%d", nr++);
-    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0);
+    opts = qemu_opts_create(qemu_find_opts("drive"), id, 0, NULL);
 
     p1 = strchr(filename, ':');
     if (p1++) {
diff --git a/hw/watchdog.c b/hw/watchdog.c
index 4c18965..a42124d 100644
--- a/hw/watchdog.c
+++ b/hw/watchdog.c
@@ -66,7 +66,7 @@ int select_watchdog(const char *p)
     QLIST_FOREACH(model, &watchdog_list, entry) {
         if (strcasecmp(model->wdt_name, p) == 0) {
             /* add the device */
-            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
             qemu_opt_set(opts, "driver", p);
             return 0;
         }
diff --git a/qemu-char.c b/qemu-char.c
index fe1126f..0bd903f 100644
--- a/qemu-char.c
+++ b/qemu-char.c
@@ -2584,10 +2584,14 @@ QemuOpts *qemu_chr_parse_compat(const char *label, const char *filename)
     int pos;
     const char *p;
     QemuOpts *opts;
+    Error *local_err = NULL;
 
-    opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1);
-    if (NULL == opts)
+    opts = qemu_opts_create(qemu_find_opts("chardev"), label, 1, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
+    }
 
     if (strstart(filename, "mon:", &p)) {
         filename = p;
diff --git a/qemu-config.c b/qemu-config.c
index be84a03..f876646 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -709,7 +709,7 @@ int qemu_global_option(const char *str)
         return -1;
     }
 
-    opts = qemu_opts_create(&qemu_global_opts, NULL, 0);
+    opts = qemu_opts_create(&qemu_global_opts, NULL, 0, NULL);
     qemu_opt_set(opts, "driver", driver);
     qemu_opt_set(opts, "property", property);
     qemu_opt_set(opts, "value", str+offset+1);
@@ -781,7 +781,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             list = find_list(lists, group);
             if (list == NULL)
                 goto out;
-            opts = qemu_opts_create(list, id, 1);
+            opts = qemu_opts_create(list, id, 1, NULL);
             continue;
         }
         if (sscanf(line, "[%63[^]]]", group) == 1) {
@@ -789,7 +789,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
             list = find_list(lists, group);
             if (list == NULL)
                 goto out;
-            opts = qemu_opts_create(list, NULL, 0);
+            opts = qemu_opts_create(list, NULL, 0, NULL);
             continue;
         }
         if (sscanf(line, " %63s = \"%1023[^\"]\"", arg, value) == 2) {
diff --git a/qemu-option.c b/qemu-option.c
index 35cd609..9f531c8 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -30,6 +30,7 @@
 #include "qemu-error.h"
 #include "qemu-objects.h"
 #include "qemu-option.h"
+#include "error.h"
 #include "qerror.h"
 
 /*
@@ -729,20 +730,21 @@ static int id_wellformed(const char *id)
     return 1;
 }
 
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists)
+QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
+                           int fail_if_exists, Error **errp)
 {
     QemuOpts *opts = NULL;
 
     if (id) {
         if (!id_wellformed(id)) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
+            error_set(errp,QERR_INVALID_PARAMETER_VALUE, "id", "an identifier");
             error_printf_unless_qmp("Identifiers consist of letters, digits, '-', '.', '_', starting with a letter.\n");
             return NULL;
         }
         opts = qemu_opts_find(list, id);
         if (opts != NULL) {
             if (fail_if_exists && !list->merge_lists) {
-                qerror_report(QERR_DUPLICATE_ID, id, list->name);
+                error_set(errp, QERR_DUPLICATE_ID, id, list->name);
                 return NULL;
             } else {
                 return opts;
@@ -783,9 +785,12 @@ int qemu_opts_set(QemuOptsList *list, const char *id,
                   const char *name, const char *value)
 {
     QemuOpts *opts;
+    Error *local_err = NULL;
 
-    opts = qemu_opts_create(list, id, 1);
-    if (opts == NULL) {
+    opts = qemu_opts_create(list, id, 1, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
     }
     return qemu_opt_set(opts, name, value);
@@ -883,6 +888,7 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
     char value[1024], *id = NULL;
     const char *p;
     QemuOpts *opts;
+    Error *local_err = NULL;
 
     assert(!permit_abbrev || list->implied_opt_name);
     firstname = permit_abbrev ? list->implied_opt_name : NULL;
@@ -898,13 +904,18 @@ static QemuOpts *opts_parse(QemuOptsList *list, const char *params,
         if (!id && !QTAILQ_EMPTY(&list->head)) {
             opts = qemu_opts_find(list, NULL);
         } else {
-            opts = qemu_opts_create(list, id, 0);
+            opts = qemu_opts_create(list, id, 0, &local_err);
         }
     } else {
-        opts = qemu_opts_create(list, id, 1);
+        opts = qemu_opts_create(list, id, 1, &local_err);
     }
-    if (opts == NULL)
+    if (opts == NULL) {
+        if (error_is_set(&local_err)) {
+            qerror_report_err(local_err);
+            error_free(local_err);
+        }
         return NULL;
+    }
 
     if (opts_do_parse(opts, params, firstname, defaults) != 0) {
         qemu_opts_del(opts);
@@ -975,11 +986,17 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
 {
     QemuOpts *opts;
+    Error *local_err = NULL;
 
-    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1);
-    if (opts == NULL)
+    opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
+                            &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
+    }
 
+    assert(opts != NULL);
     qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
     return opts;
 }
diff --git a/qemu-option.h b/qemu-option.h
index 3ca00c3..4d5b3d3 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -28,6 +28,7 @@
 
 #include <stdint.h>
 #include "qemu-queue.h"
+#include "error.h"
 #include "qdict.h"
 
 enum QEMUOptionParType {
@@ -116,7 +117,8 @@ int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
                      int abort_on_failure);
 
 QemuOpts *qemu_opts_find(QemuOptsList *list, const char *id);
-QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id, int fail_if_exists);
+QemuOpts *qemu_opts_create(QemuOptsList *list, const char *id,
+                           int fail_if_exists, Error **errp);
 void qemu_opts_reset(QemuOptsList *list);
 void qemu_opts_loc_restore(QemuOpts *opts);
 int qemu_opts_set(QemuOptsList *list, const char *id,
diff --git a/qemu-sockets.c b/qemu-sockets.c
index 46c7619..2ae715d 100644
--- a/qemu-sockets.c
+++ b/qemu-sockets.c
@@ -461,7 +461,7 @@ int inet_listen(const char *str, char *ostr, int olen,
     char *optstr;
     int sock = -1;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
     if (inet_parse(opts, str) == 0) {
         sock = inet_listen_opts(opts, port_offset, errp);
         if (sock != -1 && ostr) {
@@ -490,7 +490,7 @@ int inet_connect(const char *str, bool block, Error **errp)
     QemuOpts *opts;
     int sock = -1;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
     if (inet_parse(opts, str) == 0) {
         if (block) {
             qemu_opt_set(opts, "block", "on");
@@ -589,7 +589,7 @@ int unix_listen(const char *str, char *ostr, int olen)
     char *path, *optstr;
     int sock, len;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
 
     optstr = strchr(str, ',');
     if (optstr) {
@@ -617,7 +617,7 @@ int unix_connect(const char *path)
     QemuOpts *opts;
     int sock;
 
-    opts = qemu_opts_create(&dummy_opts, NULL, 0);
+    opts = qemu_opts_create(&dummy_opts, NULL, 0, NULL);
     qemu_opt_set(opts, "path", path);
     sock = unix_connect_opts(opts);
     qemu_opts_del(opts);
diff --git a/vl.c b/vl.c
index 23ab3a3..1485426 100644
--- a/vl.c
+++ b/vl.c
@@ -1786,7 +1786,7 @@ static int balloon_parse(const char *arg)
                 return  -1;
         } else {
             /* create empty opts */
-            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0, NULL);
         }
         qemu_opt_set(opts, "driver", "virtio-balloon");
         return 0;
@@ -1921,7 +1921,7 @@ static void monitor_parse(const char *optarg, const char *mode)
         }
     }
 
-    opts = qemu_opts_create(qemu_find_opts("mon"), label, 1);
+    opts = qemu_opts_create(qemu_find_opts("mon"), label, 1, NULL);
     if (!opts) {
         fprintf(stderr, "duplicate chardev: %s\n", label);
         exit(1);
@@ -2035,14 +2035,14 @@ static int virtcon_parse(const char *devname)
         exit(1);
     }
 
-    bus_opts = qemu_opts_create(device, NULL, 0);
+    bus_opts = qemu_opts_create(device, NULL, 0, NULL);
     if (arch_type == QEMU_ARCH_S390X) {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-s390");
     } else {
         qemu_opt_set(bus_opts, "driver", "virtio-serial-pci");
     } 
 
-    dev_opts = qemu_opts_create(device, NULL, 0);
+    dev_opts = qemu_opts_create(device, NULL, 0, NULL);
     qemu_opt_set(dev_opts, "driver", "virtconsole");
 
     snprintf(label, sizeof(label), "virtcon%d", index);
@@ -2065,7 +2065,7 @@ static int debugcon_parse(const char *devname)
     if (!qemu_chr_new("debugcon", devname, NULL)) {
         exit(1);
     }
-    opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1);
+    opts = qemu_opts_create(qemu_find_opts("device"), "debugcon", 1, NULL);
     if (!opts) {
         fprintf(stderr, "qemu: already have a debugcon device\n");
         exit(1);
@@ -2813,7 +2813,8 @@ int main(int argc, char **argv, char **envp)
                     exit(1);
                 }
                 fsdev = qemu_opts_create(qemu_find_opts("fsdev"),
-                                         qemu_opt_get(opts, "mount_tag"), 1);
+                                         qemu_opt_get(opts, "mount_tag"),
+                                         1, NULL);
                 if (!fsdev) {
                     fprintf(stderr, "duplicate fsdev id: %s\n",
                             qemu_opt_get(opts, "mount_tag"));
@@ -2845,7 +2846,8 @@ int main(int argc, char **argv, char **envp)
 
                 qemu_opt_set_bool(fsdev, "readonly",
                                 qemu_opt_get_bool(opts, "readonly", 0));
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
+                                          NULL);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev",
                              qemu_opt_get(opts, "mount_tag"));
@@ -2857,14 +2859,16 @@ int main(int argc, char **argv, char **envp)
                 QemuOpts *fsdev;
                 QemuOpts *device;
 
-                fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth", 1);
+                fsdev = qemu_opts_create(qemu_find_opts("fsdev"), "v_synth",
+                                         1, NULL);
                 if (!fsdev) {
                     fprintf(stderr, "duplicate option: %s\n", "virtfs_synth");
                     exit(1);
                 }
                 qemu_opt_set(fsdev, "fsdriver", "synth");
 
-                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0);
+                device = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
+                                          NULL);
                 qemu_opt_set(device, "driver", "virtio-9p-pci");
                 qemu_opt_set(device, "fsdev", "v_synth");
                 qemu_opt_set(device, "mount_tag", "v_synth");
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 14/29] qemu-option: parse_option_number(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (12 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 13/29] qemu-option: qemu_opts_create(): use error_set() Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 15/29] qemu-option: parse_option_bool(): " Luiz Capitulino
                   ` (15 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Note that qemu_opt_parse() callers still expect automatic error reporting
with QError, so qemu_opts_parse() calls qerror_report_err() to keep the
same semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-option.c | 26 +++++++++++++++++++-------
 1 file changed, 19 insertions(+), 7 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 9f531c8..72dcb56 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -186,7 +186,8 @@ static int parse_option_bool(const char *name, const char *value, bool *ret)
     return 0;
 }
 
-static int parse_option_number(const char *name, const char *value, uint64_t *ret)
+static void parse_option_number(const char *name, const char *value,
+                                uint64_t *ret, Error **errp)
 {
     char *postfix;
     uint64_t number;
@@ -194,15 +195,13 @@ static int parse_option_number(const char *name, const char *value, uint64_t *re
     if (value != NULL) {
         number = strtoull(value, &postfix, 0);
         if (*postfix != '\0') {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
-            return -1;
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
+            return;
         }
         *ret = number;
     } else {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a number");
-        return -1;
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a number");
     }
-    return 0;
 }
 
 static int parse_option_size(const char *name, const char *value, uint64_t *ret)
@@ -579,8 +578,11 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
 
 static int qemu_opt_parse(QemuOpt *opt)
 {
+    Error *local_err = NULL;
+
     if (opt->desc == NULL)
         return 0;
+
     switch (opt->desc->type) {
     case QEMU_OPT_STRING:
         /* nothing */
@@ -588,12 +590,22 @@ static int qemu_opt_parse(QemuOpt *opt)
     case QEMU_OPT_BOOL:
         return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
     case QEMU_OPT_NUMBER:
-        return parse_option_number(opt->name, opt->str, &opt->value.uint);
+        parse_option_number(opt->name, opt->str, &opt->value.uint,
+                            &local_err);
+        break;
     case QEMU_OPT_SIZE:
         return parse_option_size(opt->name, opt->str, &opt->value.uint);
     default:
         abort();
     }
+
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
 }
 
 static void qemu_opt_del(QemuOpt *opt)
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 15/29] qemu-option: parse_option_bool(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (13 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 14/29] qemu-option: parse_option_number(): " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 16/29] qemu-option: parse_option_size(): " Luiz Capitulino
                   ` (14 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Note that set_option_parameter() callers still expect automatic error
reporting with QError, so set_option_parameter() calls
qerror_report_err() to keep the same semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-option.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 72dcb56..b5da116 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -169,7 +169,8 @@ QEMUOptionParameter *get_option_parameter(QEMUOptionParameter *list,
     return NULL;
 }
 
-static int parse_option_bool(const char *name, const char *value, bool *ret)
+static void parse_option_bool(const char *name, const char *value, bool *ret,
+                              Error **errp)
 {
     if (value != NULL) {
         if (!strcmp(value, "on")) {
@@ -177,13 +178,11 @@ static int parse_option_bool(const char *name, const char *value, bool *ret)
         } else if (!strcmp(value, "off")) {
             *ret = 0;
         } else {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
-            return -1;
+            error_set(errp,QERR_INVALID_PARAMETER_VALUE, name, "'on' or 'off'");
         }
     } else {
         *ret = 1;
     }
-    return 0;
 }
 
 static void parse_option_number(const char *name, const char *value,
@@ -263,6 +262,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
     const char *value)
 {
     bool flag;
+    Error *local_err = NULL;
 
     // Find a matching parameter
     list = get_option_parameter(list, name);
@@ -274,9 +274,10 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
     // Process parameter
     switch (list->type) {
     case OPT_FLAG:
-        if (parse_option_bool(name, value, &flag) == -1)
-            return -1;
-        list->value.n = flag;
+        parse_option_bool(name, value, &flag, &local_err);
+        if (!error_is_set(&local_err)) {
+            list->value.n = flag;
+        }
         break;
 
     case OPT_STRING:
@@ -298,6 +299,12 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
         return -1;
     }
 
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
     return 0;
 }
 
@@ -588,7 +595,8 @@ static int qemu_opt_parse(QemuOpt *opt)
         /* nothing */
         return 0;
     case QEMU_OPT_BOOL:
-        return parse_option_bool(opt->name, opt->str, &opt->value.boolean);
+        parse_option_bool(opt->name, opt->str, &opt->value.boolean, &local_err);
+        break;
     case QEMU_OPT_NUMBER:
         parse_option_number(opt->name, opt->str, &opt->value.uint,
                             &local_err);
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 16/29] qemu-option: parse_option_size(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (14 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 15/29] qemu-option: parse_option_bool(): " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 17/29] qemu-option: qemu_opt_parse(): " Luiz Capitulino
                   ` (13 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-option.c | 17 ++++++++---------
 1 file changed, 8 insertions(+), 9 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index b5da116..42bb685 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -203,7 +203,8 @@ static void parse_option_number(const char *name, const char *value,
     }
 }
 
-static int parse_option_size(const char *name, const char *value, uint64_t *ret)
+static void parse_option_size(const char *name, const char *value,
+                              uint64_t *ret, Error **errp)
 {
     char *postfix;
     double sizef;
@@ -229,16 +230,14 @@ static int parse_option_size(const char *name, const char *value, uint64_t *ret)
             *ret = (uint64_t) sizef;
             break;
         default:
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
             error_printf_unless_qmp("You may use k, M, G or T suffixes for "
                     "kilobytes, megabytes, gigabytes and terabytes.\n");
-            return -1;
+            return;
         }
     } else {
-        qerror_report(QERR_INVALID_PARAMETER_VALUE, name, "a size");
-        return -1;
+        error_set(errp, QERR_INVALID_PARAMETER_VALUE, name, "a size");
     }
-    return 0;
 }
 
 /*
@@ -290,8 +289,7 @@ int set_option_parameter(QEMUOptionParameter *list, const char *name,
         break;
 
     case OPT_SIZE:
-        if (parse_option_size(name, value, &list->value.n) == -1)
-            return -1;
+        parse_option_size(name, value, &list->value.n, &local_err);
         break;
 
     default:
@@ -602,7 +600,8 @@ static int qemu_opt_parse(QemuOpt *opt)
                             &local_err);
         break;
     case QEMU_OPT_SIZE:
-        return parse_option_size(opt->name, opt->str, &opt->value.uint);
+        parse_option_size(opt->name, opt->str, &opt->value.uint, &local_err);
+        break;
     default:
         abort();
     }
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 17/29] qemu-option: qemu_opt_parse(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (15 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 16/29] qemu-option: parse_option_size(): " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 18/29] qemu-option: qemu_opts_validate(): " Luiz Capitulino
                   ` (12 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

The functions opt_set() and qemu_opts_validate() both call qemu_opt_parse(),
but their callers expect QError semantics. Thus, both functions call
qerro_report_err() to keep the expected semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-option.c | 36 +++++++++++++++++-------------------
 1 file changed, 17 insertions(+), 19 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index 42bb685..6d36970 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -581,38 +581,27 @@ uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval)
     return opt->value.uint;
 }
 
-static int qemu_opt_parse(QemuOpt *opt)
+static void qemu_opt_parse(QemuOpt *opt, Error **errp)
 {
-    Error *local_err = NULL;
-
     if (opt->desc == NULL)
-        return 0;
+        return;
 
     switch (opt->desc->type) {
     case QEMU_OPT_STRING:
         /* nothing */
-        return 0;
+        return;
     case QEMU_OPT_BOOL:
-        parse_option_bool(opt->name, opt->str, &opt->value.boolean, &local_err);
+        parse_option_bool(opt->name, opt->str, &opt->value.boolean, errp);
         break;
     case QEMU_OPT_NUMBER:
-        parse_option_number(opt->name, opt->str, &opt->value.uint,
-                            &local_err);
+        parse_option_number(opt->name, opt->str, &opt->value.uint, errp);
         break;
     case QEMU_OPT_SIZE:
-        parse_option_size(opt->name, opt->str, &opt->value.uint, &local_err);
+        parse_option_size(opt->name, opt->str, &opt->value.uint, errp);
         break;
     default:
         abort();
     }
-
-    if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
-    }
-
-    return 0;
 }
 
 static void qemu_opt_del(QemuOpt *opt)
@@ -628,6 +617,7 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
 {
     QemuOpt *opt;
     const QemuOptDesc *desc = opts->list->desc;
+    Error *local_err = NULL;
     int i;
 
     for (i = 0; desc[i].name != NULL; i++) {
@@ -658,10 +648,14 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
     if (value) {
         opt->str = g_strdup(value);
     }
-    if (qemu_opt_parse(opt) < 0) {
+    qemu_opt_parse(opt, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         qemu_opt_del(opt);
         return -1;
     }
+
     return 0;
 }
 
@@ -1050,6 +1044,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
 int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
 {
     QemuOpt *opt;
+    Error *local_err = NULL;
 
     assert(opts->list->desc[0].name == NULL);
 
@@ -1068,7 +1063,10 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
 
         opt->desc = &desc[i];
 
-        if (qemu_opt_parse(opt) < 0) {
+        qemu_opt_parse(opt, &local_err);
+        if (error_is_set(&local_err)) {
+            qerror_report_err(local_err);
+            error_free(local_err);
             return -1;
         }
     }
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 18/29] qemu-option: qemu_opts_validate(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (16 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 17/29] qemu-option: qemu_opt_parse(): " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 19/29] qemu-option: opt_set(): " Luiz Capitulino
                   ` (11 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

net_client_init() propagates the error up by calling qerror_report_err(),
because its users expect QError semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 net.c         |  6 +++++-
 qemu-option.c | 13 +++++--------
 qemu-option.h |  2 +-
 3 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/net.c b/net.c
index 1922d8a..f5d9cc7 100644
--- a/net.c
+++ b/net.c
@@ -1136,10 +1136,14 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
     for (i = 0; i < NET_CLIENT_TYPE_MAX; i++) {
         if (net_client_types[i].type != NULL &&
             !strcmp(net_client_types[i].type, type)) {
+            Error *local_err = NULL;
             VLANState *vlan = NULL;
             int ret;
 
-            if (qemu_opts_validate(opts, &net_client_types[i].desc[0]) == -1) {
+            qemu_opts_validate(opts, &net_client_types[i].desc[0], &local_err);
+            if (error_is_set(&local_err)) {
+                qerror_report_err(local_err);
+                error_free(local_err);
                 return -1;
             }
 
diff --git a/qemu-option.c b/qemu-option.c
index 6d36970..eee3b45 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -1041,7 +1041,7 @@ QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict)
 /* Validate parsed opts against descriptions where no
  * descriptions were provided in the QemuOptsList.
  */
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp)
 {
     QemuOpt *opt;
     Error *local_err = NULL;
@@ -1057,21 +1057,18 @@ int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc)
             }
         }
         if (desc[i].name == NULL) {
-            qerror_report(QERR_INVALID_PARAMETER, opt->name);
-            return -1;
+            error_set(errp, QERR_INVALID_PARAMETER, opt->name);
+            return;
         }
 
         opt->desc = &desc[i];
 
         qemu_opt_parse(opt, &local_err);
         if (error_is_set(&local_err)) {
-            qerror_report_err(local_err);
-            error_free(local_err);
-            return -1;
+            error_propagate(errp, local_err);
+            return;
         }
     }
-
-    return 0;
 }
 
 int qemu_opts_foreach(QemuOptsList *list, qemu_opts_loopfunc func, void *opaque,
diff --git a/qemu-option.h b/qemu-option.h
index 4d5b3d3..e9fbbb5 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -125,7 +125,7 @@ int qemu_opts_set(QemuOptsList *list, const char *id,
                   const char *name, const char *value);
 const char *qemu_opts_id(QemuOpts *opts);
 void qemu_opts_del(QemuOpts *opts);
-int qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc);
+void qemu_opts_validate(QemuOpts *opts, const QemuOptDesc *desc, Error **errp);
 int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname);
 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
 void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 19/29] qemu-option: opt_set(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (17 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 18/29] qemu-option: qemu_opts_validate(): " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 20/29] qemu-option: introduce qemu_opt_set_err() Luiz Capitulino
                   ` (10 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

The functions qemu_opt_set() and opts_do_parse() both call opt_set(),
but their callers expect QError semantics. Thus, both functions call
qerro_report_err() to keep the expected semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-option.c | 31 ++++++++++++++++++++-----------
 1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/qemu-option.c b/qemu-option.c
index eee3b45..7af2b50 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -612,8 +612,8 @@ static void qemu_opt_del(QemuOpt *opt)
     g_free(opt);
 }
 
-static int opt_set(QemuOpts *opts, const char *name, const char *value,
-                   bool prepend)
+static void opt_set(QemuOpts *opts, const char *name, const char *value,
+                    bool prepend, Error **errp)
 {
     QemuOpt *opt;
     const QemuOptDesc *desc = opts->list->desc;
@@ -629,8 +629,8 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
         if (i == 0) {
             /* empty list -> allow any */;
         } else {
-            qerror_report(QERR_INVALID_PARAMETER, name);
-            return -1;
+            error_set(errp, QERR_INVALID_PARAMETER, name);
+            return;
         }
     }
 
@@ -650,18 +650,23 @@ static int opt_set(QemuOpts *opts, const char *name, const char *value,
     }
     qemu_opt_parse(opt, &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         qemu_opt_del(opt);
-        return -1;
     }
-
-    return 0;
 }
 
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
 {
-    return opt_set(opts, name, value, false);
+    Error *local_err = NULL;
+
+    opt_set(opts, name, value, false, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return 0;
 }
 
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
@@ -847,6 +852,7 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
 {
     char option[128], value[1024];
     const char *p,*pe,*pc;
+    Error *local_err = NULL;
 
     for (p = params; *p != '\0'; p++) {
         pe = strchr(p, '=');
@@ -878,7 +884,10 @@ static int opts_do_parse(QemuOpts *opts, const char *params,
         }
         if (strcmp(option, "id") != 0) {
             /* store and parse */
-            if (opt_set(opts, option, value, prepend) == -1) {
+            opt_set(opts, option, value, prepend, &local_err);
+            if (error_is_set(&local_err)) {
+                qerror_report_err(local_err);
+                error_free(local_err);
                 return -1;
             }
         }
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 20/29] qemu-option: introduce qemu_opt_set_err()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (18 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 19/29] qemu-option: opt_set(): " Luiz Capitulino
@ 2012-06-05 17:24 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 21/29] qemu-option: qemu_opts_from_qdict(): use error_set() Luiz Capitulino
                   ` (9 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:24 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This is like qemu_opt_set(), except that it takes an Error argument.

This new function allows for a incremental conversion of code using
qemu_opt_set().

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-option.c | 6 ++++++
 qemu-option.h | 2 ++
 2 files changed, 8 insertions(+)

diff --git a/qemu-option.c b/qemu-option.c
index 7af2b50..1cddb9d 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -669,6 +669,12 @@ int qemu_opt_set(QemuOpts *opts, const char *name, const char *value)
     return 0;
 }
 
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+                      Error **errp)
+{
+    opt_set(opts, name, value, false, errp);
+}
+
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val)
 {
     QemuOpt *opt;
diff --git a/qemu-option.h b/qemu-option.h
index e9fbbb5..c0e022b 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -111,6 +111,8 @@ bool qemu_opt_get_bool(QemuOpts *opts, const char *name, bool defval);
 uint64_t qemu_opt_get_number(QemuOpts *opts, const char *name, uint64_t defval);
 uint64_t qemu_opt_get_size(QemuOpts *opts, const char *name, uint64_t defval);
 int qemu_opt_set(QemuOpts *opts, const char *name, const char *value);
+void qemu_opt_set_err(QemuOpts *opts, const char *name, const char *value,
+                      Error **errp);
 int qemu_opt_set_bool(QemuOpts *opts, const char *name, bool val);
 typedef int (*qemu_opt_loopfunc)(const char *name, const char *value, void *opaque);
 int qemu_opt_foreach(QemuOpts *opts, qemu_opt_loopfunc func, void *opaque,
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 21/29] qemu-option: qemu_opts_from_qdict(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (19 preceding siblings ...)
  2012-06-05 17:24 ` [Qemu-devel] [PATCH 20/29] qemu-option: introduce qemu_opt_set_err() Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 22/29] qerror: introduce QERR_INVALID_OPTION_GROUP Luiz Capitulino
                   ` (8 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

do_device_add() and do_netdev_add() call qerror_report_err() to maintain
their QError semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 hw/qdev-monitor.c |  7 +++++--
 net.c             |  5 ++++-
 qemu-option.c     | 31 ++++++++++++++++++++++++-------
 qemu-option.h     |  3 ++-
 4 files changed, 35 insertions(+), 11 deletions(-)

diff --git a/hw/qdev-monitor.c b/hw/qdev-monitor.c
index eed781d..b01ef06 100644
--- a/hw/qdev-monitor.c
+++ b/hw/qdev-monitor.c
@@ -554,10 +554,13 @@ void do_info_qdm(Monitor *mon)
 
 int do_device_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
+    Error *local_err = NULL;
     QemuOpts *opts;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict);
-    if (!opts) {
+    opts = qemu_opts_from_qdict(qemu_find_opts("device"), qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
     }
     if (!monitor_cur_is_qmp() && qdev_device_help(opts)) {
diff --git a/net.c b/net.c
index f5d9cc7..246209f 100644
--- a/net.c
+++ b/net.c
@@ -1237,11 +1237,14 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
 
 int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
 {
+    Error *local_err = NULL;
     QemuOpts *opts;
     int res;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict);
+    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &local_err);
     if (!opts) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
     }
 
diff --git a/qemu-option.c b/qemu-option.c
index 1cddb9d..bb3886c 100644
--- a/qemu-option.c
+++ b/qemu-option.c
@@ -968,13 +968,19 @@ void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
     assert(opts);
 }
 
+typedef struct OptsFromQDictState {
+    QemuOpts *opts;
+    Error **errp;
+} OptsFromQDictState;
+
 static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
 {
+    OptsFromQDictState *state = opaque;
     char buf[32];
     const char *value;
     int n;
 
-    if (!strcmp(key, "id")) {
+    if (!strcmp(key, "id") || error_is_set(state->errp)) {
         return;
     }
 
@@ -1002,7 +1008,8 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
     default:
         return;
     }
-    qemu_opt_set(opaque, key, value);
+
+    qemu_opt_set_err(state->opts, key, value, state->errp);
 }
 
 /*
@@ -1011,21 +1018,31 @@ static void qemu_opts_from_qdict_1(const char *key, QObject *obj, void *opaque)
  * Only QStrings, QInts, QFloats and QBools are copied.  Entries with
  * other types are silently ignored.
  */
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict)
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+                               Error **errp)
 {
-    QemuOpts *opts;
+    OptsFromQDictState state;
     Error *local_err = NULL;
+    QemuOpts *opts;
 
     opts = qemu_opts_create(list, qdict_get_try_str(qdict, "id"), 1,
                             &local_err);
     if (error_is_set(&local_err)) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+        error_propagate(errp, local_err);
         return NULL;
     }
 
     assert(opts != NULL);
-    qdict_iter(qdict, qemu_opts_from_qdict_1, opts);
+
+    state.errp = &local_err;
+    state.opts = opts;
+    qdict_iter(qdict, qemu_opts_from_qdict_1, &state);
+    if (error_is_set(&local_err)) {
+        error_propagate(errp, local_err);
+        qemu_opts_del(opts);
+        return NULL;
+    }
+
     return opts;
 }
 
diff --git a/qemu-option.h b/qemu-option.h
index c0e022b..951dec3 100644
--- a/qemu-option.h
+++ b/qemu-option.h
@@ -132,7 +132,8 @@ int qemu_opts_do_parse(QemuOpts *opts, const char *params, const char *firstname
 QemuOpts *qemu_opts_parse(QemuOptsList *list, const char *params, int permit_abbrev);
 void qemu_opts_set_defaults(QemuOptsList *list, const char *params,
                             int permit_abbrev);
-QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict);
+QemuOpts *qemu_opts_from_qdict(QemuOptsList *list, const QDict *qdict,
+                               Error **errp);
 QDict *qemu_opts_to_qdict(QemuOpts *opts, QDict *qdict);
 
 typedef int (*qemu_opts_loopfunc)(QemuOpts *opts, void *opaque);
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 22/29] qerror: introduce QERR_INVALID_OPTION_GROUP
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (20 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 21/29] qemu-option: qemu_opts_from_qdict(): use error_set() Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 23/29] qemu-config: find_list(): use error_set() Luiz Capitulino
                   ` (7 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qerror.c | 4 ++++
 qerror.h | 3 +++
 2 files changed, 7 insertions(+)

diff --git a/qerror.c b/qerror.c
index 5092fe7..92c4eff 100644
--- a/qerror.c
+++ b/qerror.c
@@ -156,6 +156,10 @@ static const QErrorStringTable qerror_table[] = {
         .desc      = "Invalid block format '%(name)'",
     },
     {
+        .error_fmt = QERR_INVALID_OPTION_GROUP,
+        .desc      = "There is no option group '%(group)'",
+    },
+    {
         .error_fmt = QERR_INVALID_PARAMETER,
         .desc      = "Invalid parameter '%(name)'",
     },
diff --git a/qerror.h b/qerror.h
index 4cbba48..b4c8758 100644
--- a/qerror.h
+++ b/qerror.h
@@ -139,6 +139,9 @@ QError *qobject_to_qerror(const QObject *obj);
 #define QERR_INVALID_BLOCK_FORMAT \
     "{ 'class': 'InvalidBlockFormat', 'data': { 'name': %s } }"
 
+#define QERR_INVALID_OPTION_GROUP \
+    "{ 'class': 'InvalidOptionGroup', 'data': { 'group': %s } }"
+
 #define QERR_INVALID_PARAMETER \
     "{ 'class': 'InvalidParameter', 'data': { 'name': %s } }"
 
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 23/29] qemu-config: find_list(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (21 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 22/29] qerror: introduce QERR_INVALID_OPTION_GROUP Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 24/29] qemu-config: introduce qemu_find_opts_err() Luiz Capitulino
                   ` (6 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Note that qemu_find_opts() and qemu_config_parse() need to call
error_report() to maintain their semantics on error.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-config.c | 32 +++++++++++++++++++++++++-------
 1 file changed, 25 insertions(+), 7 deletions(-)

diff --git a/qemu-config.c b/qemu-config.c
index f876646..bdb381d 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -3,6 +3,7 @@
 #include "qemu-option.h"
 #include "qemu-config.h"
 #include "hw/qdev.h"
+#include "error.h"
 
 static QemuOptsList qemu_drive_opts = {
     .name = "drive",
@@ -631,7 +632,8 @@ static QemuOptsList *vm_config_groups[32] = {
     NULL,
 };
 
-static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
+static QemuOptsList *find_list(QemuOptsList **lists, const char *group,
+                               Error **errp)
 {
     int i;
 
@@ -640,14 +642,23 @@ static QemuOptsList *find_list(QemuOptsList **lists, const char *group)
             break;
     }
     if (lists[i] == NULL) {
-        error_report("there is no option group \"%s\"", group);
+        error_set(errp, QERR_INVALID_OPTION_GROUP, group);
     }
     return lists[i];
 }
 
 QemuOptsList *qemu_find_opts(const char *group)
 {
-    return find_list(vm_config_groups, group);
+    QemuOptsList *ret;
+    Error *local_err = NULL;
+
+    ret = find_list(vm_config_groups, group, &local_err);
+    if (error_is_set(&local_err)) {
+        error_report("%s\n", error_get_pretty(local_err));
+        error_free(local_err);
+    }
+
+    return ret;
 }
 
 void qemu_add_opts(QemuOptsList *list)
@@ -762,6 +773,7 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
     char line[1024], group[64], id[64], arg[64], value[1024];
     Location loc;
     QemuOptsList *list = NULL;
+    Error *local_err = NULL;
     QemuOpts *opts = NULL;
     int res = -1, lno = 0;
 
@@ -778,17 +790,23 @@ int qemu_config_parse(FILE *fp, QemuOptsList **lists, const char *fname)
         }
         if (sscanf(line, "[%63s \"%63[^\"]\"]", group, id) == 2) {
             /* group with id */
-            list = find_list(lists, group);
-            if (list == NULL)
+            list = find_list(lists, group, &local_err);
+            if (error_is_set(&local_err)) {
+                error_report("%s\n", error_get_pretty(local_err));
+                error_free(local_err);
                 goto out;
+            }
             opts = qemu_opts_create(list, id, 1, NULL);
             continue;
         }
         if (sscanf(line, "[%63[^]]]", group) == 1) {
             /* group without id */
-            list = find_list(lists, group);
-            if (list == NULL)
+            list = find_list(lists, group, &local_err);
+            if (error_is_set(&local_err)) {
+                error_report("%s\n", error_get_pretty(local_err));
+                error_free(local_err);
                 goto out;
+            }
             opts = qemu_opts_create(list, NULL, 0, NULL);
             continue;
         }
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 24/29] qemu-config: introduce qemu_find_opts_err()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (22 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 23/29] qemu-config: find_list(): use error_set() Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 25/29] net: purge the monitor object from all init functions Luiz Capitulino
                   ` (5 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This is like qemu_find_opts(), except that it takes an Error argument.

This new function allows for a incremental conversion of code using
qemu_find_opts().

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 qemu-config.c | 5 +++++
 qemu-config.h | 3 +++
 2 files changed, 8 insertions(+)

diff --git a/qemu-config.c b/qemu-config.c
index bdb381d..bb3bff4 100644
--- a/qemu-config.c
+++ b/qemu-config.c
@@ -661,6 +661,11 @@ QemuOptsList *qemu_find_opts(const char *group)
     return ret;
 }
 
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp)
+{
+    return find_list(vm_config_groups, group, errp);
+}
+
 void qemu_add_opts(QemuOptsList *list)
 {
     int entries, i;
diff --git a/qemu-config.h b/qemu-config.h
index 6d7365d..e9f2ef4 100644
--- a/qemu-config.h
+++ b/qemu-config.h
@@ -1,11 +1,14 @@
 #ifndef QEMU_CONFIG_H
 #define QEMU_CONFIG_H
 
+#include "error.h"
+
 extern QemuOptsList qemu_fsdev_opts;
 extern QemuOptsList qemu_virtfs_opts;
 extern QemuOptsList qemu_spice_opts;
 
 QemuOptsList *qemu_find_opts(const char *group);
+QemuOptsList *qemu_find_opts_err(const char *group, Error **errp);
 void qemu_add_opts(QemuOptsList *list);
 int qemu_set_option(const char *str);
 int qemu_global_option(const char *str);
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 25/29] net: purge the monitor object from all init functions
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (23 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 24/29] qemu-config: introduce qemu_find_opts_err() Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 26/29] net: net_client_init(): use error_set() Luiz Capitulino
                   ` (4 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

The only backend that really uses it is the socket one, which calls
monitor_get_fd(). But it can use 'cur_mon' instead.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 hw/pci-hotplug.c     |  2 +-
 hw/usb/dev-network.c |  2 +-
 net.c                | 18 +++++++-----------
 net.h                |  2 +-
 net/dump.c           |  2 +-
 net/dump.h           |  3 +--
 net/slirp.c          |  5 +----
 net/slirp.h          |  5 +----
 net/socket.c         |  8 +++-----
 net/socket.h         |  3 +--
 net/tap-win32.c      |  2 +-
 net/tap.c            |  9 ++++-----
 net/tap.h            |  5 ++---
 net/vde.c            |  2 +-
 net/vde.h            |  2 +-
 15 files changed, 27 insertions(+), 43 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index c55d8b9..785eb3d 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -60,7 +60,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
 
     qemu_opt_set(opts, "type", "nic");
 
-    ret = net_client_init(mon, opts, 0);
+    ret = net_client_init(opts, 0);
     if (ret < 0)
         return NULL;
     if (nd_table[ret].devaddr) {
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index b238a09..4e26e64 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1367,7 +1367,7 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
     qemu_opt_set(opts, "type", "nic");
     qemu_opt_set(opts, "model", "usb");
 
-    idx = net_client_init(NULL, opts, 0);
+    idx = net_client_init(opts, 0);
     if (idx == -1) {
         return NULL;
     }
diff --git a/net.c b/net.c
index 246209f..adb7e20 100644
--- a/net.c
+++ b/net.c
@@ -745,10 +745,7 @@ int net_handle_fd_param(Monitor *mon, const char *param)
     return fd;
 }
 
-static int net_init_nic(QemuOpts *opts,
-                        Monitor *mon,
-                        const char *name,
-                        VLANState *vlan)
+static int net_init_nic(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     int idx;
     NICInfo *nd;
@@ -821,7 +818,6 @@ static int net_init_nic(QemuOpts *opts,
      }
 
 typedef int (*net_client_init_func)(QemuOpts *opts,
-                                    Monitor *mon,
                                     const char *name,
                                     VLANState *vlan);
 
@@ -1085,7 +1081,7 @@ static const struct {
 #endif /* CONFIG_NET_BRIDGE */
 };
 
-int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
+int net_client_init(QemuOpts *opts, int is_netdev)
 {
     const char *name;
     const char *type;
@@ -1156,7 +1152,7 @@ int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev)
 
             ret = 0;
             if (net_client_types[i].init) {
-                ret = net_client_types[i].init(opts, mon, name, vlan);
+                ret = net_client_types[i].init(opts, name, vlan);
                 if (ret < 0) {
                     /* TODO push error reporting into init() methods */
                     qerror_report(QERR_DEVICE_INIT_FAILED, type);
@@ -1213,7 +1209,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 
     qemu_opt_set(opts, "type", device);
 
-    if (net_client_init(mon, opts, 0) < 0) {
+    if (net_client_init(opts, 0) < 0) {
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }
@@ -1248,7 +1244,7 @@ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    res = net_client_init(mon, opts, 1);
+    res = net_client_init(opts, 1);
     if (res < 0) {
         qemu_opts_del(opts);
     }
@@ -1431,14 +1427,14 @@ void net_check_clients(void)
 
 static int net_init_client(QemuOpts *opts, void *dummy)
 {
-    if (net_client_init(NULL, opts, 0) < 0)
+    if (net_client_init(opts, 0) < 0)
         return -1;
     return 0;
 }
 
 static int net_init_netdev(QemuOpts *opts, void *dummy)
 {
-    return net_client_init(NULL, opts, 1);
+    return net_client_init(opts, 1);
 }
 
 int net_init_clients(void)
diff --git a/net.h b/net.h
index 64993b4..9d1ed93 100644
--- a/net.h
+++ b/net.h
@@ -163,7 +163,7 @@ struct HCIInfo *qemu_next_hci(void);
 extern const char *legacy_tftp_prefix;
 extern const char *legacy_bootp_filename;
 
-int net_client_init(Monitor *mon, QemuOpts *opts, int is_netdev);
+int net_client_init(QemuOpts *opts, int is_netdev);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
 void net_check_clients(void);
diff --git a/net/dump.c b/net/dump.c
index 4b48d48..f835c51 100644
--- a/net/dump.c
+++ b/net/dump.c
@@ -144,7 +144,7 @@ static int net_dump_init(VLANState *vlan, const char *device,
     return 0;
 }
 
-int net_init_dump(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     int len;
     const char *file;
diff --git a/net/dump.h b/net/dump.h
index fdc91ad..2b5d9ba 100644
--- a/net/dump.h
+++ b/net/dump.h
@@ -27,7 +27,6 @@
 #include "net.h"
 #include "qemu-common.h"
 
-int net_init_dump(QemuOpts *opts, Monitor *mon,
-                  const char *name, VLANState *vlan);
+int net_init_dump(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* QEMU_NET_DUMP_H */
diff --git a/net/slirp.c b/net/slirp.c
index 96f5032..37b6ccf 100644
--- a/net/slirp.c
+++ b/net/slirp.c
@@ -676,10 +676,7 @@ static int net_init_slirp_configs(const char *name, const char *value, void *opa
     return 0;
 }
 
-int net_init_slirp(QemuOpts *opts,
-                   Monitor *mon,
-                   const char *name,
-                   VLANState *vlan)
+int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     struct slirp_config_str *config;
     const char *vhost;
diff --git a/net/slirp.h b/net/slirp.h
index c17de8e..53fe95d 100644
--- a/net/slirp.h
+++ b/net/slirp.h
@@ -30,10 +30,7 @@
 
 #ifdef CONFIG_SLIRP
 
-int net_init_slirp(QemuOpts *opts,
-                   Monitor *mon,
-                   const char *name,
-                   VLANState *vlan);
+int net_init_slirp(QemuOpts *opts, const char *name, VLANState *vlan);
 
 void net_slirp_hostfwd_add(Monitor *mon, const QDict *qdict);
 void net_slirp_hostfwd_remove(Monitor *mon, const QDict *qdict);
diff --git a/net/socket.c b/net/socket.c
index 0bcf229..fcd0a3c 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -26,6 +26,7 @@
 #include "config-host.h"
 
 #include "net.h"
+#include "monitor.h"
 #include "qemu-char.h"
 #include "qemu-common.h"
 #include "qemu-error.h"
@@ -585,10 +586,7 @@ static int net_socket_udp_init(VLANState *vlan,
     return 0;
 }
 
-int net_init_socket(QemuOpts *opts,
-                    Monitor *mon,
-                    const char *name,
-                    VLANState *vlan)
+int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     if (qemu_opt_get(opts, "fd")) {
         int fd;
@@ -601,7 +599,7 @@ int net_init_socket(QemuOpts *opts,
             return -1;
         }
 
-        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
+        fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd"));
         if (fd == -1) {
             return -1;
         }
diff --git a/net/socket.h b/net/socket.h
index ea46f02..e1fe959 100644
--- a/net/socket.h
+++ b/net/socket.h
@@ -27,7 +27,6 @@
 #include "net.h"
 #include "qemu-common.h"
 
-int net_init_socket(QemuOpts *opts, Monitor *mon,
-                    const char *name, VLANState *vlan);
+int net_init_socket(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* QEMU_NET_SOCKET_H */
diff --git a/net/tap-win32.c b/net/tap-win32.c
index 596132e..a801a55 100644
--- a/net/tap-win32.c
+++ b/net/tap-win32.c
@@ -699,7 +699,7 @@ static int tap_win32_init(VLANState *vlan, const char *model,
     return 0;
 }
 
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     const char *ifname;
 
diff --git a/net/tap.c b/net/tap.c
index f240028..5ac4ba3 100644
--- a/net/tap.c
+++ b/net/tap.c
@@ -512,8 +512,7 @@ static int net_bridge_run_helper(const char *helper, const char *bridge)
     return -1;
 }
 
-int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
-                    VLANState *vlan)
+int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     TAPState *s;
     int fd, vnet_hdr;
@@ -583,7 +582,7 @@ static int net_tap_init(QemuOpts *opts, int *vnet_hdr)
     return fd;
 }
 
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     TAPState *s;
     int fd, vnet_hdr = 0;
@@ -600,7 +599,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
             return -1;
         }
 
-        fd = net_handle_fd_param(mon, qemu_opt_get(opts, "fd"));
+        fd = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "fd"));
         if (fd == -1) {
             return -1;
         }
@@ -687,7 +686,7 @@ int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan
         int vhostfd, r;
         bool force = qemu_opt_get_bool(opts, "vhostforce", false);
         if (qemu_opt_get(opts, "vhostfd")) {
-            r = net_handle_fd_param(mon, qemu_opt_get(opts, "vhostfd"));
+            r = net_handle_fd_param(cur_mon, qemu_opt_get(opts, "vhostfd"));
             if (r == -1) {
                 return -1;
             }
diff --git a/net/tap.h b/net/tap.h
index 56c591f..b2a9450 100644
--- a/net/tap.h
+++ b/net/tap.h
@@ -32,7 +32,7 @@
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
 
-int net_init_tap(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+int net_init_tap(QemuOpts *opts, const char *name, VLANState *vlan);
 
 int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required);
 
@@ -57,7 +57,6 @@ int tap_get_fd(VLANClientState *vc);
 struct vhost_net;
 struct vhost_net *tap_get_vhost_net(VLANClientState *vc);
 
-int net_init_bridge(QemuOpts *opts, Monitor *mon, const char *name,
-                    VLANState *vlan);
+int net_init_bridge(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* QEMU_NET_TAP_H */
diff --git a/net/vde.c b/net/vde.c
index ac48ab2..6b9d452 100644
--- a/net/vde.c
+++ b/net/vde.c
@@ -110,7 +110,7 @@ static int net_vde_init(VLANState *vlan, const char *model,
     return 0;
 }
 
-int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan)
+int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan)
 {
     const char *sock;
     const char *group;
diff --git a/net/vde.h b/net/vde.h
index 3e6ca3e..732e575 100644
--- a/net/vde.h
+++ b/net/vde.h
@@ -29,7 +29,7 @@
 
 #ifdef CONFIG_VDE
 
-int net_init_vde(QemuOpts *opts, Monitor *mon, const char *name, VLANState *vlan);
+int net_init_vde(QemuOpts *opts, const char *name, VLANState *vlan);
 
 #endif /* CONFIG_VDE */
 
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 26/29] net: net_client_init(): use error_set()
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (24 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 25/29] net: purge the monitor object from all init functions Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 27/29] qapi: convert netdev_add Luiz Capitulino
                   ` (3 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Callers are changed to use qerror_report_err() to keep their QError
semantics.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 hw/pci-hotplug.c     |  8 ++++++--
 hw/usb/dev-network.c |  7 +++++--
 net.c                | 54 ++++++++++++++++++++++++++++++++++++----------------
 net.h                |  2 +-
 4 files changed, 50 insertions(+), 21 deletions(-)

diff --git a/hw/pci-hotplug.c b/hw/pci-hotplug.c
index 785eb3d..61257f4 100644
--- a/hw/pci-hotplug.c
+++ b/hw/pci-hotplug.c
@@ -39,6 +39,7 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
                                        const char *devaddr,
                                        const char *opts_str)
 {
+    Error *local_err = NULL;
     QemuOpts *opts;
     PCIBus *bus;
     int ret, devfn;
@@ -60,9 +61,12 @@ static PCIDevice *qemu_pci_hot_add_nic(Monitor *mon,
 
     qemu_opt_set(opts, "type", "nic");
 
-    ret = net_client_init(opts, 0);
-    if (ret < 0)
+    ret = net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
+    }
     if (nd_table[ret].devaddr) {
         monitor_printf(mon, "Parameter addr not supported\n");
         return NULL;
diff --git a/hw/usb/dev-network.c b/hw/usb/dev-network.c
index 4e26e64..5d2f098 100644
--- a/hw/usb/dev-network.c
+++ b/hw/usb/dev-network.c
@@ -1356,6 +1356,7 @@ static int usb_net_initfn(USBDevice *dev)
 
 static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
 {
+    Error *local_err = NULL;
     USBDevice *dev;
     QemuOpts *opts;
     int idx;
@@ -1367,8 +1368,10 @@ static USBDevice *usb_net_init(USBBus *bus, const char *cmdline)
     qemu_opt_set(opts, "type", "nic");
     qemu_opt_set(opts, "model", "usb");
 
-    idx = net_client_init(opts, 0);
-    if (idx == -1) {
+    idx = net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return NULL;
     }
 
diff --git a/net.c b/net.c
index adb7e20..8f7cb40 100644
--- a/net.c
+++ b/net.c
@@ -1081,7 +1081,7 @@ static const struct {
 #endif /* CONFIG_NET_BRIDGE */
 };
 
-int net_client_init(QemuOpts *opts, int is_netdev)
+int net_client_init(QemuOpts *opts, int is_netdev, Error **errp)
 {
     const char *name;
     const char *type;
@@ -1089,7 +1089,7 @@ int net_client_init(QemuOpts *opts, int is_netdev)
 
     type = qemu_opt_get(opts, "type");
     if (!type) {
-        qerror_report(QERR_MISSING_PARAMETER, "type");
+        error_set(errp, QERR_MISSING_PARAMETER, "type");
         return -1;
     }
 
@@ -1105,21 +1105,21 @@ int net_client_init(QemuOpts *opts, int is_netdev)
             strcmp(type, "vde") != 0 &&
 #endif
             strcmp(type, "socket") != 0) {
-            qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
-                          "a netdev backend type");
+            error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+                      "a netdev backend type");
             return -1;
         }
 
         if (qemu_opt_get(opts, "vlan")) {
-            qerror_report(QERR_INVALID_PARAMETER, "vlan");
+            error_set(errp, QERR_INVALID_PARAMETER, "vlan");
             return -1;
         }
         if (qemu_opt_get(opts, "name")) {
-            qerror_report(QERR_INVALID_PARAMETER, "name");
+            error_set(errp, QERR_INVALID_PARAMETER, "name");
             return -1;
         }
         if (!qemu_opts_id(opts)) {
-            qerror_report(QERR_MISSING_PARAMETER, "id");
+            error_set(errp, QERR_MISSING_PARAMETER, "id");
             return -1;
         }
     }
@@ -1138,8 +1138,7 @@ int net_client_init(QemuOpts *opts, int is_netdev)
 
             qemu_opts_validate(opts, &net_client_types[i].desc[0], &local_err);
             if (error_is_set(&local_err)) {
-                qerror_report_err(local_err);
-                error_free(local_err);
+                error_propagate(errp, local_err);
                 return -1;
             }
 
@@ -1155,7 +1154,7 @@ int net_client_init(QemuOpts *opts, int is_netdev)
                 ret = net_client_types[i].init(opts, name, vlan);
                 if (ret < 0) {
                     /* TODO push error reporting into init() methods */
-                    qerror_report(QERR_DEVICE_INIT_FAILED, type);
+                    error_set(errp, QERR_DEVICE_INIT_FAILED, type);
                     return -1;
                 }
             }
@@ -1163,8 +1162,8 @@ int net_client_init(QemuOpts *opts, int is_netdev)
         }
     }
 
-    qerror_report(QERR_INVALID_PARAMETER_VALUE, "type",
-                  "a network client type");
+    error_set(errp, QERR_INVALID_PARAMETER_VALUE, "type",
+              "a network client type");
     return -1;
 }
 
@@ -1195,6 +1194,7 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 {
     const char *device = qdict_get_str(qdict, "device");
     const char *opts_str = qdict_get_try_str(qdict, "opts");
+    Error *local_err = NULL;
     QemuOpts *opts;
 
     if (!net_host_check_device(device)) {
@@ -1209,7 +1209,10 @@ void net_host_device_add(Monitor *mon, const QDict *qdict)
 
     qemu_opt_set(opts, "type", device);
 
-    if (net_client_init(opts, 0) < 0) {
+    net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         monitor_printf(mon, "adding host network device %s failed\n", device);
     }
 }
@@ -1244,8 +1247,10 @@ int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
         return -1;
     }
 
-    res = net_client_init(opts, 1);
+    res = net_client_init(opts, 1, &local_err);
     if (res < 0) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         qemu_opts_del(opts);
     }
 
@@ -1427,14 +1432,31 @@ void net_check_clients(void)
 
 static int net_init_client(QemuOpts *opts, void *dummy)
 {
-    if (net_client_init(opts, 0) < 0)
+    Error *local_err = NULL;
+
+    net_client_init(opts, 0, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
         return -1;
+    }
+
     return 0;
 }
 
 static int net_init_netdev(QemuOpts *opts, void *dummy)
 {
-    return net_client_init(opts, 1);
+    Error *local_err = NULL;
+    int ret;
+
+    ret = net_client_init(opts, 1, &local_err);
+    if (error_is_set(&local_err)) {
+        qerror_report_err(local_err);
+        error_free(local_err);
+        return -1;
+    }
+
+    return ret;
 }
 
 int net_init_clients(void)
diff --git a/net.h b/net.h
index 9d1ed93..7ee97e9 100644
--- a/net.h
+++ b/net.h
@@ -163,7 +163,7 @@ struct HCIInfo *qemu_next_hci(void);
 extern const char *legacy_tftp_prefix;
 extern const char *legacy_bootp_filename;
 
-int net_client_init(QemuOpts *opts, int is_netdev);
+int net_client_init(QemuOpts *opts, int is_netdev, Error **errp);
 int net_client_parse(QemuOptsList *opts_list, const char *str);
 int net_init_clients(void);
 void net_check_clients(void);
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 27/29] qapi: convert netdev_add
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (25 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 26/29] net: net_client_init(): use error_set() Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 28/29] qapi: convert netdev_del Luiz Capitulino
                   ` (2 subsequent siblings)
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

This is not a full QAPI conversion, but an intermediate step.

In essence, do_netdev_add() is split into three functions:

 1. netdev_add(): performs the actual work. This function is fully
    converted to Error (thus, it's "qapi-friendly")

 2. qmp_netdev_add(): the QMP front-end for netdev_add(). This is
    coded by hand and not auto-generated (gen=no in the schema). The
    reason for this it's a lot easier and simpler to with QemuOpts
    this way

 3. hmp_netdev_add(): HMP front-end.

This design was suggested by Paolo Bonzini.

Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 hmp-commands.hx  |  3 +--
 hmp.c            | 21 +++++++++++++++++++++
 hmp.h            |  1 +
 net.c            | 36 ++++++++++++++++++++++++------------
 net.h            |  3 ++-
 qapi-schema.json | 28 ++++++++++++++++++++++++++++
 qmp-commands.hx  |  5 +----
 7 files changed, 78 insertions(+), 19 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index 81723c8..d0ce6a5 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1037,8 +1037,7 @@ ETEXI
         .args_type  = "netdev:O",
         .params     = "[user|tap|socket],id=str[,prop=value][,...]",
         .help       = "add host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_add,
+        .mhandler.cmd = hmp_netdev_add,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 42ced2a..7a4e25f 100644
--- a/hmp.c
+++ b/hmp.c
@@ -14,6 +14,8 @@
  */
 
 #include "hmp.h"
+#include "net.h"
+#include "qemu-option.h"
 #include "qemu-timer.h"
 #include "qmp-commands.h"
 
@@ -969,3 +971,22 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
                           &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_netdev_add(Monitor *mon, const QDict *qdict)
+{
+    Error *err = NULL;
+    QemuOpts *opts;
+
+    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &err);
+    if (error_is_set(&err)) {
+        goto out;
+    }
+
+    netdev_add(opts, &err);
+    if (error_is_set(&err)) {
+        qemu_opts_del(opts);
+    }
+
+out:
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 5cf3241..017df87 100644
--- a/hmp.h
+++ b/hmp.h
@@ -62,5 +62,6 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
 void hmp_migrate(Monitor *mon, const QDict *qdict);
 void hmp_device_del(Monitor *mon, const QDict *qdict);
 void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
+void hmp_netdev_add(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/net.c b/net.c
index 8f7cb40..5f0c53c 100644
--- a/net.c
+++ b/net.c
@@ -1234,27 +1234,39 @@ void net_host_device_remove(Monitor *mon, const QDict *qdict)
     qemu_del_vlan_client(vc);
 }
 
-int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void netdev_add(QemuOpts *opts, Error **errp)
+{
+    net_client_init(opts, 1, errp);
+}
+
+int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret)
 {
     Error *local_err = NULL;
+    QemuOptsList *opts_list;
     QemuOpts *opts;
-    int res;
 
-    opts = qemu_opts_from_qdict(qemu_find_opts("netdev"), qdict, &local_err);
-    if (!opts) {
-        qerror_report_err(local_err);
-        error_free(local_err);
-        return -1;
+    opts_list = qemu_find_opts_err("netdev", &local_err);
+    if (error_is_set(&local_err)) {
+        goto exit_err;
     }
 
-    res = net_client_init(opts, 1, &local_err);
-    if (res < 0) {
-        qerror_report_err(local_err);
-        error_free(local_err);
+    opts = qemu_opts_from_qdict(opts_list, qdict, &local_err);
+    if (error_is_set(&local_err)) {
+        goto exit_err;
+    }
+
+    netdev_add(opts, &local_err);
+    if (error_is_set(&local_err)) {
         qemu_opts_del(opts);
+        goto exit_err;
     }
 
-    return res;
+    return 0;
+
+exit_err:
+    qerror_report_err(local_err);
+    error_free(local_err);
+    return -1;
 }
 
 int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
diff --git a/net.h b/net.h
index 7ee97e9..1eb9280 100644
--- a/net.h
+++ b/net.h
@@ -170,7 +170,8 @@ void net_check_clients(void);
 void net_cleanup(void);
 void net_host_device_add(Monitor *mon, const QDict *qdict);
 void net_host_device_remove(Monitor *mon, const QDict *qdict);
-int do_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret_data);
+void netdev_add(QemuOpts *opts, Error **errp);
+int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret);
 int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
diff --git a/qapi-schema.json b/qapi-schema.json
index dfa0e1f..69fcd8e 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1798,3 +1798,31 @@
 { 'command': 'dump-guest-memory',
   'data': { 'paging': 'bool', 'protocol': 'str', '*begin': 'int',
             '*length': 'int' } }
+##
+# @netdev_add:
+#
+# Add a network backend.
+#
+# @type: the type of network backend.  Current valid values are 'user', 'tap',
+#        'vde', 'socket', 'dump' and 'bridge'
+#
+# @id: the name of the new network backend
+#
+# @props: #optional a list of properties to be passed to the backend in
+#         the format 'name=value', like 'ifname=tap0,script=no'
+#
+# Notes: The semantics of @props is not well defined.  Future commands will be
+#        introduced that provide stronger typing for backend creation.
+#
+# Since: 0.14.0
+#
+# Returns: Nothing on success
+#          If @type is not a valid network backend, DeviceNotFound
+#          If @id is not a valid identifier, InvalidParameterValue
+#          if @id already exists, DuplicateId
+#          If @props contains an invalid parameter for this backend,
+#            InvalidParameter
+##
+{ 'command': 'netdev_add',
+  'data': {'type': 'str', 'id': 'str', '*props': '**'},
+  'gen': 'no' }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 2aa64ad..f6550cb 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -642,10 +642,7 @@ EQMP
     {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
-        .params     = "[user|tap|socket],id=str[,prop=value][,...]",
-        .help       = "add host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_add,
+        .mhandler.cmd_new = qmp_netdev_add,
     },
 
 SQMP
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 28/29] qapi: convert netdev_del
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (26 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 27/29] qapi: convert netdev_add Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 29/29] Add 'query-events' command to QMP to query async events Luiz Capitulino
  2012-06-07  1:17 ` [Qemu-devel] [PULL 00/29]: QMP queue Anthony Liguori
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

Signed-off-by: Anthony Liguori <aliguori@us.ibm.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
Reviewed-By: Laszlo Ersek <lersek@redhat.com>
---
 hmp-commands.hx  |  3 +--
 hmp.c            |  9 +++++++++
 hmp.h            |  1 +
 net.c            | 11 +++++------
 net.h            |  1 -
 qapi-schema.json | 14 ++++++++++++++
 qmp-commands.hx  |  5 +----
 7 files changed, 31 insertions(+), 13 deletions(-)

diff --git a/hmp-commands.hx b/hmp-commands.hx
index d0ce6a5..f5d9d91 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1051,8 +1051,7 @@ ETEXI
         .args_type  = "id:s",
         .params     = "id",
         .help       = "remove host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_del,
+        .mhandler.cmd = hmp_netdev_del,
     },
 
 STEXI
diff --git a/hmp.c b/hmp.c
index 7a4e25f..2ce8cb9 100644
--- a/hmp.c
+++ b/hmp.c
@@ -990,3 +990,12 @@ void hmp_netdev_add(Monitor *mon, const QDict *qdict)
 out:
     hmp_handle_error(mon, &err);
 }
+
+void hmp_netdev_del(Monitor *mon, const QDict *qdict)
+{
+    const char *id = qdict_get_str(qdict, "id");
+    Error *err = NULL;
+
+    qmp_netdev_del(id, &err);
+    hmp_handle_error(mon, &err);
+}
diff --git a/hmp.h b/hmp.h
index 017df87..79d138d 100644
--- a/hmp.h
+++ b/hmp.h
@@ -63,5 +63,6 @@ void hmp_migrate(Monitor *mon, const QDict *qdict);
 void hmp_device_del(Monitor *mon, const QDict *qdict);
 void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict);
 void hmp_netdev_add(Monitor *mon, const QDict *qdict);
+void hmp_netdev_del(Monitor *mon, const QDict *qdict);
 
 #endif
diff --git a/net.c b/net.c
index 5f0c53c..4aa416c 100644
--- a/net.c
+++ b/net.c
@@ -1269,19 +1269,18 @@ exit_err:
     return -1;
 }
 
-int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data)
+void qmp_netdev_del(const char *id, Error **errp)
 {
-    const char *id = qdict_get_str(qdict, "id");
     VLANClientState *vc;
 
     vc = qemu_find_netdev(id);
     if (!vc) {
-        qerror_report(QERR_DEVICE_NOT_FOUND, id);
-        return -1;
+        error_set(errp, QERR_DEVICE_NOT_FOUND, id);
+        return;
     }
+
     qemu_del_vlan_client(vc);
-    qemu_opts_del(qemu_opts_find(qemu_find_opts("netdev"), id));
-    return 0;
+    qemu_opts_del(qemu_opts_find(qemu_find_opts_err("netdev", errp), id));
 }
 
 static void print_net_client(Monitor *mon, VLANClientState *vc)
diff --git a/net.h b/net.h
index 1eb9280..bdc2a06 100644
--- a/net.h
+++ b/net.h
@@ -172,7 +172,6 @@ void net_host_device_add(Monitor *mon, const QDict *qdict);
 void net_host_device_remove(Monitor *mon, const QDict *qdict);
 void netdev_add(QemuOpts *opts, Error **errp);
 int qmp_netdev_add(Monitor *mon, const QDict *qdict, QObject **ret);
-int do_netdev_del(Monitor *mon, const QDict *qdict, QObject **ret_data);
 
 #define DEFAULT_NETWORK_SCRIPT "/etc/qemu-ifup"
 #define DEFAULT_NETWORK_DOWN_SCRIPT "/etc/qemu-ifdown"
diff --git a/qapi-schema.json b/qapi-schema.json
index 69fcd8e..bb1f806 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -1826,3 +1826,17 @@
 { 'command': 'netdev_add',
   'data': {'type': 'str', 'id': 'str', '*props': '**'},
   'gen': 'no' }
+
+##
+# @netdev_del:
+#
+# Remove a network backend.
+#
+# @id: the name of the network backend to remove
+#
+# Returns: Nothing on success
+#          If @id is not a valid network backend, DeviceNotFound
+#
+# Since: 0.14.0
+##
+{ 'command': 'netdev_del', 'data': {'id': 'str'} }
diff --git a/qmp-commands.hx b/qmp-commands.hx
index f6550cb..57ea803 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -671,10 +671,7 @@ EQMP
     {
         .name       = "netdev_del",
         .args_type  = "id:s",
-        .params     = "id",
-        .help       = "remove host network device",
-        .user_print = monitor_user_noop,
-        .mhandler.cmd_new = do_netdev_del,
+        .mhandler.cmd_new = qmp_marshal_input_netdev_del,
     },
 
 SQMP
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* [Qemu-devel] [PATCH 29/29] Add 'query-events' command to QMP to query async events
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (27 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 28/29] qapi: convert netdev_del Luiz Capitulino
@ 2012-06-05 17:25 ` Luiz Capitulino
  2012-06-07  1:17 ` [Qemu-devel] [PULL 00/29]: QMP queue Anthony Liguori
  29 siblings, 0 replies; 31+ messages in thread
From: Luiz Capitulino @ 2012-06-05 17:25 UTC (permalink / raw)
  To: qemu-devel; +Cc: aliguori

From: "Daniel P. Berrange" <berrange@redhat.com>

Sometimes it is neccessary for an application to determine
whether a particular QMP event is available, so they can
decide whether to use compatibility code instead. This
introduces a new 'query-events' command to QMP to do just
that

 { "execute": "query-events" }
 {"return": [{"name": "WAKEUP"},
             {"name": "SUSPEND"},
             {"name": "DEVICE_TRAY_MOVED"},
             {"name": "BLOCK_JOB_CANCELLED"},
             {"name": "BLOCK_JOB_COMPLETED"},
             ...snip...
             {"name": "SHUTDOWN"}]}

* monitor.c: Turn MonitorEvent -> string conversion
  into a lookup from a static table of constant strings.
  Add impl of qmp_query_events monitor command handler
* qapi-schema.json, qmp-commands.hx: Define contract of
  query-events command

Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com>
---
 monitor.c        | 107 +++++++++++++++++++++++--------------------------------
 monitor.h        |   4 +++
 qapi-schema.json |  22 ++++++++++++
 qmp-commands.hx  |  37 +++++++++++++++++++
 4 files changed, 108 insertions(+), 62 deletions(-)

diff --git a/monitor.c b/monitor.c
index 12a6fe2..a3bc2c7 100644
--- a/monitor.c
+++ b/monitor.c
@@ -422,6 +422,30 @@ static void timestamp_put(QDict *qdict)
     qdict_put_obj(qdict, "timestamp", obj);
 }
 
+
+static const char *monitor_event_names[] = {
+    [QEVENT_SHUTDOWN] = "SHUTDOWN",
+    [QEVENT_RESET] = "RESET",
+    [QEVENT_POWERDOWN] = "POWERDOWN",
+    [QEVENT_STOP] = "STOP",
+    [QEVENT_RESUME] = "RESUME",
+    [QEVENT_VNC_CONNECTED] = "VNC_CONNECTED",
+    [QEVENT_VNC_INITIALIZED] = "VNC_INITIALIZED",
+    [QEVENT_VNC_DISCONNECTED] = "VNC_DISCONNECTED",
+    [QEVENT_BLOCK_IO_ERROR] = "BLOCK_IO_ERROR",
+    [QEVENT_RTC_CHANGE] = "RTC_CHANGE",
+    [QEVENT_WATCHDOG] = "WATCHDOG",
+    [QEVENT_SPICE_CONNECTED] = "SPICE_CONNECTED",
+    [QEVENT_SPICE_INITIALIZED] = "SPICE_INITIALIZED",
+    [QEVENT_SPICE_DISCONNECTED] = "SPICE_DISCONNECTED",
+    [QEVENT_BLOCK_JOB_COMPLETED] = "BLOCK_JOB_COMPLETED",
+    [QEVENT_BLOCK_JOB_CANCELLED] = "BLOCK_JOB_CANCELLED",
+    [QEVENT_DEVICE_TRAY_MOVED] = "DEVICE_TRAY_MOVED",
+    [QEVENT_SUSPEND] = "SUSPEND",
+    [QEVENT_WAKEUP] = "WAKEUP",
+};
+QEMU_BUILD_BUG_ON(ARRAY_SIZE(monitor_event_names) != QEVENT_MAX)
+
 /**
  * monitor_protocol_event(): Generate a Monitor event
  *
@@ -435,68 +459,8 @@ void monitor_protocol_event(MonitorEvent event, QObject *data)
 
     assert(event < QEVENT_MAX);
 
-    switch (event) {
-        case QEVENT_SHUTDOWN:
-            event_name = "SHUTDOWN";
-            break;
-        case QEVENT_RESET:
-            event_name = "RESET";
-            break;
-        case QEVENT_POWERDOWN:
-            event_name = "POWERDOWN";
-            break;
-        case QEVENT_STOP:
-            event_name = "STOP";
-            break;
-        case QEVENT_RESUME:
-            event_name = "RESUME";
-            break;
-        case QEVENT_VNC_CONNECTED:
-            event_name = "VNC_CONNECTED";
-            break;
-        case QEVENT_VNC_INITIALIZED:
-            event_name = "VNC_INITIALIZED";
-            break;
-        case QEVENT_VNC_DISCONNECTED:
-            event_name = "VNC_DISCONNECTED";
-            break;
-        case QEVENT_BLOCK_IO_ERROR:
-            event_name = "BLOCK_IO_ERROR";
-            break;
-        case QEVENT_RTC_CHANGE:
-            event_name = "RTC_CHANGE";
-            break;
-        case QEVENT_WATCHDOG:
-            event_name = "WATCHDOG";
-            break;
-        case QEVENT_SPICE_CONNECTED:
-            event_name = "SPICE_CONNECTED";
-            break;
-        case QEVENT_SPICE_INITIALIZED:
-            event_name = "SPICE_INITIALIZED";
-            break;
-        case QEVENT_SPICE_DISCONNECTED:
-            event_name = "SPICE_DISCONNECTED";
-            break;
-        case QEVENT_BLOCK_JOB_COMPLETED:
-            event_name = "BLOCK_JOB_COMPLETED";
-            break;
-        case QEVENT_BLOCK_JOB_CANCELLED:
-            event_name = "BLOCK_JOB_CANCELLED";
-            break;
-        case QEVENT_DEVICE_TRAY_MOVED:
-             event_name = "DEVICE_TRAY_MOVED";
-            break;
-        case QEVENT_SUSPEND:
-            event_name = "SUSPEND";
-            break;
-        case QEVENT_WAKEUP:
-            event_name = "WAKEUP";
-            break;
-        default:
-            abort();
-            break;
-    }
+    event_name = monitor_event_names[event];
+    assert(event_name != NULL);
 
     qmp = qdict_new();
     timestamp_put(qmp);
@@ -738,6 +702,25 @@ CommandInfoList *qmp_query_commands(Error **errp)
     return cmd_list;
 }
 
+EventInfoList *qmp_query_events(Error **errp)
+{
+    EventInfoList *info, *ev_list = NULL;
+    MonitorEvent e;
+
+    for (e = 0 ; e < QEVENT_MAX ; e++) {
+        const char *event_name = monitor_event_names[e];
+        assert(event_name != NULL);
+        info = g_malloc0(sizeof(*info));
+        info->value = g_malloc0(sizeof(*info->value));
+        info->value->name = g_strdup(event_name);
+
+        info->next = ev_list;
+        ev_list = info;
+    }
+
+    return ev_list;
+}
+
 /* set the current CPU defined by the user */
 int monitor_set_cpu(int cpu_index)
 {
diff --git a/monitor.h b/monitor.h
index 0d49800..cd1d878 100644
--- a/monitor.h
+++ b/monitor.h
@@ -41,6 +41,10 @@ typedef enum MonitorEvent {
     QEVENT_DEVICE_TRAY_MOVED,
     QEVENT_SUSPEND,
     QEVENT_WAKEUP,
+
+    /* Add to 'monitor_event_names' array in monitor.c when
+     * defining new events here */
+
     QEVENT_MAX,
 } MonitorEvent;
 
diff --git a/qapi-schema.json b/qapi-schema.json
index bb1f806..3b6e346 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -228,6 +228,28 @@
 { 'command': 'query-commands', 'returns': ['CommandInfo'] }
 
 ##
+# @EventInfo:
+#
+# Information about a QMP event
+#
+# @name: The event name
+#
+# Since: 1.2.0
+##
+{ 'type': 'EventInfo', 'data': {'name': 'str'} }
+
+##
+# @query-events:
+#
+# Return a list of supported QMP events by this server
+#
+# Returns: A list of @EventInfo for all supported events
+#
+# Since: 1.2.0
+##
+{ 'command': 'query-events', 'returns': ['EventInfo'] }
+
+##
 # @MigrationStats
 #
 # Detailed migration status.
diff --git a/qmp-commands.hx b/qmp-commands.hx
index 57ea803..2e1a38e 100644
--- a/qmp-commands.hx
+++ b/qmp-commands.hx
@@ -1209,6 +1209,43 @@ EQMP
     },
 
 SQMP
+query-events
+--------------
+
+List QMP available events.
+
+Each event is represented by a json-object, the returned value is a json-array
+of all events.
+
+Each json-object contains:
+
+- "name": event's name (json-string)
+
+Example:
+
+-> { "execute": "query-events" }
+<- {
+      "return":[
+         {
+            "name":"SHUTDOWN"
+         },
+         {
+            "name":"RESET"
+         }
+      ]
+   }
+
+Note: This example has been shortened as the real response is too long.
+
+EQMP
+
+    {
+        .name       = "query-events",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_query_events,
+    },
+
+SQMP
 query-chardev
 -------------
 
-- 
1.7.10.2.565.gbd578b5

^ permalink raw reply related	[flat|nested] 31+ messages in thread

* Re: [Qemu-devel] [PULL 00/29]: QMP queue
  2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
                   ` (28 preceding siblings ...)
  2012-06-05 17:25 ` [Qemu-devel] [PATCH 29/29] Add 'query-events' command to QMP to query async events Luiz Capitulino
@ 2012-06-07  1:17 ` Anthony Liguori
  29 siblings, 0 replies; 31+ messages in thread
From: Anthony Liguori @ 2012-06-07  1:17 UTC (permalink / raw)
  To: Luiz Capitulino; +Cc: qemu-devel

On 06/06/2012 01:24 AM, Luiz Capitulino wrote:
> Contains the new commands dump-guest-memory and query-events; and the
> netdev_add/netdev_del conversion to the QAPI.
>
> The changes (since 8cc9b43f7c5f826b39af4b012ad89bb55faac29c) are available
> in the following repository:
>
>      git://repo.or.cz/qemu/qmp-unstable.git queue/qmp

Pulled.  Thanks.

Regards,

Anthony Liguori


> Daniel P. Berrange (1):
>        Add 'query-events' command to QMP to query async events
>
> Luiz Capitulino (16):
>        qemu-option: qemu_opts_create(): use error_set()
>        qemu-option: parse_option_number(): use error_set()
>        qemu-option: parse_option_bool(): use error_set()
>        qemu-option: parse_option_size(): use error_set()
>        qemu-option: qemu_opt_parse(): use error_set()
>        qemu-option: qemu_opts_validate(): use error_set()
>        qemu-option: opt_set(): use error_set()
>        qemu-option: introduce qemu_opt_set_err()
>        qemu-option: qemu_opts_from_qdict(): use error_set()
>        qerror: introduce QERR_INVALID_OPTION_GROUP
>        qemu-config: find_list(): use error_set()
>        qemu-config: introduce qemu_find_opts_err()
>        net: purge the monitor object from all init functions
>        net: net_client_init(): use error_set()
>        qapi: convert netdev_add
>        qapi: convert netdev_del
>
> Wen Congyang (12):
>        Add API to create memory mapping list
>        Add API to check whether a physical address is I/O address
>        implement cpu_get_memory_mapping()
>        Add API to check whether paging mode is enabled
>        Add API to get memory mapping
>        Add API to get memory mapping without do paging
>        target-i386: Add API to write elf notes to core file
>        target-i386: Add API to write cpu status to core file
>        target-i386: add API to get dump info
>        target-i386: Add API to get note's size
>        make gdb_id() generally avialable and rename it to cpu_index()
>        introduce a new monitor command 'dump-guest-memory' to dump guest's memory
>
>   Makefile.target                   |   5 +
>   blockdev.c                        |   2 +-
>   configure                         |   8 +
>   cpu-all.h                         |  70 +++
>   cpu-common.h                      |   4 +
>   dump.c                            | 883 ++++++++++++++++++++++++++++++++++++++
>   dump.h                            |  23 +
>   elf.h                             |   5 +
>   exec.c                            |  12 +
>   gdbstub.c                         |  19 +-
>   gdbstub.h                         |   9 +
>   hmp-commands.hx                   |  34 +-
>   hmp.c                             |  52 +++
>   hmp.h                             |   3 +
>   hw/pci-hotplug.c                  |   8 +-
>   hw/qdev-monitor.c                 |   7 +-
>   hw/usb/dev-network.c              |   7 +-
>   hw/usb/dev-storage.c              |   2 +-
>   hw/watchdog.c                     |   2 +-
>   memory_mapping.c                  | 249 +++++++++++
>   memory_mapping.h                  |  74 ++++
>   monitor.c                         | 107 ++---
>   monitor.h                         |   4 +
>   net.c                             | 104 +++--
>   net.h                             |   6 +-
>   net/dump.c                        |   2 +-
>   net/dump.h                        |   3 +-
>   net/slirp.c                       |   5 +-
>   net/slirp.h                       |   5 +-
>   net/socket.c                      |   8 +-
>   net/socket.h                      |   3 +-
>   net/tap-win32.c                   |   2 +-
>   net/tap.c                         |   9 +-
>   net/tap.h                         |   5 +-
>   net/vde.c                         |   2 +-
>   net/vde.h                         |   2 +-
>   qapi-schema.json                  | 107 +++++
>   qemu-char.c                       |   8 +-
>   qemu-config.c                     |  43 +-
>   qemu-config.h                     |   3 +
>   qemu-option.c                     | 175 +++++---
>   qemu-option.h                     |  11 +-
>   qemu-sockets.c                    |   8 +-
>   qerror.c                          |   4 +
>   qerror.h                          |   3 +
>   qmp-commands.hx                   |  83 +++-
>   target-i386/arch_dump.c           | 449 +++++++++++++++++++
>   target-i386/arch_memory_mapping.c | 271 ++++++++++++
>   vl.c                              |  22 +-
>   49 files changed, 2685 insertions(+), 247 deletions(-)
>
>
>

^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2012-06-07  1:17 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-05 17:24 [Qemu-devel] [PULL 00/29]: QMP queue Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 01/29] Add API to create memory mapping list Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 02/29] Add API to check whether a physical address is I/O address Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 03/29] implement cpu_get_memory_mapping() Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 04/29] Add API to check whether paging mode is enabled Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 05/29] Add API to get memory mapping Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 06/29] Add API to get memory mapping without do paging Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 07/29] target-i386: Add API to write elf notes to core file Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 08/29] target-i386: Add API to write cpu status " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 09/29] target-i386: add API to get dump info Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 10/29] target-i386: Add API to get note's size Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 11/29] make gdb_id() generally avialable and rename it to cpu_index() Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 12/29] introduce a new monitor command 'dump-guest-memory' to dump guest's memory Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 13/29] qemu-option: qemu_opts_create(): use error_set() Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 14/29] qemu-option: parse_option_number(): " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 15/29] qemu-option: parse_option_bool(): " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 16/29] qemu-option: parse_option_size(): " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 17/29] qemu-option: qemu_opt_parse(): " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 18/29] qemu-option: qemu_opts_validate(): " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 19/29] qemu-option: opt_set(): " Luiz Capitulino
2012-06-05 17:24 ` [Qemu-devel] [PATCH 20/29] qemu-option: introduce qemu_opt_set_err() Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 21/29] qemu-option: qemu_opts_from_qdict(): use error_set() Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 22/29] qerror: introduce QERR_INVALID_OPTION_GROUP Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 23/29] qemu-config: find_list(): use error_set() Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 24/29] qemu-config: introduce qemu_find_opts_err() Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 25/29] net: purge the monitor object from all init functions Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 26/29] net: net_client_init(): use error_set() Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 27/29] qapi: convert netdev_add Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 28/29] qapi: convert netdev_del Luiz Capitulino
2012-06-05 17:25 ` [Qemu-devel] [PATCH 29/29] Add 'query-events' command to QMP to query async events Luiz Capitulino
2012-06-07  1:17 ` [Qemu-devel] [PULL 00/29]: QMP queue Anthony Liguori

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.