Patchwork [RFC,04/14,v7] Add API to get memory mapping

login
register
mail settings
Submitter Wen Congyang
Date March 1, 2012, 2:43 a.m.
Message ID <4F4EE241.5030503@cn.fujitsu.com>
Download mbox | patch
Permalink /patch/143877/
State New
Headers show

Comments

Wen Congyang - March 1, 2012, 2:43 a.m.
Add API to get all virtual address and physical address mapping.
If there is no virtual address for some physical address, the virtual
address is 0.

Signed-off-by: Wen Congyang <wency@cn.fujitsu.com>
---
 memory_mapping.c |   71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |    8 ++++++
 2 files changed, 79 insertions(+), 0 deletions(-)
HATAYAMA Daisuke - March 1, 2012, 6:01 a.m.
From: Wen Congyang <wency@cn.fujitsu.com>
Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 10:43:13 +0800

> +int qemu_get_guest_memory_mapping(MemoryMappingList *list)
> +{
> +    CPUState *env;
> +    MemoryMapping *memory_mapping;
> +    RAMBlock *block;
> +    ram_addr_t offset, length;
> +    int ret;
> +
> +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
> +    for (env = first_cpu; env != NULL; env = env->next_cpu) {
> +        ret = cpu_get_memory_mapping(list, env);
> +        if (ret < 0) {
> +            return -1;
> +        }
> +    }
> +#else
> +    return -2;
> +#endif
> +
> +    /* some memory may be not mapped, add them into memory mapping's list */

The part from here is logic fully for 2nd kernel? If so, I think it
better to describe why this addtional mapping is needed; we should
assume most people doesn't know kdump mechanism.

> +    QLIST_FOREACH(block, &ram_list.blocks, next) {
> +        offset = block->offset;
> +        length = block->length;
> +
> +        QTAILQ_FOREACH(memory_mapping, &list->head, next) {
> +            if (memory_mapping->phys_addr >= (offset + length)) {
> +                /*
> +                 * memory_mapping's list does not conatin the region
> +                 * [offset, offset+length)
> +                 */
> +                create_new_memory_mapping(list, offset, 0, length);
> +                length = 0;
> +                break;
> +            }
> +
> +            if ((memory_mapping->phys_addr + memory_mapping->length) <=
> +                offset) {
> +                continue;
> +            }
> +
> +            if (memory_mapping->phys_addr > offset) {
> +                /*
> +                 * memory_mapping's list does not conatin the region
> +                 * [offset, memory_mapping->phys_addr)
> +                 */
> +                create_new_memory_mapping(list, offset, 0,
> +                                          memory_mapping->phys_addr - offset);
> +            }
> +
> +            if ((offset + length) <=
> +                (memory_mapping->phys_addr + memory_mapping->length)) {
> +                length = 0;
> +                break;
> +            }
> +            length -= memory_mapping->phys_addr + memory_mapping->length -
> +                      offset;
> +            offset = memory_mapping->phys_addr + memory_mapping->length;
> +        }
> +
> +        if (length > 0) {
> +            /*
> +             * memory_mapping's list does not conatin the region
> +             * [offset, memory_mapping->phys_addr)
> +             */
> +            create_new_memory_mapping(list, offset, 0, length);
> +        }
> +    }
> +
> +    return 0;
> +}

I think it more readable if shortening memory_mapping->phys_addr and
memmory_maping->length at the berinning of the innermost foreach loop.

  m_phys_addr = memory_mapping->phys_addr;
  m_length = memory_mapping->length;

Then, each conditionals becomes compact.

Thanks.
HATAYAMA, Daisuke
Wen Congyang - March 1, 2012, 6:17 a.m.
At 03/01/2012 02:01 PM, HATAYAMA Daisuke Wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
> Date: Thu, 01 Mar 2012 10:43:13 +0800
> 
>> +int qemu_get_guest_memory_mapping(MemoryMappingList *list)
>> +{
>> +    CPUState *env;
>> +    MemoryMapping *memory_mapping;
>> +    RAMBlock *block;
>> +    ram_addr_t offset, length;
>> +    int ret;
>> +
>> +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
>> +    for (env = first_cpu; env != NULL; env = env->next_cpu) {
>> +        ret = cpu_get_memory_mapping(list, env);
>> +        if (ret < 0) {
>> +            return -1;
>> +        }
>> +    }
>> +#else
>> +    return -2;
>> +#endif
>> +
>> +    /* some memory may be not mapped, add them into memory mapping's list */
> 
> The part from here is logic fully for 2nd kernel? If so, I think it
> better to describe why this addtional mapping is needed; we should
> assume most people doesn't know kdump mechanism.

Not only for 2nd kernel. If the guest has 1 vcpu, and is in the 2nd kernel,
we need this logic for 1st kernel.

Thanks
Wen Congyang

> 
>> +    QLIST_FOREACH(block, &ram_list.blocks, next) {
>> +        offset = block->offset;
>> +        length = block->length;
>> +
>> +        QTAILQ_FOREACH(memory_mapping, &list->head, next) {
>> +            if (memory_mapping->phys_addr >= (offset + length)) {
>> +                /*
>> +                 * memory_mapping's list does not conatin the region
>> +                 * [offset, offset+length)
>> +                 */
>> +                create_new_memory_mapping(list, offset, 0, length);
>> +                length = 0;
>> +                break;
>> +            }
>> +
>> +            if ((memory_mapping->phys_addr + memory_mapping->length) <=
>> +                offset) {
>> +                continue;
>> +            }
>> +
>> +            if (memory_mapping->phys_addr > offset) {
>> +                /*
>> +                 * memory_mapping's list does not conatin the region
>> +                 * [offset, memory_mapping->phys_addr)
>> +                 */
>> +                create_new_memory_mapping(list, offset, 0,
>> +                                          memory_mapping->phys_addr - offset);
>> +            }
>> +
>> +            if ((offset + length) <=
>> +                (memory_mapping->phys_addr + memory_mapping->length)) {
>> +                length = 0;
>> +                break;
>> +            }
>> +            length -= memory_mapping->phys_addr + memory_mapping->length -
>> +                      offset;
>> +            offset = memory_mapping->phys_addr + memory_mapping->length;
>> +        }
>> +
>> +        if (length > 0) {
>> +            /*
>> +             * memory_mapping's list does not conatin the region
>> +             * [offset, memory_mapping->phys_addr)
>> +             */
>> +            create_new_memory_mapping(list, offset, 0, length);
>> +        }
>> +    }
>> +
>> +    return 0;
>> +}
> 
> I think it more readable if shortening memory_mapping->phys_addr and
> memmory_maping->length at the berinning of the innermost foreach loop.
> 
>   m_phys_addr = memory_mapping->phys_addr;
>   m_length = memory_mapping->length;
> 
> Then, each conditionals becomes compact.
> 
> Thanks.
> HATAYAMA, Daisuke
> 
>
HATAYAMA Daisuke - March 1, 2012, 7:11 a.m.
From: Wen Congyang <wency@cn.fujitsu.com>
Subject: Re: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 14:17:53 +0800

> At 03/01/2012 02:01 PM, HATAYAMA Daisuke Wrote:
>> From: Wen Congyang <wency@cn.fujitsu.com>
>> Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
>> Date: Thu, 01 Mar 2012 10:43:13 +0800
>> 
>>> +int qemu_get_guest_memory_mapping(MemoryMappingList *list)
>>> +{
>>> +    CPUState *env;
>>> +    MemoryMapping *memory_mapping;
>>> +    RAMBlock *block;
>>> +    ram_addr_t offset, length;
>>> +    int ret;
>>> +
>>> +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
>>> +    for (env = first_cpu; env != NULL; env = env->next_cpu) {
>>> +        ret = cpu_get_memory_mapping(list, env);
>>> +        if (ret < 0) {
>>> +            return -1;
>>> +        }
>>> +    }
>>> +#else
>>> +    return -2;
>>> +#endif
>>> +
>>> +    /* some memory may be not mapped, add them into memory mapping's list */
>> 
>> The part from here is logic fully for 2nd kernel? If so, I think it
>> better to describe why this addtional mapping is needed; we should
>> assume most people doesn't know kdump mechanism.
> 
> Not only for 2nd kernel. If the guest has 1 vcpu, and is in the 2nd kernel,
> we need this logic for 1st kernel.
> 

So you should describe two cases explicitly. I don't understand them
from ``some memory''.

and please consider cleanup below too. Conditionals over two lines are
hard to read.

>> 
>> I think it more readable if shortening memory_mapping->phys_addr and
>> memmory_maping->length at the berinning of the innermost foreach loop.
>> 
>>   m_phys_addr = memory_mapping->phys_addr;
>>   m_length = memory_mapping->length;
>> 
>> Then, each conditionals becomes compact.

Thanks.
HATAYAMA, Daisuke
Wen Congyang - March 1, 2012, 7:22 a.m.
At 03/01/2012 03:11 PM, HATAYAMA Daisuke Wrote:
> From: Wen Congyang <wency@cn.fujitsu.com>
> Subject: Re: [RFC][PATCH 04/14 v7] Add API to get memory mapping
> Date: Thu, 01 Mar 2012 14:17:53 +0800
> 
>> At 03/01/2012 02:01 PM, HATAYAMA Daisuke Wrote:
>>> From: Wen Congyang <wency@cn.fujitsu.com>
>>> Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
>>> Date: Thu, 01 Mar 2012 10:43:13 +0800
>>>
>>>> +int qemu_get_guest_memory_mapping(MemoryMappingList *list)
>>>> +{
>>>> +    CPUState *env;
>>>> +    MemoryMapping *memory_mapping;
>>>> +    RAMBlock *block;
>>>> +    ram_addr_t offset, length;
>>>> +    int ret;
>>>> +
>>>> +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
>>>> +    for (env = first_cpu; env != NULL; env = env->next_cpu) {
>>>> +        ret = cpu_get_memory_mapping(list, env);
>>>> +        if (ret < 0) {
>>>> +            return -1;
>>>> +        }
>>>> +    }
>>>> +#else
>>>> +    return -2;
>>>> +#endif
>>>> +
>>>> +    /* some memory may be not mapped, add them into memory mapping's list */
>>>
>>> The part from here is logic fully for 2nd kernel? If so, I think it
>>> better to describe why this addtional mapping is needed; we should
>>> assume most people doesn't know kdump mechanism.
>>
>> Not only for 2nd kernel. If the guest has 1 vcpu, and is in the 2nd kernel,
>> we need this logic for 1st kernel.
>>
> 
> So you should describe two cases explicitly. I don't understand them
> from ``some memory''.
> 
> and please consider cleanup below too. Conditionals over two lines are
> hard to read.

OK. I will fix it.

Thanks
Wen Congyang

> 
>>>
>>> I think it more readable if shortening memory_mapping->phys_addr and
>>> memmory_maping->length at the berinning of the innermost foreach loop.
>>>
>>>   m_phys_addr = memory_mapping->phys_addr;
>>>   m_length = memory_mapping->length;
>>>
>>> Then, each conditionals becomes compact.
> 
> Thanks.
> HATAYAMA, Daisuke
> 
>

Patch

diff --git a/memory_mapping.c b/memory_mapping.c
index 84fb2c8..3743805 100644
--- a/memory_mapping.c
+++ b/memory_mapping.c
@@ -132,3 +132,74 @@  void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUState *env;
+    MemoryMapping *memory_mapping;
+    RAMBlock *block;
+    ram_addr_t offset, length;
+    int ret;
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+    for (env = first_cpu; env != NULL; env = env->next_cpu) {
+        ret = cpu_get_memory_mapping(list, env);
+        if (ret < 0) {
+            return -1;
+        }
+    }
+#else
+    return -2;
+#endif
+
+    /* some memory may be not mapped, add them into memory mapping's list */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        offset = block->offset;
+        length = block->length;
+
+        QTAILQ_FOREACH(memory_mapping, &list->head, next) {
+            if (memory_mapping->phys_addr >= (offset + length)) {
+                /*
+                 * memory_mapping's list does not conatin the region
+                 * [offset, offset+length)
+                 */
+                create_new_memory_mapping(list, offset, 0, length);
+                length = 0;
+                break;
+            }
+
+            if ((memory_mapping->phys_addr + memory_mapping->length) <=
+                offset) {
+                continue;
+            }
+
+            if (memory_mapping->phys_addr > offset) {
+                /*
+                 * memory_mapping's list does not conatin the region
+                 * [offset, memory_mapping->phys_addr)
+                 */
+                create_new_memory_mapping(list, offset, 0,
+                                          memory_mapping->phys_addr - offset);
+            }
+
+            if ((offset + length) <=
+                (memory_mapping->phys_addr + memory_mapping->length)) {
+                length = 0;
+                break;
+            }
+            length -= memory_mapping->phys_addr + memory_mapping->length -
+                      offset;
+            offset = memory_mapping->phys_addr + memory_mapping->length;
+        }
+
+        if (length > 0) {
+            /*
+             * memory_mapping's list does not conatin the region
+             * [offset, memory_mapping->phys_addr)
+             */
+            create_new_memory_mapping(list, offset, 0, length);
+        }
+    }
+
+    return 0;
+}
diff --git a/memory_mapping.h b/memory_mapping.h
index 633fcb9..5760d1d 100644
--- a/memory_mapping.h
+++ b/memory_mapping.h
@@ -41,4 +41,12 @@  void memory_mapping_list_add_sorted(MemoryMappingList *list,
 void memory_mapping_list_free(MemoryMappingList *list);
 void memory_mapping_list_init(MemoryMappingList *list);
 
+/*
+ * Return value:
+ *    0: success
+ *   -1: failed
+ *   -2: unsupported
+ */
+int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+
 #endif