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 <we...@cn.fujitsu.com> --- memory_mapping.c | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ memory_mapping.h | 8 +++++ 2 files changed, 96 insertions(+), 0 deletions(-) diff --git a/memory_mapping.c b/memory_mapping.c index 718f271..f74c5d0 100644 --- a/memory_mapping.c +++ b/memory_mapping.c @@ -164,3 +164,91 @@ 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, m_length; + target_phys_addr_t m_phys_addr; + int ret; + bool paging_mode; + +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING) + paging_mode = cpu_paging_enabled(first_cpu); + if (paging_mode) { + 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 in the memory mapping's list: + * 1. the guest doesn't use paging + * 2. the guest is in 2nd kernel, and the memory used by 1st kernel is not + * in paging table + * add them into memory mapping's list + */ + QLIST_FOREACH(block, &ram_list.blocks, next) { + offset = block->offset; + length = block->length; + + if (!paging_mode) { + create_new_memory_mapping(list, offset, offset, length); + continue; + } + + QTAILQ_FOREACH(memory_mapping, &list->head, next) { + m_phys_addr = memory_mapping->phys_addr; + m_length = memory_mapping->length; + + if (offset + length <= m_phys_addr) { + /* + * memory_mapping's list does not conatin the region + * [offset, offset+length) + */ + create_new_memory_mapping(list, offset, 0, length); + length = 0; + break; + } + + if (m_phys_addr + m_length <= offset) { + continue; + } + + if (m_phys_addr > offset) { + /* + * memory_mapping's list does not conatin the region + * [offset, memory_mapping->phys_addr) + */ + create_new_memory_mapping(list, offset, 0, + m_phys_addr - offset); + } + + if (offset + length <= m_phys_addr + m_length) { + length = 0; + break; + } + + length -= m_phys_addr + m_length - offset; + offset = m_phys_addr + m_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 836b047..ebd7cf6 100644 --- a/memory_mapping.h +++ b/memory_mapping.h @@ -44,4 +44,12 @@ 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 -- 1.7.1