From patchwork Tue Jul 24 01:09:25 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Cyril Chemparathy X-Patchwork-Id: 1415621 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork2.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork2.kernel.org (Postfix) with ESMTP id 0DDB6DFFCF for ; Thu, 6 Sep 2012 15:07:42 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1T9dZz-0004hV-O3; Thu, 06 Sep 2012 15:01:17 +0000 Received: from casper.infradead.org ([2001:770:15f::2]) by merlin.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1StTzu-0003ji-Gj for linux-arm-kernel@merlin.infradead.org; Tue, 24 Jul 2012 01:33:14 +0000 Received: from arroyo.ext.ti.com ([192.94.94.40]) by casper.infradead.org with esmtps (Exim 4.76 #1 (Red Hat Linux)) id 1StTdD-000732-BE for linux-arm-kernel@lists.infradead.org; Tue, 24 Jul 2012 01:09:50 +0000 Received: from dlelxv30.itg.ti.com ([172.17.2.17]) by arroyo.ext.ti.com (8.13.7/8.13.7) with ESMTP id q6O19enL011179; Mon, 23 Jul 2012 20:09:40 -0500 Received: from DLEE74.ent.ti.com (dlee74.ent.ti.com [157.170.170.8]) by dlelxv30.itg.ti.com (8.13.8/8.13.8) with ESMTP id q6O19eLI010292; Mon, 23 Jul 2012 20:09:40 -0500 Received: from dlelxv22.itg.ti.com (172.17.1.197) by DLEE74.ent.ti.com (157.170.170.8) with Microsoft SMTP Server id 14.1.323.3; Mon, 23 Jul 2012 20:09:40 -0500 Received: from ares-ubuntu.am.dhcp.ti.com (ares-ubuntu.am.dhcp.ti.com [158.218.103.17]) by dlelxv22.itg.ti.com (8.13.8/8.13.8) with ESMTP id q6O19e3t024623; Mon, 23 Jul 2012 20:09:40 -0500 Received: from a0875269 by ares-ubuntu.am.dhcp.ti.com with local (Exim 4.76) (envelope-from ) id 1StTd6-0002Ux-8F; Mon, 23 Jul 2012 21:09:40 -0400 From: Cyril Chemparathy To: Subject: [RFC 23/23] ARM: keystone: add switch over to high physical address range Date: Mon, 23 Jul 2012 21:09:25 -0400 Message-ID: <1343092165-9470-24-git-send-email-cyril@ti.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1343092165-9470-1-git-send-email-cyril@ti.com> References: <1343092165-9470-1-git-send-email-cyril@ti.com> MIME-Version: 1.0 X-Bad-Reply: References and In-Reply-To but no 'Re:' in Subject. X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20120724_020947_835265_C292DFD8 X-CRM114-Status: GOOD ( 26.58 ) X-Spam-Score: -6.9 (------) X-Spam-Report: SpamAssassin version 3.3.2 on casper.infradead.org summary: Content analysis details: (-6.9 points, 5.0 required) pts rule name description ---- ---------------------- -------------------------------------------------- -5.0 RCVD_IN_DNSWL_HI RBL: Sender listed at http://www.dnswl.org/, high trust [192.94.94.40 listed in list.dnswl.org] -0.0 T_RP_MATCHES_RCVD Envelope sender domain matches handover relay domain -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] X-Mailman-Approved-At: Thu, 06 Sep 2012 10:43:38 -0400 Cc: nico@linaro.org, catalin.marinas@arm.com, will.deacon@arm.com, linux-kernel@vger.kernel.org, Vitaly Andrianov , Cyril Chemparathy X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org Keystone platforms have their physical memory mapped at an address outside the 32-bit physical range. A Keystone machine with 16G of RAM would find its memory at 0x0800000000 - 0x0bffffffff. For boot purposes, the interconnect supports a limited alias of some of this memory within the 32-bit addressable space (0x80000000 - 0xffffffff). This aliasing is implemented in hardware, and is not intended to be used much beyond boot. For instance, DMA coherence does not work when running out of this aliased address space. Therefore, we've taken the approach of booting out of the low physical address range, and subsequently we switch over to the high range once we're safely inside machine specific territory. This patch implements this switch over mechanism, which involves rewiring the TTBRs and page tables to point to the new physical address space. Signed-off-by: Vitaly Andrianov Signed-off-by: Cyril Chemparathy --- arch/arm/Kconfig | 1 + arch/arm/boot/dts/keystone-sim.dts | 6 +- arch/arm/configs/keystone_defconfig | 1 + arch/arm/mach-keystone/include/mach/memory.h | 29 ++++++++ arch/arm/mach-keystone/keystone.c | 92 ++++++++++++++++++++++++++ arch/arm/mach-keystone/platsmp.c | 21 ++++++ 6 files changed, 147 insertions(+), 3 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 5b82879..f970ee1 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -373,6 +373,7 @@ config ARCH_KEYSTONE select NEED_MACH_MEMORY_H select HAVE_SCHED_CLOCK select HAVE_SMP + select ZONE_DMA if ARM_LPAE help Support for boards based on the Texas Instruments Keystone family of SoCs. diff --git a/arch/arm/boot/dts/keystone-sim.dts b/arch/arm/boot/dts/keystone-sim.dts index 118d631..afdef89 100644 --- a/arch/arm/boot/dts/keystone-sim.dts +++ b/arch/arm/boot/dts/keystone-sim.dts @@ -4,7 +4,7 @@ / { model = "Texas Instruments Keystone 2 SoC"; compatible = "ti,keystone-evm"; - #address-cells = <1>; + #address-cells = <2>; #size-cells = <1>; interrupt-parent = <&gic>; @@ -13,11 +13,11 @@ }; chosen { - bootargs = "console=ttyS0,115200n8 debug earlyprintk lpj=50000 rdinit=/bin/ash rw root=/dev/ram0 initrd=0x85000000,9M"; + bootargs = "console=ttyS0,115200n8 debug earlyprintk lpj=50000 rdinit=/bin/ash rw root=/dev/ram0 initrd=0x805000000,9M"; }; memory { - reg = <0x80000000 0x8000000>; + reg = <0x00000008 0x00000000 0x8000000>; }; cpus { diff --git a/arch/arm/configs/keystone_defconfig b/arch/arm/configs/keystone_defconfig index 5f71e66..8ea3b96 100644 --- a/arch/arm/configs/keystone_defconfig +++ b/arch/arm/configs/keystone_defconfig @@ -1,6 +1,7 @@ CONFIG_EXPERIMENTAL=y CONFIG_BLK_DEV_INITRD=y CONFIG_ARCH_KEYSTONE=y +CONFIG_ARM_LPAE=y CONFIG_SMP=y CONFIG_ARM_ARCH_TIMER=y CONFIG_NR_CPUS=4 diff --git a/arch/arm/mach-keystone/include/mach/memory.h b/arch/arm/mach-keystone/include/mach/memory.h index 7c78b1e..6404633 100644 --- a/arch/arm/mach-keystone/include/mach/memory.h +++ b/arch/arm/mach-keystone/include/mach/memory.h @@ -19,4 +19,33 @@ #define MAX_PHYSMEM_BITS 36 #define SECTION_SIZE_BITS 34 +#define KEYSTONE_LOW_PHYS_START 0x80000000ULL +#define KEYSTONE_LOW_PHYS_SIZE 0x80000000ULL /* 2G */ +#define KEYSTONE_LOW_PHYS_END (KEYSTONE_LOW_PHYS_START + \ + KEYSTONE_LOW_PHYS_SIZE - 1) + +#define KEYSTONE_HIGH_PHYS_START 0x800000000ULL +#define KEYSTONE_HIGH_PHYS_SIZE 0x400000000ULL /* 16G */ +#define KEYSTONE_HIGH_PHYS_END (KEYSTONE_HIGH_PHYS_START + \ + KEYSTONE_HIGH_PHYS_SIZE - 1) +#ifdef CONFIG_ARM_LPAE + +#ifndef __ASSEMBLY__ + +extern phys_addr_t keystone_phys_offset; + +#define PLAT_PHYS_OFFSET keystone_phys_offset + +static inline phys_addr_t __virt_to_idmap(unsigned long x) +{ + return (phys_addr_t)(x) - CONFIG_PAGE_OFFSET + + KEYSTONE_LOW_PHYS_START; +} + +#define virt_to_idmap(x) __virt_to_idmap((unsigned long)(x)) + +#endif /* __ASSEMBLY__ */ + +#endif /* CONFIG_ARM_LPAE */ + #endif /* __ASM_MACH_MEMORY_H */ diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c index 650e202..f0f4a08 100644 --- a/arch/arm/mach-keystone/keystone.c +++ b/arch/arm/mach-keystone/keystone.c @@ -19,12 +19,20 @@ #include #include #include +#include #include #include #include #include #include +#include +#include +#include +#include +#include +#include +#include extern struct smp_ops keystone_smp_ops; @@ -74,6 +82,86 @@ static const char *keystone_match[] __initconst = { NULL, }; +#ifdef CONFIG_ARM_LPAE + +phys_addr_t keystone_phys_offset = KEYSTONE_LOW_PHYS_START; + +extern struct proc_info_list *lookup_processor_type(unsigned int); + +static void __init keystone_init_meminfo(void) +{ + unsigned long map_start, map_end; + struct proc_info_list *procinfo; + phys_addr_t mem_start, mem_end; + pgd_t *pgd0, *pgdk; + pud_t *pud0, *pudk; + pmd_t *pmd0, *pmdk; + phys_addr_t phys; + pmdval_t pmdprot; + int i; + + BUG_ON(meminfo.nr_banks < 1); + + mem_start = meminfo.bank[0].start; + mem_end = mem_start + meminfo.bank[0].size - 1; + + /* nothing to do if we are running out of the <32-bit space */ + if (mem_start >= KEYSTONE_LOW_PHYS_START && + mem_end <= KEYSTONE_LOW_PHYS_END) + return; + + BUG_ON(mem_start < KEYSTONE_HIGH_PHYS_START || + mem_end > KEYSTONE_HIGH_PHYS_END); + + /* remap kernel code and data */ + map_start = init_mm.start_code; + map_end = init_mm.brk; + + /* get a handle on things - */ + pgd0 = pgd_offset_k(0); + pud0 = pud_offset(pgd0, 0); + pmd0 = pmd_offset(pud0, 0); + + pgdk = pgd_offset_k(map_start); + pudk = pud_offset(pgdk, map_start); + pmdk = pmd_offset(pudk, map_start); + + procinfo = lookup_processor_type(read_cpuid_id()); + pmdprot = procinfo->__cpu_mm_mmu_flags; + + /* set the phys offset, all pa/va operations now use this */ + keystone_phys_offset = KEYSTONE_HIGH_PHYS_START; + + /* remap level 1 table */ + for (i = 0; i < PTRS_PER_PGD; i++) { + *pud0++ = __pud(__pa(pmd0) | PMD_TYPE_TABLE | L_PGD_SWAPPER); + pmd0 += PTRS_PER_PMD; + } + + /* remap pmds for kernel mapping */ + phys = __pa(map_start) & PMD_MASK; + do { + *pmdk++ = __pmd(phys | pmdprot); + phys += PMD_SIZE; + } while (phys < map_end); + + flush_cache_all(); + cpu_set_ttbr(0, __pa(pgd0)); + cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET); + local_flush_tlb_all(); + + pr_err("relocated to high address space\n"); +} + +#else + +static void __init keystone_init_meminfo(void) +{ + /* nothing to do here */ +} + +#endif + DT_MACHINE_START(KEYSTONE, "Keystone") smp_ops(keystone_smp_ops) .map_io = keystone_map_io, @@ -82,5 +170,9 @@ DT_MACHINE_START(KEYSTONE, "Keystone") .handle_irq = gic_handle_irq, .init_machine = keystone_init, .dt_compat = keystone_match, + .init_meminfo = keystone_init_meminfo, +#ifdef CONFIG_ZONE_DMA + .dma_zone_size = SZ_2G, +#endif .nr_irqs = 480, MACHINE_END diff --git a/arch/arm/mach-keystone/platsmp.c b/arch/arm/mach-keystone/platsmp.c index 437659a..074fccb 100644 --- a/arch/arm/mach-keystone/platsmp.c +++ b/arch/arm/mach-keystone/platsmp.c @@ -24,6 +24,7 @@ #include #include #include +#include #include extern void secondary_startup(void); @@ -51,15 +52,35 @@ static void __init keystone_smp_prepare_cpus(unsigned int max_cpus) /* nothing for now */ } +#ifdef CONFIG_ARM_LPAE +static void __cpuinit keystone_secondary_initmem(void) +{ + pgd_t *pgd0; + + pgd0 = pgd_offset_k(0); + cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET); + local_flush_tlb_all(); +} +#else +static void __cpuinit keystone_secondary_initmem(void) +{ +} +#endif + static void __cpuinit keystone_secondary_init(unsigned int cpu) { gic_secondary_init(0); + keystone_secondary_initmem(); } static int __cpuinit keystone_boot_secondary(unsigned int cpu, struct task_struct *idle) { +#ifdef CONFIG_ARM_LPAE + unsigned long *jump_ptr = phys_to_virt(0x8000001f0); +#else unsigned long *jump_ptr = phys_to_virt(0x800001f0); +#endif jump_ptr[cpu] = virt_to_idmap(&secondary_startup); __cpuc_flush_dcache_area(jump_ptr, sizeof(jump_ptr) * 4);