From patchwork Tue Jun 5 17:24:40 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Luiz Capitulino X-Patchwork-Id: 163109 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 894B6B6F62 for ; Wed, 6 Jun 2012 03:25:27 +1000 (EST) Received: from localhost ([::1]:33413 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SbxVV-0001SV-A4 for incoming@patchwork.ozlabs.org; Tue, 05 Jun 2012 13:25:25 -0400 Received: from eggs.gnu.org ([208.118.235.92]:54102) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SbxV7-0001Eo-R9 for qemu-devel@nongnu.org; Tue, 05 Jun 2012 13:25:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1SbxV2-0000qN-Ln for qemu-devel@nongnu.org; Tue, 05 Jun 2012 13:25:01 -0400 Received: from mx1.redhat.com ([209.132.183.28]:61660) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1SbxV2-0000qF-D0 for qemu-devel@nongnu.org; Tue, 05 Jun 2012 13:24:56 -0400 Received: from int-mx01.intmail.prod.int.phx2.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id q55HOqvs014275 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Tue, 5 Jun 2012 13:24:52 -0400 Received: from localhost (ovpn-116-79.ams2.redhat.com [10.36.116.79]) by int-mx01.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id q55HOoKN015826; Tue, 5 Jun 2012 13:24:51 -0400 From: Luiz Capitulino To: qemu-devel@nongnu.org Date: Tue, 5 Jun 2012 14:24:40 -0300 Message-Id: <1338917108-3965-2-git-send-email-lcapitulino@redhat.com> In-Reply-To: <1338917108-3965-1-git-send-email-lcapitulino@redhat.com> References: <1338917108-3965-1-git-send-email-lcapitulino@redhat.com> X-Scanned-By: MIMEDefang 2.67 on 10.5.11.11 X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 209.132.183.28 Cc: aliguori@us.ibm.com Subject: [Qemu-devel] [PATCH 01/29] Add API to create memory mapping list X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org From: Wen Congyang 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 Signed-off-by: Luiz Capitulino --- 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 + * + * 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 + * + * 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