From patchwork Mon Oct 7 19:34:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Santosh Shilimkar X-Patchwork-Id: 2998951 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B86CF9F245 for ; Mon, 7 Oct 2013 19:35:58 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 88F84201E7 for ; Mon, 7 Oct 2013 19:35:57 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D4F072011D for ; Mon, 7 Oct 2013 19:35:55 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VTGac-0004KG-Fq; Mon, 07 Oct 2013 19:35:34 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VTGaX-0007q1-Fu; Mon, 07 Oct 2013 19:35:29 +0000 Received: from bear.ext.ti.com ([192.94.94.41]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VTGaQ-0007oB-2a for linux-arm-kernel@lists.infradead.org; Mon, 07 Oct 2013 19:35:25 +0000 Received: from dflxv15.itg.ti.com ([128.247.5.124]) by bear.ext.ti.com (8.13.7/8.13.7) with ESMTP id r97JYhEW021750; Mon, 7 Oct 2013 14:34:43 -0500 Received: from DFLE72.ent.ti.com (dfle72.ent.ti.com [128.247.5.109]) by dflxv15.itg.ti.com (8.14.3/8.13.8) with ESMTP id r97JYhTo009006; Mon, 7 Oct 2013 14:34:43 -0500 Received: from dflp33.itg.ti.com (10.64.6.16) by DFLE72.ent.ti.com (128.247.5.109) with Microsoft SMTP Server id 14.2.342.3; Mon, 7 Oct 2013 14:34:43 -0500 Received: from [158.218.101.61] (ileax41-snat.itg.ti.com [10.172.224.153]) by dflp33.itg.ti.com (8.14.3/8.13.8) with ESMTP id r97JYfS5028918; Mon, 7 Oct 2013 14:34:41 -0500 Message-ID: <52530CD1.5010309@ti.com> Date: Mon, 7 Oct 2013 15:34:41 -0400 From: Santosh Shilimkar User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:17.0) Gecko/17.0 Thunderbird/17.0 MIME-Version: 1.0 To: Will Deacon Subject: Re: [PATCH v3 5/6] ARM: mm: Recreate kernel mappings in early_paging_init() References: <1380835081-12129-1-git-send-email-santosh.shilimkar@ti.com> <1380835081-12129-6-git-send-email-santosh.shilimkar@ti.com> <20131004155958.GU24303@mudshark.cambridge.arm.com> <524EE8F4.4060407@ti.com> In-Reply-To: <524EE8F4.4060407@ti.com> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131007_153522_340689_EF5FBB1E X-CRM114-Status: GOOD ( 29.65 ) X-Spam-Score: -7.1 (-------) Cc: "nicolas.pitre@linaro.org" , "linux@arm.linux.org.uk" , Nicolas Pitre , R Sricharan , "arm@kernel.org" , "linux-arm-kernel@lists.infradead.org" X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Will, On Friday 04 October 2013 12:12 PM, Santosh Shilimkar wrote: > On Friday 04 October 2013 11:59 AM, Will Deacon wrote: >> On Thu, Oct 03, 2013 at 10:17:59PM +0100, Santosh Shilimkar wrote: >>> This patch adds a step in the init sequence, in order to recreate >>> the kernel code/data page table mappings prior to full paging >>> initialization. This is necessary on LPAE systems that run out of >>> a physical address space outside the 4G limit. On these systems, >>> this implementation provides a machine descriptor hook that allows >>> the PHYS_OFFSET to be overridden in a machine specific fashion. >> >> [...] >> >>> diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c >>> index b1d17ee..47c7497 100644 >>> --- a/arch/arm/mm/mmu.c >>> +++ b/arch/arm/mm/mmu.c [..] >>> @@ -1315,6 +1316,87 @@ static void __init map_lowmem(void) >>> } >>> } >>> >>> +#ifdef CONFIG_ARM_LPAE >>> +extern void fixup_pv_table(const void *, unsigned long); >>> +extern const void *__pv_table_begin, *__pv_table_end; >>> + >>> +/* >>> + * early_paging_init() recreates boot time page table setup, allowing machines >>> + * to switch over to a high (>4G) address space on LPAE systems >>> + */ >>> +void __init early_paging_init(const struct machine_desc *mdesc, >>> + struct proc_info_list *procinfo) >>> +{ >>> + pmdval_t pmdprot = procinfo->__cpu_mm_mmu_flags; >>> + unsigned long map_start, map_end; >>> + pgd_t *pgd0, *pgdk; >>> + pud_t *pud0, *pudk; >>> + pmd_t *pmd0, *pmdk; >>> + phys_addr_t phys; >>> + int i; >>> + >>> + /* 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); >>> + >>> + phys = PHYS_OFFSET; >>> + >>> + if (mdesc->init_meminfo) { >>> + mdesc->init_meminfo(); >>> + /* Run the patch stub to update the constants */ >>> + fixup_pv_table(&__pv_table_begin, >>> + (&__pv_table_end - &__pv_table_begin) << 2); >>> + >>> + /* >>> + * Cache cleaning operations for self-modifying code >>> + * We should clean the entries by MVA but running a >>> + * for loop over every pv_table entry pointer would >>> + * just complicate the code. >>> + */ >>> + flush_cache_louis(); >>> + dsb(); >>> + isb(); >> >> You don't need either of these barriers. >> > Agree. Just want to be clear, its because they are already present > in flush_cache_louis(), right ? > Updated patch end of the email which addresses your comments. Regarding above barriers, we dropped the dsb() but I have to retain the isb() to commit the I-cache/BTB invalidate ops which are issued as part of flush_cache_louis(). Off-list I was discussing whether to patch cache-v7.S to add an isb to flush_cache_louis() with Russell but looking at other usages we though of leaving the isb() in my patch itself. Without the isb(), we see corruption on next v2p conversion. Let me know if you have any other concern. I plan to prepare a branch for RMK to pull in for upcoming merge window. Regards, Santosh From 6c4be7594a9556d1d79503c17d0ce629abec17d7 Mon Sep 17 00:00:00 2001 From: Santosh Shilimkar Date: Wed, 31 Jul 2013 12:44:46 -0400 Subject: [PATCH v3 5/5] ARM: mm: Recreate kernel mappings in early_paging_init() This patch adds a step in the init sequence, in order to recreate the kernel code/data page table mappings prior to full paging initialization. This is necessary on LPAE systems that run out of a physical address space outside the 4G limit. On these systems, this implementation provides a machine descriptor hook that allows the PHYS_OFFSET to be overridden in a machine specific fashion. Cc: Russell King Acked-by: Nicolas Pitre Signed-off-by: R Sricharan Signed-off-by: Santosh Shilimkar --- arch/arm/include/asm/mach/arch.h | 1 + arch/arm/kernel/setup.c | 3 ++ arch/arm/mm/mmu.c | 89 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+) diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h index 402a2bc..17a3fa2 100644 --- a/arch/arm/include/asm/mach/arch.h +++ b/arch/arm/include/asm/mach/arch.h @@ -49,6 +49,7 @@ struct machine_desc { bool (*smp_init)(void); void (*fixup)(struct tag *, char **, struct meminfo *); + void (*init_meminfo)(void); void (*reserve)(void);/* reserve mem blocks */ void (*map_io)(void);/* IO mapping function */ void (*init_early)(void); diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c index 0e1e2b3..b9a6dac 100644 --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -73,6 +73,7 @@ __setup("fpe=", fpe_setup); #endif extern void paging_init(const struct machine_desc *desc); +extern void early_paging_init(const struct machine_desc *, struct proc_info_list *); extern void sanity_check_meminfo(void); extern enum reboot_mode reboot_mode; extern void setup_dma_zone(const struct machine_desc *desc); @@ -878,6 +879,8 @@ void __init setup_arch(char **cmdline_p) parse_early_param(); sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]), meminfo_cmp, NULL); + + early_paging_init(mdesc, lookup_processor_type(read_cpuid_id())); sanity_check_meminfo(); arm_memblock_init(&meminfo, mdesc); diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index b1d17ee..0751b46 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -1315,6 +1316,94 @@ static void __init map_lowmem(void) } } +#ifdef CONFIG_ARM_LPAE +extern void fixup_pv_table(const void *, unsigned long); +extern const void *__pv_table_begin, *__pv_table_end; + +/* + * early_paging_init() recreates boot time page table setup, allowing machines + * to switch over to a high (>4G) address space on LPAE systems + */ +void __init early_paging_init(const struct machine_desc *mdesc, + struct proc_info_list *procinfo) +{ + pmdval_t pmdprot = procinfo->__cpu_mm_mmu_flags; + unsigned long map_start, map_end; + pgd_t *pgd0, *pgdk; + pud_t *pud0, *pudk, *pud_start; + pmd_t *pmd0, *pmdk, *pmd_start; + phys_addr_t phys; + int i; + + /* 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); + pud_start = pud0 = pud_offset(pgd0, 0); + pmd0 = pmd_offset(pud0, 0); + + pgdk = pgd_offset_k(map_start); + pudk = pud_offset(pgdk, map_start); + pmd_start = pmdk = pmd_offset(pudk, map_start); + + phys = PHYS_OFFSET; + + if (mdesc->init_meminfo) { + mdesc->init_meminfo(); + /* Run the patch stub to update the constants */ + fixup_pv_table(&__pv_table_begin, + (&__pv_table_end - &__pv_table_begin) << 2); + + /* + * Cache cleaning operations for self-modifying code + * We should clean the entries by MVA but running a + * for loop over every pv_table entry pointer would + * just complicate the code. isb() is added to commit + * all the prior cp15 operations. + */ + flush_cache_louis(); + isb(); + } + + /* 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; + } + + __cpuc_flush_dcache_area(pud_start, sizeof(pud_start) * PTRS_PER_PGD); + outer_clean_range(virt_to_phys(pud_start), sizeof(pud_start) * PTRS_PER_PGD); + + /* remap pmds for kernel mapping */ + phys = __pa(map_start) & PMD_MASK; + i = 0; + do { + *pmdk++ = __pmd(phys | pmdprot); + phys += PMD_SIZE; + i++; + } while (phys < map_end); + + __cpuc_flush_dcache_area(pmd_start, sizeof(pmd_start) * i); + outer_clean_range(virt_to_phys(pmd_start), sizeof(pmd_start) * i); + + cpu_switch_mm(pgd0, &init_mm); + cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET); + local_flush_tlb_all(); +} + +#else + +void __init early_paging_init(const struct machine_desc *mdesc, + struct proc_info_list *procinfo) +{ + if (mdesc->init_meminfo) + mdesc->init_meminfo(); +} + +#endif + /* * paging_init() sets up the page tables, initialises the zone memory * maps, and sets up the zero page, bad page and bad page tables.