Patchwork [RFC,02/16,v6] Add API to create memory mapping list

login
register
mail settings
Submitter Wen Congyang
Date Feb. 9, 2012, 3:20 a.m.
Message ID <4F333B64.8030107@cn.fujitsu.com>
Download mbox | patch
Permalink /patch/140292/
State New
Headers show

Comments

Wen Congyang - Feb. 9, 2012, 3:20 a.m.
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
Jan Kiszka - Feb. 14, 2012, 4:39 p.m.
On 2012-02-09 04:20, Wen Congyang wrote:
> 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
> 
> diff --git a/Makefile.target b/Makefile.target
> index 68481a3..e35e464 100644
> --- a/Makefile.target
> +++ b/Makefile.target
> @@ -200,6 +200,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
> +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..d83b7d7
> --- /dev/null
> +++ b/memory_mapping.c
> @@ -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;
> +}
> diff --git a/memory_mapping.h b/memory_mapping.h
> new file mode 100644
> index 0000000..a4b1532
> --- /dev/null
> +++ b/memory_mapping.h
> @@ -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;

This field looks unused by this series. Unless I miss something, you
probably want to drop it.

> +    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

A bit hard to understand and use the API. I would suggest:

memory_mapping_list_add_sorted(MemoryMappingList *list, ...);
memory_mapping_list_add_head(MemoryMappingList *list, ...);
memory_mapping_list_free(MemoryMappingList *list);

memory_mapping_list_add_head should set a flag in the MemoryMapping
appended to the list or let the MemoryMappingList point to the firs
sorted entry. That way, the adding order becomes irrelevant.

Moreover, you are lacking some
memory_mapping_list_init(MemoryMappingList *list). Cleaner than
open-coding this.

Jan
Wen Congyang - Feb. 15, 2012, 3 a.m.
At 02/15/2012 12:39 AM, Jan Kiszka Wrote:
> On 2012-02-09 04:20, Wen Congyang wrote:
>> 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
>>
>> diff --git a/Makefile.target b/Makefile.target
>> index 68481a3..e35e464 100644
>> --- a/Makefile.target
>> +++ b/Makefile.target
>> @@ -200,6 +200,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
>> +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..d83b7d7
>> --- /dev/null
>> +++ b/memory_mapping.c
>> @@ -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;
>> +}
>> diff --git a/memory_mapping.h b/memory_mapping.h
>> new file mode 100644
>> index 0000000..a4b1532
>> --- /dev/null
>> +++ b/memory_mapping.h
>> @@ -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;
> 
> This field looks unused by this series. Unless I miss something, you
> probably want to drop it.

It is used in patch 09/16. I need it to calculate the PT_LOAD's 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
> 
> A bit hard to understand and use the API. I would suggest:

Sorry for confusing you. I will change the API's name.

> 
> memory_mapping_list_add_sorted(MemoryMappingList *list, ...);
> memory_mapping_list_add_head(MemoryMappingList *list, ...);
> memory_mapping_list_free(MemoryMappingList *list);
> 
> memory_mapping_list_add_head should set a flag in the MemoryMapping
> appended to the list or let the MemoryMappingList point to the firs
> sorted entry. That way, the adding order becomes irrelevant.

Agree with it.

> 
> Moreover, you are lacking some
> memory_mapping_list_init(MemoryMappingList *list). Cleaner than
> open-coding this.

A useful API, and I will add it.
Thanks
Wen Congyang

> 
> Jan
>

Patch

diff --git a/Makefile.target b/Makefile.target
index 68481a3..e35e464 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -200,6 +200,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
+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..d83b7d7
--- /dev/null
+++ b/memory_mapping.c
@@ -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;
+}
diff --git a/memory_mapping.h b/memory_mapping.h
new file mode 100644
index 0000000..a4b1532
--- /dev/null
+++ b/memory_mapping.h
@@ -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