@@ -197,6 +197,7 @@ obj-$(CONFIG_REALLY_VIRTFS) += 9pfs/virtio-9p-device.o
obj-$(CONFIG_KVM) += kvm.o kvm-all.o
obj-$(CONFIG_NO_KVM) += kvm-stub.o
obj-y += memory.o savevm.o
+obj-y += memory_mapping.o
LIBS+=-lz
QEMU_CFLAGS += $(VNC_TLS_CFLAGS)
new file mode 100644
@@ -0,0 +1,130 @@
+/*
+ * QEMU memory mapping
+ *
+ * Copyright Fujitsu, Corp. 2011
+ *
+ * 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 MemoryMapping *last_mapping;
+
+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, *p;
+
+ memory_mapping = g_malloc(sizeof(MemoryMapping));
+ memory_mapping->phys_addr = phys_addr;
+ memory_mapping->virt_addr = virt_addr;
+ memory_mapping->length = length;
+ last_mapping = memory_mapping;
+ list->num++;
+ QTAILQ_FOREACH(p, &list->head, next) {
+ if (p->phys_addr >= memory_mapping->phys_addr) {
+ QTAILQ_INSERT_BEFORE(p, memory_mapping, next);
+ return;
+ }
+ }
+ QTAILQ_INSERT_TAIL(&list->head, memory_mapping, next);
+ return;
+}
+
+void create_new_memory_mapping_head(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;
+ last_mapping = memory_mapping;
+ list->num++;
+ QTAILQ_INSERT_HEAD(&list->head, memory_mapping, next);
+ return;
+}
+
+void add_to_memory_mapping(MemoryMappingList *list,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length)
+{
+ MemoryMapping *memory_mapping;
+
+ if (QTAILQ_EMPTY(&list->head)) {
+ create_new_memory_mapping(list, phys_addr, virt_addr, length);
+ return;
+ }
+
+ if (last_mapping) {
+ if ((phys_addr == (last_mapping->phys_addr + last_mapping->length)) &&
+ (virt_addr == (last_mapping->virt_addr + last_mapping->length))) {
+ last_mapping->length += length;
+ return;
+ }
+ }
+
+ QTAILQ_FOREACH(memory_mapping, &list->head, next) {
+ last_mapping = memory_mapping;
+ if ((phys_addr == (last_mapping->phys_addr + last_mapping->length)) &&
+ (virt_addr == (last_mapping->virt_addr + last_mapping->length))) {
+ last_mapping->length += length;
+ return;
+ }
+
+ if (!(phys_addr >= (last_mapping->phys_addr)) ||
+ !(phys_addr < (last_mapping->phys_addr + last_mapping->length))) {
+ /* last_mapping does not contain this region */
+ continue;
+ }
+ if (!(virt_addr >= (last_mapping->virt_addr)) ||
+ !(virt_addr < (last_mapping->virt_addr + last_mapping->length))) {
+ /* last_mapping does not contain this region */
+ continue;
+ }
+ if ((virt_addr - last_mapping->virt_addr) !=
+ (phys_addr - last_mapping->phys_addr)) {
+ /*
+ * last_mapping contains this region, but we should create another
+ * mapping region.
+ */
+ break;
+ }
+
+ /* merge this region into last_mapping */
+ if ((virt_addr + length) >
+ (last_mapping->virt_addr + last_mapping->length)) {
+ last_mapping->length = virt_addr + length - last_mapping->virt_addr;
+ }
+ return;
+ }
+
+ /* this region can not be merged into any existed memory mapping. */
+ create_new_memory_mapping(list, phys_addr, virt_addr, length);
+ return;
+}
+
+void free_memory_mapping_list(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;
+}
new file mode 100644
@@ -0,0 +1,38 @@
+#ifndef MEMORY_MAPPING_H
+#define MEMORY_MAPPING_H
+
+#include "qemu-queue.h"
+
+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;
+ QTAILQ_HEAD(, MemoryMapping) head;
+} MemoryMappingList;
+
+/*
+ * crash needs some memory mapping should be at the head of the list. It will
+ * cause the list is not sorted. So the caller must add the special memory
+ * mapping after adding all the normal memory mapping into list.
+ */
+void create_new_memory_mapping_head(MemoryMappingList *list,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length);
+/*
+ * add or merge the memory region into the memory mapping's list. The list is
+ * sorted by phys_addr.
+ */
+void add_to_memory_mapping(MemoryMappingList *list,
+ target_phys_addr_t phys_addr,
+ target_phys_addr_t virt_addr,
+ ram_addr_t length);
+
+void free_memory_mapping_list(MemoryMappingList *list);
+
+#endif
The memory mapping list stores virtual address and physical address mapping. The folloing patch will use this information to create PT_LOAD in the vmcore. Signed-off-by: Wen Congyang <wency@cn.fujitsu.com> --- Makefile.target | 1 + memory_mapping.c | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ memory_mapping.h | 38 ++++++++++++++++ 3 files changed, 169 insertions(+), 0 deletions(-) create mode 100644 memory_mapping.c create mode 100644 memory_mapping.h