From patchwork Thu Jul 31 11:01:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ian Campbell X-Patchwork-Id: 34578 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pa0-f72.google.com (mail-pa0-f72.google.com [209.85.220.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 3CE8920540 for ; Thu, 31 Jul 2014 11:03:45 +0000 (UTC) Received: by mail-pa0-f72.google.com with SMTP id eu11sf16534798pac.3 for ; Thu, 31 Jul 2014 04:03:44 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:message-id:from:to:date:in-reply-to :references:mime-version:cc:subject:precedence:list-id :list-unsubscribe:list-post:list-help:list-subscribe:sender :errors-to:x-original-sender:x-original-authentication-results :mailing-list:list-archive:content-type:content-transfer-encoding; bh=LUqWSWY6j4OHLmEKlToXd1G6MI7DhXPNStvzX6eSIWE=; b=B+a/FgrSa7zhSmb/3Yl3BDnUcl7ciV0AHfGQwT2WdtAPb4cjcNkapALxHeO0ixAGco hsDhqjVNMR8QklPXeS4c1AVI5yFkcntUgLKhvhZAHuOOiR1mjZjaHSCW/uMrqD8NlOYY If51oYRmplayEvynRB8vq1xuoAGi96iW+Q4pbVT3gzWdPiZu4NDglNuQ2qOkn/ZyPp5D 7uYkk4FKoxZ8Xfr/lK0T6hWIhdR6rOWQ86e/3PjttPBRRbA8wHx+csEt97CUMrImMrRV 2vbUoYJag7evgz9P82psoO3kbqM+9/PP4OSEFIeBt7yuhZ91xUhZAifkBBIerxLB7HqE Ie+g== X-Gm-Message-State: ALoCoQkPic8KexMYVHY7BwrV3bNAHQ8pcMfyeuTRcPNpb37rrb/OarliJypSEp6q8taEZatK6qfI X-Received: by 10.70.24.163 with SMTP id v3mr4352102pdf.8.1406804624543; Thu, 31 Jul 2014 04:03:44 -0700 (PDT) X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.93.101 with SMTP id c92ls890789qge.90.gmail; Thu, 31 Jul 2014 04:03:44 -0700 (PDT) X-Received: by 10.221.41.135 with SMTP id tu7mr9797874vcb.70.1406804624410; Thu, 31 Jul 2014 04:03:44 -0700 (PDT) Received: from mail-vc0-f175.google.com (mail-vc0-f175.google.com [209.85.220.175]) by mx.google.com with ESMTPS id kd5si4048065veb.67.2014.07.31.04.03.44 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 31 Jul 2014 04:03:44 -0700 (PDT) Received-SPF: pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.175 as permitted sender) client-ip=209.85.220.175; Received: by mail-vc0-f175.google.com with SMTP id ik5so3833411vcb.20 for ; Thu, 31 Jul 2014 04:03:44 -0700 (PDT) X-Received: by 10.220.118.136 with SMTP id v8mr11607009vcq.50.1406804624226; Thu, 31 Jul 2014 04:03:44 -0700 (PDT) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patch@linaro.org Received: by 10.221.37.5 with SMTP id tc5csp8910vcb; Thu, 31 Jul 2014 04:03:43 -0700 (PDT) X-Received: by 10.43.98.68 with SMTP id cn4mr14463604icc.40.1406804623634; Thu, 31 Jul 2014 04:03:43 -0700 (PDT) Received: from lists.xen.org (lists.xen.org. [50.57.142.19]) by mx.google.com with ESMTPS id o7si13328942icu.68.2014.07.31.04.03.43 for (version=TLSv1 cipher=RC4-SHA bits=128/128); Thu, 31 Jul 2014 04:03:43 -0700 (PDT) Received-SPF: none (google.com: xen-devel-bounces@lists.xen.org does not designate permitted sender hosts) client-ip=50.57.142.19; Received: from localhost ([127.0.0.1] helo=lists.xen.org) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1XCo7B-0002RT-Ew; Thu, 31 Jul 2014 11:01:41 +0000 Message-Id: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xen.org with esmtp (Exim 4.72) (envelope-from ) id 1XCo79-0002Qn-Ml for xen-devel@lists.xen.org; Thu, 31 Jul 2014 11:01:39 +0000 Received: from [85.158.139.211:64874] by server-16.bemta-5.messagelabs.com id 79/7D-01029-3122AD35; Thu, 31 Jul 2014 11:01:39 +0000 X-Env-Sender: Ian.Campbell@citrix.com X-Msg-Ref: server-4.tower-206.messagelabs.com!1406804496!11100942!2 X-Originating-IP: [66.165.176.63] X-SpamReason: No, hits=2.0 required=7.0 tests=msgid: No Message-ID, sa_preprocessor: VHJ1c3RlZCBJUDogNjYuMTY1LjE3Ni42MyA9PiAzMDYwNDg=\n X-StarScan-Received: X-StarScan-Version: 6.11.3; banners=-,-,- X-VirusChecked: Checked Received: (qmail 12271 invoked from network); 31 Jul 2014 11:01:38 -0000 Received: from smtp02.citrix.com (HELO SMTP02.CITRIX.COM) (66.165.176.63) by server-4.tower-206.messagelabs.com with RC4-SHA encrypted SMTP; 31 Jul 2014 11:01:38 -0000 X-IronPort-AV: E=Sophos;i="5.01,771,1400025600"; d="scan'208";a="158035965" Received: from ukmail1.uk.xensource.com (10.80.16.128) by smtprelay.citrix.com (10.13.107.80) with Microsoft SMTP Server id 14.3.181.6; Thu, 31 Jul 2014 07:01:36 -0400 Received: from drall.uk.xensource.com ([10.80.16.71]) by ukmail1.uk.xensource.com with smtp (Exim 4.69) (envelope-from ) id 1XCo74-0004QY-QR; Thu, 31 Jul 2014 12:01:35 +0100 Received: by drall.uk.xensource.com (sSMTP sendmail emulation); Thu, 31 Jul 2014 12:01:34 +0100 From: Ian Campbell To: Date: Thu, 31 Jul 2014 12:01:33 +0100 X-Mailer: git-send-email 1.7.10.4 In-Reply-To: References: MIME-Version: 1.0 X-DLP: MIA2 Cc: Ian Campbell , stefano.stabellini@eu.citrix.com, julien.grall@linaro.org, tim@xen.org, Roy Franz , Jan Beulich , Fu Wei Subject: [Xen-devel] [PATCH RFC 2/2] xen: arm: Enable physical address space compression (PDX) on arm64 X-BeenThere: xen-devel@lists.xen.org X-Mailman-Version: 2.1.13 Precedence: list List-Id: List-Unsubscribe: , List-Post: , List-Help: , List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: ian.campbell@citrix.com X-Original-Authentication-Results: mx.google.com; spf=pass (google.com: domain of patch+caf_=patchwork-forward=linaro.org@linaro.org designates 209.85.220.175 as permitted sender) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org X-Google-Group-Id: 836684582541 List-Archive: This allows us to support sparse physical address maps which we previously could not because the frametable would end up taking up an enourmous fraction of RAM. On a fast model which has RAM at 0x80000000-0x100000000 and 0x880000000-0x900000000 this reduces the size of the frametable from 478M to 84M. This is very much a WIP. Things left to do: - Make it work for arm32 (completely broken) - Should xenheap_mfn_start/frametable_base_pdx be an (optional?) part of the common infra? - Sort out the semtantics of mfn/pdx vs frame table base, I suspect these are a bit confused right now... - Probably lots of bugs... Posting because I'm going to be away but it will hopefully be useful for the UEFI and grub+multiboot work being done by Linaro. Signed-off-by: Ian Campbell --- xen/arch/arm/Rules.mk | 1 + xen/arch/arm/mm.c | 18 +++++++------ xen/arch/arm/setup.c | 58 ++++++++++++++++++++++++++++++++---------- xen/include/asm-arm/config.h | 4 ++- xen/include/asm-arm/mm.h | 31 +++++++++++----------- xen/include/asm-arm/numa.h | 2 +- 6 files changed, 76 insertions(+), 38 deletions(-) diff --git a/xen/arch/arm/Rules.mk b/xen/arch/arm/Rules.mk index 8658176..26fafa2 100644 --- a/xen/arch/arm/Rules.mk +++ b/xen/arch/arm/Rules.mk @@ -10,6 +10,7 @@ HAS_DEVICE_TREE := y HAS_VIDEO := y HAS_ARM_HDLCD := y HAS_PASSTHROUGH := y +HAS_PDX := y CFLAGS += -I$(BASEDIR)/include diff --git a/xen/arch/arm/mm.c b/xen/arch/arm/mm.c index fa6a729..bc399c0 100644 --- a/xen/arch/arm/mm.c +++ b/xen/arch/arm/mm.c @@ -140,7 +140,7 @@ unsigned long xenheap_mfn_start __read_mostly = ~0UL; unsigned long xenheap_mfn_end __read_mostly; unsigned long xenheap_virt_end __read_mostly; -unsigned long frametable_base_mfn __read_mostly; +unsigned long frametable_base_pdx __read_mostly; unsigned long frametable_virt_end __read_mostly; unsigned long max_page; @@ -683,7 +683,7 @@ void __init setup_xenheap_mappings(unsigned long base_mfn, /* Align to previous 1GB boundary */ base_mfn &= ~((FIRST_SIZE>>PAGE_SHIFT)-1); - offset = base_mfn - xenheap_mfn_start; + offset = pfn_to_pdx(base_mfn - xenheap_mfn_start); vaddr = DIRECTMAP_VIRT_START + offset*PAGE_SIZE; while ( base_mfn < end_mfn ) @@ -734,7 +734,8 @@ void __init setup_xenheap_mappings(unsigned long base_mfn, void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) { unsigned long nr_pages = (pe - ps) >> PAGE_SHIFT; - unsigned long frametable_size = nr_pages * sizeof(struct page_info); + unsigned long nr_pdxs = pfn_to_pdx(nr_pages); + unsigned long frametable_size = nr_pdxs * sizeof(struct page_info); unsigned long base_mfn; #ifdef CONFIG_ARM_64 lpae_t *second, pte; @@ -742,7 +743,7 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) int i; #endif - frametable_base_mfn = ps >> PAGE_SHIFT; + frametable_base_pdx = pfn_to_pdx(ps >> PAGE_SHIFT); /* Round up to 32M boundary */ frametable_size = (frametable_size + 0x1ffffff) & ~0x1ffffff; @@ -763,11 +764,12 @@ void __init setup_frametable_mappings(paddr_t ps, paddr_t pe) create_32mb_mappings(xen_second, FRAMETABLE_VIRT_START, base_mfn, frametable_size >> PAGE_SHIFT); #endif - memset(&frame_table[0], 0, nr_pages * sizeof(struct page_info)); - memset(&frame_table[nr_pages], -1, - frametable_size - (nr_pages * sizeof(struct page_info))); + memset(&frame_table[0], 0, nr_pdxs * sizeof(struct page_info)); + memset(&frame_table[nr_pdxs], -1, + frametable_size - (nr_pdxs * sizeof(struct page_info))); + + frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pdxs * sizeof(struct page_info)); - frametable_virt_end = FRAMETABLE_VIRT_START + (nr_pages * sizeof(struct page_info)); } void *__init arch_vmap_virt_end(void) diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c index 446b4dc..dbd92bb 100644 --- a/xen/arch/arm/setup.c +++ b/xen/arch/arm/setup.c @@ -423,6 +423,46 @@ static paddr_t __init get_xen_paddr(void) return paddr; } +/* Sets all bits from the most-significant 1-bit down to the LSB */ +static u64 __init fill_mask(u64 mask) +{ + while (mask & (mask + 1)) + mask |= mask + 1; + return mask; +} + +static void init_pdx(void) +{ + u64 mask = fill_mask(bootinfo.mem.bank[0].start - 1); + int bank; + + for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ ) + { + paddr_t bank_start = bootinfo.mem.bank[bank].start; + paddr_t bank_size = bootinfo.mem.bank[bank].size; + paddr_t bank_end = bank_start + bank_size; + + set_pdx_range(paddr_to_pfn(bank_start), + paddr_to_pfn(bank_end)); + + + mask |= bank_start | fill_mask(bank_start ^ (bank_end - 1)); + } + + for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ ) + { + paddr_t bank_start = bootinfo.mem.bank[bank].start; + paddr_t bank_size = bootinfo.mem.bank[bank].size; + paddr_t bank_end = bank_start + bank_size; + + if (~mask & + fill_mask(bank_start ^ (bank_end - 1))) + mask = 0; + } + + pfn_pdx_hole_setup(mask >> PAGE_SHIFT); +} + #ifdef CONFIG_ARM_32 static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) { @@ -439,6 +479,8 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) if ( !bootinfo.mem.nr_banks ) panic("No memory bank"); + init_pdx(); + /* * We are going to accumulate two regions here. * @@ -468,6 +510,7 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) paddr_t new_ram_start = min(ram_start,bank_start); paddr_t new_ram_end = max(ram_end,bank_end); +#error ARM32 not converted to PDX yet /* * If the new bank is contiguous with the initial contiguous * region then incorporate it into the contiguous region. @@ -616,6 +659,8 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) unsigned long dtb_pages; void *fdt; + init_pdx(); + total_pages = 0; for ( bank = 0 ; bank < bootinfo.mem.nr_banks; bank++ ) { @@ -628,19 +673,6 @@ static void __init setup_mm(unsigned long dtb_paddr, size_t dtb_size) paddr_t new_ram_start = min(ram_start,bank_start); paddr_t new_ram_end = max(ram_end,bank_end); - /* - * We allow non-contigious regions so long as at least half of - * the total RAM region actually contains RAM. We actually - * fudge this slightly and require that adding the current - * bank does not cause us to violate this restriction. - * - * This restriction ensures that the frametable (which is not - * currently sparse) does not consume all available RAM. - */ - if ( bank > 0 && 2 * new_ram_size < new_ram_end - new_ram_start ) - /* Would create memory map which is too sparse, so stop here. */ - break; - ram_start = new_ram_start; ram_end = new_ram_end; ram_size = new_ram_size; diff --git a/xen/include/asm-arm/config.h b/xen/include/asm-arm/config.h index 1c3abcf..e525c7f 100644 --- a/xen/include/asm-arm/config.h +++ b/xen/include/asm-arm/config.h @@ -149,7 +149,9 @@ #define VMAP_VIRT_END (VMAP_VIRT_START + GB(1) - 1) #define FRAMETABLE_VIRT_START GB(32) -#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + GB(32) - 1) +#define FRAMETABLE_SIZE GB(32) +#define FRAMETABLE_NR (FRAMETABLE_SIZE / sizeof(*frame_table)) +#define FRAMETABLE_VIRT_END (FRAMETABLE_VIRT_START + FRAMETABLE_SIZE - 1) #define DIRECTMAP_VIRT_START SLOT0(256) #define DIRECTMAP_SIZE (SLOT0_ENTRY_SIZE * (265-256)) diff --git a/xen/include/asm-arm/mm.h b/xen/include/asm-arm/mm.h index 9fa80a4..77901f7 100644 --- a/xen/include/asm-arm/mm.h +++ b/xen/include/asm-arm/mm.h @@ -6,6 +6,7 @@ #include #include #include +#include /* Align Xen to a 2 MiB boundary. */ #define XEN_PADDR_ALIGN (1 << 21) @@ -140,12 +141,14 @@ extern void share_xen_page_with_privileged_guests( struct page_info *page, int readonly); #define frame_table ((struct page_info *)FRAMETABLE_VIRT_START) -/* MFN of the first page in the frame table. */ -extern unsigned long frametable_base_mfn; +/* PDX of the first page in the frame table. */ +extern unsigned long frametable_base_pdx; extern unsigned long max_page; extern unsigned long total_pages; +#define PDX_GROUP_SHIFT SECOND_SHIFT + /* Boot-time pagetable setup */ extern void setup_pagetables(unsigned long boot_phys_offset, paddr_t xen_paddr); /* Remove early mappings */ @@ -184,20 +187,15 @@ static inline void __iomem *ioremap_wc(paddr_t start, size_t len) return ioremap_attr(start, len, PAGE_HYPERVISOR_WC); } +/* XXX -- account for base */ #define mfn_valid(mfn) ({ \ unsigned long __m_f_n = (mfn); \ - likely(__m_f_n >= frametable_base_mfn && __m_f_n < max_page); \ + likely(pfn_to_pdx(__m_f_n) >= frametable_base_pdx && __mfn_valid(__m_f_n)); \ }) -#define max_pdx max_page -#define pfn_to_pdx(pfn) (pfn) -#define pdx_to_pfn(pdx) (pdx) -#define virt_to_pdx(va) virt_to_mfn(va) -#define pdx_to_virt(pdx) mfn_to_virt(pdx) - /* Convert between machine frame numbers and page-info structures. */ -#define mfn_to_page(mfn) (frame_table + (pfn_to_pdx(mfn) - frametable_base_mfn)) -#define page_to_mfn(pg) pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_mfn) +#define mfn_to_page(mfn) (frame_table + (pfn_to_pdx(mfn) - frametable_base_pdx)) +#define page_to_mfn(pg) pdx_to_pfn((unsigned long)((pg) - frame_table) + frametable_base_pdx) #define __page_to_mfn(pg) page_to_mfn(pg) #define __mfn_to_page(mfn) mfn_to_page(mfn) @@ -221,6 +219,7 @@ static inline paddr_t __virt_to_maddr(vaddr_t va) #define virt_to_maddr(va) __virt_to_maddr((vaddr_t)(va)) #ifdef CONFIG_ARM_32 +#error ARM32 not converted to PDX yet static inline void *maddr_to_virt(paddr_t ma) { ASSERT(is_xen_heap_mfn(ma >> PAGE_SHIFT)); @@ -230,9 +229,11 @@ static inline void *maddr_to_virt(paddr_t ma) #else static inline void *maddr_to_virt(paddr_t ma) { - ASSERT((ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT)); - ma -= pfn_to_paddr(xenheap_mfn_start); - return (void *)(unsigned long) ma + DIRECTMAP_VIRT_START; + ASSERT(pfn_to_pdx(ma >> PAGE_SHIFT) < (DIRECTMAP_SIZE >> PAGE_SHIFT)); + return (void *)(DIRECTMAP_VIRT_START - + pfn_to_paddr(xenheap_mfn_start) + + ((ma & ma_va_bottom_mask) | + ((ma & ma_top_mask) >> pfn_pdx_hole_shift))); } #endif @@ -264,7 +265,7 @@ static inline struct page_info *virt_to_page(const void *v) return frame_table + ((va - XENHEAP_VIRT_START) >> PAGE_SHIFT) + xenheap_mfn_start - - frametable_base_mfn; + - frametable_base_pdx; } static inline void *page_to_virt(const struct page_info *pg) diff --git a/xen/include/asm-arm/numa.h b/xen/include/asm-arm/numa.h index 2c019d7..06a9d5a 100644 --- a/xen/include/asm-arm/numa.h +++ b/xen/include/asm-arm/numa.h @@ -12,7 +12,7 @@ static inline __attribute__((pure)) int phys_to_nid(paddr_t addr) /* XXX: implement NUMA support */ #define node_spanned_pages(nid) (total_pages) -#define node_start_pfn(nid) (frametable_base_mfn) +#define node_start_pfn(nid) (pdx_to_pfn(frametable_base_pdx)) #define __node_distance(a, b) (20) #endif /* __ARCH_ARM_NUMA_H */