From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1Lm8rw-0002sE-PS for qemu-devel@nongnu.org; Tue, 24 Mar 2009 11:48:48 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1Lm8re-0002gW-Rf for qemu-devel@nongnu.org; Tue, 24 Mar 2009 11:48:37 -0400 Received: from [199.232.76.173] (port=33132 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Lm8re-0002gJ-A5 for qemu-devel@nongnu.org; Tue, 24 Mar 2009 11:48:30 -0400 Received: from mel.act-europe.fr ([212.99.106.210]:52807) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1Lm8rd-0003ch-PJ for qemu-devel@nongnu.org; Tue, 24 Mar 2009 11:48:30 -0400 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 3E34C290056 for ; Tue, 24 Mar 2009 16:48:07 +0100 (CET) Received: from mel.act-europe.fr ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id 1qbmGfJZD7e6 for ; Tue, 24 Mar 2009 16:48:07 +0100 (CET) Received: from ulanbator.act-europe.fr (ulanbator.act-europe.fr [10.10.1.67]) by mel.act-europe.fr (Postfix) with ESMTP id 0F419290017 for ; Tue, 24 Mar 2009 16:48:07 +0100 (CET) From: Tristan Gingold Date: Tue, 24 Mar 2009 16:47:43 +0100 Message-Id: <1237909687-31711-2-git-send-email-gingold@adacore.com> In-Reply-To: <1237909687-31711-1-git-send-email-gingold@adacore.com> References: <1237909687-31711-1-git-send-email-gingold@adacore.com> Subject: [Qemu-devel] [PATCH 01/25] 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 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 e869a20..4330003 100644 --- a/exec.c +++ b/exec.c @@ -147,14 +147,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) @@ -165,7 +168,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; @@ -339,12 +344,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; -#if TARGET_PHYS_ADDR_SPACE_BITS > 32 + lp = p + ((index >> L1_SHIFT) & (L1_SIZE - 1)); -#if TARGET_PHYS_ADDR_SPACE_BITS > (32 + L1_BITS) -#error unsupported TARGET_PHYS_ADDR_SPACE_BITS -#endif + /* 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 lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1)); p = *lp; if (!p) { @@ -357,6 +381,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