From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mailman by lists.gnu.org with tmda-scanned (Exim 4.43) id 1LoIc6-0008GP-KP for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:22 -0400 Received: from exim by lists.gnu.org with spam-scanned (Exim 4.43) id 1LoIc1-00088m-Pc for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:22 -0400 Received: from [199.232.76.173] (port=54222 helo=monty-python.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1LoIc1-00088V-JS for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:17 -0400 Received: from mel.act-europe.fr ([212.99.106.210]:60592) by monty-python.gnu.org with esmtp (Exim 4.60) (envelope-from ) id 1LoIc0-0000x9-PH for qemu-devel@nongnu.org; Mon, 30 Mar 2009 10:37:17 -0400 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id C48BA290007 for ; Mon, 30 Mar 2009 16:36:35 +0200 (CEST) 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 WdgyiBmRDwlZ for ; Mon, 30 Mar 2009 16:36:35 +0200 (CEST) Received: from ulanbator.act-europe.fr (ulanbator.act-europe.fr [10.10.1.67]) by mel.act-europe.fr (Postfix) with ESMTP id 03639290037 for ; Mon, 30 Mar 2009 16:36:35 +0200 (CEST) From: Tristan Gingold Date: Mon, 30 Mar 2009 16:36:16 +0200 Message-Id: <1238423794-25455-2-git-send-email-gingold@adacore.com> In-Reply-To: <1238423794-25455-1-git-send-email-gingold@adacore.com> References: <1238423794-25455-1-git-send-email-gingold@adacore.com> Subject: [Qemu-devel] [PATCH 01/19] 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, 26 insertions(+), 24 deletions(-) diff --git a/exec.c b/exec.c index df22c79..4b2ebc2 100644 --- a/exec.c +++ b/exec.c @@ -147,15 +147,14 @@ 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) + +#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 (32 - L2_BITS - TARGET_PAGE_BITS) +#define L1_BITS L1_BITS_ #endif +#define L1_SHIFT (TARGET_PHYS_ADDR_SPACE_BITS - TARGET_PAGE_BITS - L1_BITS) #define L1_SIZE (1 << L1_BITS) #define L2_SIZE (1 << L2_BITS) @@ -165,7 +164,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; @@ -338,25 +339,26 @@ static PhysPageDesc *phys_page_find_alloc(target_phys_addr_t index, int alloc) { void **lp, **p; PhysPageDesc *pd; + int i; + /* 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 - lp = p + ((index >> (L1_BITS + L2_BITS)) & (L1_SIZE - 1)); - p = *lp; - if (!p) { - /* allocate if not found */ - if (!alloc) - return NULL; - p = qemu_vmalloc(sizeof(void *) * L1_SIZE); - memset(p, 0, sizeof(void *) * L1_SIZE); - *lp = p; + /* 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)); } -#endif - lp = p + ((index >> L2_BITS) & (L1_SIZE - 1)); + pd = *lp; if (!pd) { int i; -- 1.6.2