From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Li8GT-0006iQ-K3 for qemu-devel@nongnu.org; Fri, 13 Mar 2009 10:21:33 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Li8GN-0006cj-VI for qemu-devel@nongnu.org; Fri, 13 Mar 2009 10:21:31 -0400 Received: from [199.232.76.173] (port=50641 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Li8GN-0006bz-5g for qemu-devel@nongnu.org; Fri, 13 Mar 2009 10:21:27 -0400 Received: from mel.act-europe.fr ([212.99.106.210]:53486) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Li8GM-0002Rk-KJ for qemu-devel@nongnu.org; Fri, 13 Mar 2009 10:21:26 -0400 From: Tristan Gingold Date: Fri, 13 Mar 2009 15:20:20 +0100 Message-Id: <1236954043-91856-2-git-send-email-gingold@adacore.com> In-Reply-To: <1236954043-91856-1-git-send-email-gingold@adacore.com> References: <1236954043-91856-1-git-send-email-gingold@adacore.com> Subject: [Qemu-devel] [PATCH 01/24] Add support for multi-level phys map. Reply-To: qemu-devel@nongnu.org List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: Tristan Gingold As Alpha physical addresses are 44 bits, l1_phys_map can't be anymore 2 levels. Use a more generic multi-level approach and explain why we don't need to extend l1_map. Signed-off-by: Tristan Gingold --- exec.c | 50 ++++++++++++++++++++++++++++++++++++++------------ 1 files changed, 38 insertions(+), 12 deletions(-) diff --git a/exec.c b/exec.c index abe37c3..fd3e441 100644 --- a/exec.c +++ b/exec.c @@ -150,14 +150,17 @@ typedef struct PhysPageDesc { } PhysPageDesc; #define L2_BITS 10 -#if defined(CONFIG_USER_ONLY) && defined(TARGET_VIRT_ADDR_SPACE_BITS) -/* XXX: this is a temporary hack for alpha target. - * In the future, this is to be replaced by a multi-level table - * to actually be able to handle the complete 64 bits address space. - */ -#define L1_BITS (TARGET_VIRT_ADDR_SPACE_BITS - L2_BITS - TARGET_PAGE_BITS) + +#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + 32 - L2_BITS - TARGET_PAGE_BITS) +# define MULTILEVEL_PHYS_MAP +# define L1_BITS_ ((TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS) % L2_BITS) +# if L1_BITS_ < 4 /* avoid ridiculous small l1 */ +# define L1_BITS (L1_BITS_ + L2_BITS) +# else +# define L1_BITS L1_BITS_ +# endif #else -#define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS) +# define L1_BITS (32 - L2_BITS - TARGET_PAGE_BITS) #endif #define L1_SIZE (1 << L1_BITS) @@ -168,7 +171,9 @@ unsigned long qemu_host_page_bits; unsigned long qemu_host_page_size; unsigned long qemu_host_page_mask; -/* XXX: for system emulation, it could just be an array */ +/* XXX: for system emulation, it could just be an array. As this is currently + a two level map this limits the size of RAM memory that can contains + target code. In practice this is large enough (>= 4GB) */ static PageDesc *l1_map[L1_SIZE]; static PhysPageDesc **l1_phys_map; @@ -342,12 +347,31 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc) void **lp, **p; PhysPageDesc *pd; +#ifdef MULTILEVEL_PHYS_MAP + int i; +#define L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - L1_BITS) + + /* Level 1. */ + p = (void **)l1_phys_map; + lp = p + ((index >> L1_SHIFT) & (L1_SIZE - 1)); + + /* Level 2..n-1 */ + for (i = (L1_SHIFT / L2_BITS) - 1; i > 0; i--) { + p = *lp; + if (!p) { + /* allocate if not found */ + if (!alloc) + return NULL; + p = qemu_vmalloc(sizeof(void *) * L2_SIZE); + memset(p, 0, sizeof(void *) * L2_SIZE); + *lp = p; + } + lp = p + ((index >> (i * L2_BITS)) & (L2_SIZE - 1)); + } +#else p = (void **)l1_phys_map; -#if TARGET_PHYS_ADDR_SPACE_BITS > 32 -#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS) -#error unsupported TARGET_PHYS_ADDR_SPACE_BITS -#endif +#if TARGET_PHYS_ADDR_SPACE_BITS > 32 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1)); p = *lp; if (!p) { @@ -360,6 +384,8 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc) } #endif lp = p + ((index >> L2_BITS) & (L1_SIZE - 1)); +#endif + pd = *lp; if (!pd) { int i; -- 1.6.2