1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2d111e8f9SRussell King /*
3d111e8f9SRussell King * linux/arch/arm/mm/mmu.c
4d111e8f9SRussell King *
5d111e8f9SRussell King * Copyright (C) 1995-2005 Russell King
6d111e8f9SRussell King */
7ae8f1541SRussell King #include <linux/module.h>
8d111e8f9SRussell King #include <linux/kernel.h>
9d111e8f9SRussell King #include <linux/errno.h>
10d111e8f9SRussell King #include <linux/init.h>
11d111e8f9SRussell King #include <linux/mman.h>
12d111e8f9SRussell King #include <linux/nodemask.h>
132778f620SRussell King #include <linux/memblock.h>
14d907387cSCatalin Marinas #include <linux/fs.h>
150536bdf3SNicolas Pitre #include <linux/vmalloc.h>
16158e8bfeSAlessandro Rubini #include <linux/sizes.h>
17d111e8f9SRussell King
1815d07dc9SRussell King #include <asm/cp15.h>
190ba8b9b2SRussell King #include <asm/cputype.h>
203f973e22SNicolas Pitre #include <asm/cachetype.h>
21ebd4922eSRussell King #include <asm/sections.h>
22d111e8f9SRussell King #include <asm/setup.h>
23e616c591SRussell King #include <asm/smp_plat.h>
24aecc83e5SArnd Bergmann #include <asm/tcm.h>
25d111e8f9SRussell King #include <asm/tlb.h>
26d73cd428SNicolas Pitre #include <asm/highmem.h>
279f97da78SDavid Howells #include <asm/system_info.h>
28247055aaSCatalin Marinas #include <asm/traps.h>
29a77e0c7bSSantosh Shilimkar #include <asm/procinfo.h>
30a9ff6961SLinus Walleij #include <asm/page.h>
31ca15ca40SMike Rapoport #include <asm/pgalloc.h>
32c12366baSLinus Walleij #include <asm/kasan_def.h>
33d111e8f9SRussell King
34d111e8f9SRussell King #include <asm/mach/arch.h>
35d111e8f9SRussell King #include <asm/mach/map.h>
36c2794437SRob Herring #include <asm/mach/pci.h>
37a05e54c1SLiu Hua #include <asm/fixmap.h>
38d111e8f9SRussell King
399254970cSLucas Stach #include "fault.h"
40d111e8f9SRussell King #include "mm.h"
41d111e8f9SRussell King
427a1be318SArd Biesheuvel extern unsigned long __atags_pointer;
437a1be318SArd Biesheuvel
44d111e8f9SRussell King /*
45d111e8f9SRussell King * empty_zero_page is a special page that is used for
46d111e8f9SRussell King * zero-initialized data and COW.
47d111e8f9SRussell King */
48d111e8f9SRussell King struct page *empty_zero_page;
493653f3abSAneesh Kumar K.V EXPORT_SYMBOL(empty_zero_page);
50d111e8f9SRussell King
51d111e8f9SRussell King /*
52d111e8f9SRussell King * The pmd table for the upper-most set of pages.
53d111e8f9SRussell King */
54d111e8f9SRussell King pmd_t *top_pmd;
55d111e8f9SRussell King
561d4d3715SJungseung Lee pmdval_t user_pmd_table = _PAGE_USER_TABLE;
571d4d3715SJungseung Lee
58ae8f1541SRussell King #define CPOLICY_UNCACHED 0
59ae8f1541SRussell King #define CPOLICY_BUFFERED 1
60ae8f1541SRussell King #define CPOLICY_WRITETHROUGH 2
61ae8f1541SRussell King #define CPOLICY_WRITEBACK 3
62ae8f1541SRussell King #define CPOLICY_WRITEALLOC 4
63ae8f1541SRussell King
64ae8f1541SRussell King static unsigned int cachepolicy __initdata = CPOLICY_WRITEBACK;
65ae8f1541SRussell King static unsigned int ecc_mask __initdata = 0;
6644b18693SImre_Deak pgprot_t pgprot_user;
67ae8f1541SRussell King pgprot_t pgprot_kernel;
68ae8f1541SRussell King
6944b18693SImre_Deak EXPORT_SYMBOL(pgprot_user);
70ae8f1541SRussell King EXPORT_SYMBOL(pgprot_kernel);
71ae8f1541SRussell King
72ae8f1541SRussell King struct cachepolicy {
73ae8f1541SRussell King const char policy[16];
74ae8f1541SRussell King unsigned int cr_mask;
75442e70c0SCatalin Marinas pmdval_t pmd;
76f6e3354dSRussell King pteval_t pte;
77ae8f1541SRussell King };
78ae8f1541SRussell King
79ae8f1541SRussell King static struct cachepolicy cache_policies[] __initdata = {
80ae8f1541SRussell King {
81ae8f1541SRussell King .policy = "uncached",
82ae8f1541SRussell King .cr_mask = CR_W|CR_C,
83ae8f1541SRussell King .pmd = PMD_SECT_UNCACHED,
84bb30f36fSRussell King .pte = L_PTE_MT_UNCACHED,
85ae8f1541SRussell King }, {
86ae8f1541SRussell King .policy = "buffered",
87ae8f1541SRussell King .cr_mask = CR_C,
88ae8f1541SRussell King .pmd = PMD_SECT_BUFFERED,
89bb30f36fSRussell King .pte = L_PTE_MT_BUFFERABLE,
90ae8f1541SRussell King }, {
91ae8f1541SRussell King .policy = "writethrough",
92ae8f1541SRussell King .cr_mask = 0,
93ae8f1541SRussell King .pmd = PMD_SECT_WT,
94bb30f36fSRussell King .pte = L_PTE_MT_WRITETHROUGH,
95ae8f1541SRussell King }, {
96ae8f1541SRussell King .policy = "writeback",
97ae8f1541SRussell King .cr_mask = 0,
98ae8f1541SRussell King .pmd = PMD_SECT_WB,
99bb30f36fSRussell King .pte = L_PTE_MT_WRITEBACK,
100ae8f1541SRussell King }, {
101ae8f1541SRussell King .policy = "writealloc",
102ae8f1541SRussell King .cr_mask = 0,
103ae8f1541SRussell King .pmd = PMD_SECT_WBWA,
104bb30f36fSRussell King .pte = L_PTE_MT_WRITEALLOC,
105ae8f1541SRussell King }
106ae8f1541SRussell King };
107ae8f1541SRussell King
108b849a60eSUwe Kleine-König #ifdef CONFIG_CPU_CP15
10920e7e364SRussell King static unsigned long initial_pmd_value __initdata = 0;
11020e7e364SRussell King
111ae8f1541SRussell King /*
112ca8f0b0aSRussell King * Initialise the cache_policy variable with the initial state specified
113ca8f0b0aSRussell King * via the "pmd" value. This is used to ensure that on ARMv6 and later,
114ca8f0b0aSRussell King * the C code sets the page tables up with the same policy as the head
115ca8f0b0aSRussell King * assembly code, which avoids an illegal state where the TLBs can get
116ca8f0b0aSRussell King * confused. See comments in early_cachepolicy() for more information.
117ca8f0b0aSRussell King */
init_default_cache_policy(unsigned long pmd)118ca8f0b0aSRussell King void __init init_default_cache_policy(unsigned long pmd)
119ca8f0b0aSRussell King {
120ca8f0b0aSRussell King int i;
121ca8f0b0aSRussell King
12220e7e364SRussell King initial_pmd_value = pmd;
12320e7e364SRussell King
1246b3142b2SStefan Agner pmd &= PMD_SECT_CACHE_MASK;
125ca8f0b0aSRussell King
126ca8f0b0aSRussell King for (i = 0; i < ARRAY_SIZE(cache_policies); i++)
127ca8f0b0aSRussell King if (cache_policies[i].pmd == pmd) {
128ca8f0b0aSRussell King cachepolicy = i;
129ca8f0b0aSRussell King break;
130ca8f0b0aSRussell King }
131ca8f0b0aSRussell King
132ca8f0b0aSRussell King if (i == ARRAY_SIZE(cache_policies))
133ca8f0b0aSRussell King pr_err("ERROR: could not find cache policy\n");
134ca8f0b0aSRussell King }
135ca8f0b0aSRussell King
136ca8f0b0aSRussell King /*
137ca8f0b0aSRussell King * These are useful for identifying cache coherency problems by allowing
138ca8f0b0aSRussell King * the cache or the cache and writebuffer to be turned off. (Note: the
139ca8f0b0aSRussell King * write buffer should not be on and the cache off).
140ae8f1541SRussell King */
early_cachepolicy(char * p)1412b0d8c25SJeremy Kerr static int __init early_cachepolicy(char *p)
142ae8f1541SRussell King {
143ca8f0b0aSRussell King int i, selected = -1;
144ae8f1541SRussell King
145ae8f1541SRussell King for (i = 0; i < ARRAY_SIZE(cache_policies); i++) {
146ae8f1541SRussell King int len = strlen(cache_policies[i].policy);
147ae8f1541SRussell King
1482b0d8c25SJeremy Kerr if (memcmp(p, cache_policies[i].policy, len) == 0) {
149ca8f0b0aSRussell King selected = i;
150ae8f1541SRussell King break;
151ae8f1541SRussell King }
152ae8f1541SRussell King }
153ca8f0b0aSRussell King
154ca8f0b0aSRussell King if (selected == -1)
155ca8f0b0aSRussell King pr_err("ERROR: unknown or unsupported cache policy\n");
156ca8f0b0aSRussell King
1574b46d641SRussell King /*
1584b46d641SRussell King * This restriction is partly to do with the way we boot; it is
1594b46d641SRussell King * unpredictable to have memory mapped using two different sets of
1604b46d641SRussell King * memory attributes (shared, type, and cache attribs). We can not
1614b46d641SRussell King * change these attributes once the initial assembly has setup the
1624b46d641SRussell King * page tables.
1634b46d641SRussell King */
164ca8f0b0aSRussell King if (cpu_architecture() >= CPU_ARCH_ARMv6 && selected != cachepolicy) {
165ca8f0b0aSRussell King pr_warn("Only cachepolicy=%s supported on ARMv6 and later\n",
166ca8f0b0aSRussell King cache_policies[cachepolicy].policy);
167ca8f0b0aSRussell King return 0;
16811179d8cSCatalin Marinas }
169ca8f0b0aSRussell King
170ca8f0b0aSRussell King if (selected != cachepolicy) {
171ca8f0b0aSRussell King unsigned long cr = __clear_cr(cache_policies[selected].cr_mask);
172ca8f0b0aSRussell King cachepolicy = selected;
173ae8f1541SRussell King flush_cache_all();
174b4b20ad8SRussell King set_cr(cr);
175ca8f0b0aSRussell King }
1762b0d8c25SJeremy Kerr return 0;
177ae8f1541SRussell King }
1782b0d8c25SJeremy Kerr early_param("cachepolicy", early_cachepolicy);
179ae8f1541SRussell King
early_nocache(char * __unused)1802b0d8c25SJeremy Kerr static int __init early_nocache(char *__unused)
181ae8f1541SRussell King {
182ae8f1541SRussell King char *p = "buffered";
1834ed89f22SRussell King pr_warn("nocache is deprecated; use cachepolicy=%s\n", p);
1842b0d8c25SJeremy Kerr early_cachepolicy(p);
1852b0d8c25SJeremy Kerr return 0;
186ae8f1541SRussell King }
1872b0d8c25SJeremy Kerr early_param("nocache", early_nocache);
188ae8f1541SRussell King
early_nowrite(char * __unused)1892b0d8c25SJeremy Kerr static int __init early_nowrite(char *__unused)
190ae8f1541SRussell King {
191ae8f1541SRussell King char *p = "uncached";
1924ed89f22SRussell King pr_warn("nowb is deprecated; use cachepolicy=%s\n", p);
1932b0d8c25SJeremy Kerr early_cachepolicy(p);
1942b0d8c25SJeremy Kerr return 0;
195ae8f1541SRussell King }
1962b0d8c25SJeremy Kerr early_param("nowb", early_nowrite);
197ae8f1541SRussell King
1981b6ba46bSCatalin Marinas #ifndef CONFIG_ARM_LPAE
early_ecc(char * p)1992b0d8c25SJeremy Kerr static int __init early_ecc(char *p)
200ae8f1541SRussell King {
2012b0d8c25SJeremy Kerr if (memcmp(p, "on", 2) == 0)
202ae8f1541SRussell King ecc_mask = PMD_PROTECTION;
2032b0d8c25SJeremy Kerr else if (memcmp(p, "off", 3) == 0)
204ae8f1541SRussell King ecc_mask = 0;
2052b0d8c25SJeremy Kerr return 0;
206ae8f1541SRussell King }
2072b0d8c25SJeremy Kerr early_param("ecc", early_ecc);
2081b6ba46bSCatalin Marinas #endif
209ae8f1541SRussell King
210b849a60eSUwe Kleine-König #else /* ifdef CONFIG_CPU_CP15 */
211b849a60eSUwe Kleine-König
early_cachepolicy(char * p)212b849a60eSUwe Kleine-König static int __init early_cachepolicy(char *p)
213b849a60eSUwe Kleine-König {
2148b521cb2SJoe Perches pr_warn("cachepolicy kernel parameter not supported without cp15\n");
2157b83299eSRandy Dunlap return 0;
216b849a60eSUwe Kleine-König }
217b849a60eSUwe Kleine-König early_param("cachepolicy", early_cachepolicy);
218b849a60eSUwe Kleine-König
noalign_setup(char * __unused)219b849a60eSUwe Kleine-König static int __init noalign_setup(char *__unused)
220b849a60eSUwe Kleine-König {
2218b521cb2SJoe Perches pr_warn("noalign kernel parameter not supported without cp15\n");
2227b83299eSRandy Dunlap return 1;
223b849a60eSUwe Kleine-König }
224b849a60eSUwe Kleine-König __setup("noalign", noalign_setup);
225b849a60eSUwe Kleine-König
226b849a60eSUwe Kleine-König #endif /* ifdef CONFIG_CPU_CP15 / else */
227b849a60eSUwe Kleine-König
22836bb94baSRussell King #define PROT_PTE_DEVICE L_PTE_PRESENT|L_PTE_YOUNG|L_PTE_DIRTY|L_PTE_XN
2294d9c5b89SChristoffer Dall #define PROT_PTE_S2_DEVICE PROT_PTE_DEVICE
230b1cce6b1SRussell King #define PROT_SECT_DEVICE PMD_TYPE_SECT|PMD_SECT_AP_WRITE
2310af92befSRussell King
2327619751fSKees Cook static struct mem_type mem_types[] __ro_after_init = {
2330af92befSRussell King [MT_DEVICE] = { /* Strongly ordered / ARMv6 shared device */
234bb30f36fSRussell King .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_SHARED |
235bb30f36fSRussell King L_PTE_SHARED,
236ae8f1541SRussell King .prot_l1 = PMD_TYPE_TABLE,
237b1cce6b1SRussell King .prot_sect = PROT_SECT_DEVICE | PMD_SECT_S,
2380af92befSRussell King .domain = DOMAIN_IO,
2390af92befSRussell King },
2400af92befSRussell King [MT_DEVICE_NONSHARED] = { /* ARMv6 non-shared device */
241bb30f36fSRussell King .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_NONSHARED,
2420af92befSRussell King .prot_l1 = PMD_TYPE_TABLE,
243b1cce6b1SRussell King .prot_sect = PROT_SECT_DEVICE,
2440af92befSRussell King .domain = DOMAIN_IO,
2450af92befSRussell King },
2466a22d824SChristoph Hellwig [MT_DEVICE_CACHED] = { /* ioremap_cache */
247bb30f36fSRussell King .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_CACHED,
2480af92befSRussell King .prot_l1 = PMD_TYPE_TABLE,
2490af92befSRussell King .prot_sect = PROT_SECT_DEVICE | PMD_SECT_WB,
2500af92befSRussell King .domain = DOMAIN_IO,
2510af92befSRussell King },
2521ad77a87SLennert Buytenhek [MT_DEVICE_WC] = { /* ioremap_wc */
253bb30f36fSRussell King .prot_pte = PROT_PTE_DEVICE | L_PTE_MT_DEV_WC,
2540af92befSRussell King .prot_l1 = PMD_TYPE_TABLE,
255b1cce6b1SRussell King .prot_sect = PROT_SECT_DEVICE,
256ae8f1541SRussell King .domain = DOMAIN_IO,
257ae8f1541SRussell King },
258ebb4c658SRussell King [MT_UNCACHED] = {
259ebb4c658SRussell King .prot_pte = PROT_PTE_DEVICE,
260ebb4c658SRussell King .prot_l1 = PMD_TYPE_TABLE,
261ebb4c658SRussell King .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
262ebb4c658SRussell King .domain = DOMAIN_IO,
263ebb4c658SRussell King },
264ae8f1541SRussell King [MT_CACHECLEAN] = {
2659ef79635SRussell King .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
266ae8f1541SRussell King .domain = DOMAIN_KERNEL,
267ae8f1541SRussell King },
2681b6ba46bSCatalin Marinas #ifndef CONFIG_ARM_LPAE
269ae8f1541SRussell King [MT_MINICLEAN] = {
2709ef79635SRussell King .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN | PMD_SECT_MINICACHE,
271ae8f1541SRussell King .domain = DOMAIN_KERNEL,
272ae8f1541SRussell King },
2731b6ba46bSCatalin Marinas #endif
274ae8f1541SRussell King [MT_LOW_VECTORS] = {
275ae8f1541SRussell King .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
27636bb94baSRussell King L_PTE_RDONLY,
277ae8f1541SRussell King .prot_l1 = PMD_TYPE_TABLE,
278a02d8dfdSRussell King .domain = DOMAIN_VECTORS,
279ae8f1541SRussell King },
280ae8f1541SRussell King [MT_HIGH_VECTORS] = {
281ae8f1541SRussell King .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
28236bb94baSRussell King L_PTE_USER | L_PTE_RDONLY,
283ae8f1541SRussell King .prot_l1 = PMD_TYPE_TABLE,
284a02d8dfdSRussell King .domain = DOMAIN_VECTORS,
285ae8f1541SRussell King },
2862e2c9de2SRussell King [MT_MEMORY_RWX] = {
28736bb94baSRussell King .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
288f1a2481cSSantosh Shilimkar .prot_l1 = PMD_TYPE_TABLE,
2899ef79635SRussell King .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
290ae8f1541SRussell King .domain = DOMAIN_KERNEL,
291ae8f1541SRussell King },
292ebd4922eSRussell King [MT_MEMORY_RW] = {
293ebd4922eSRussell King .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
294ebd4922eSRussell King L_PTE_XN,
295ebd4922eSRussell King .prot_l1 = PMD_TYPE_TABLE,
296ebd4922eSRussell King .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
297ebd4922eSRussell King .domain = DOMAIN_KERNEL,
298ebd4922eSRussell King },
299598f0a99SZhen Lei [MT_MEMORY_RO] = {
300598f0a99SZhen Lei .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
301598f0a99SZhen Lei L_PTE_XN | L_PTE_RDONLY,
302598f0a99SZhen Lei .prot_l1 = PMD_TYPE_TABLE,
30314ca1a46SWang Kefeng #ifdef CONFIG_ARM_LPAE
30414ca1a46SWang Kefeng .prot_sect = PMD_TYPE_SECT | L_PMD_SECT_RDONLY | PMD_SECT_AP2,
30514ca1a46SWang Kefeng #else
306598f0a99SZhen Lei .prot_sect = PMD_TYPE_SECT,
30714ca1a46SWang Kefeng #endif
308598f0a99SZhen Lei .domain = DOMAIN_KERNEL,
309598f0a99SZhen Lei },
310ae8f1541SRussell King [MT_ROM] = {
3119ef79635SRussell King .prot_sect = PMD_TYPE_SECT,
312ae8f1541SRussell King .domain = DOMAIN_KERNEL,
313ae8f1541SRussell King },
3142e2c9de2SRussell King [MT_MEMORY_RWX_NONCACHED] = {
315f1a2481cSSantosh Shilimkar .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
31636bb94baSRussell King L_PTE_MT_BUFFERABLE,
317f1a2481cSSantosh Shilimkar .prot_l1 = PMD_TYPE_TABLE,
318e4707dd3SPaul Walmsley .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE,
319e4707dd3SPaul Walmsley .domain = DOMAIN_KERNEL,
320e4707dd3SPaul Walmsley },
3212e2c9de2SRussell King [MT_MEMORY_RW_DTCM] = {
322f444fce3SLinus Walleij .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
32336bb94baSRussell King L_PTE_XN,
324cb9d7707SLinus Walleij .prot_l1 = PMD_TYPE_TABLE,
325cb9d7707SLinus Walleij .prot_sect = PMD_TYPE_SECT | PMD_SECT_XN,
326cb9d7707SLinus Walleij .domain = DOMAIN_KERNEL,
327cb9d7707SLinus Walleij },
3282e2c9de2SRussell King [MT_MEMORY_RWX_ITCM] = {
32936bb94baSRussell King .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
330cb9d7707SLinus Walleij .prot_l1 = PMD_TYPE_TABLE,
331f444fce3SLinus Walleij .domain = DOMAIN_KERNEL,
332cb9d7707SLinus Walleij },
3332e2c9de2SRussell King [MT_MEMORY_RW_SO] = {
3348fb54284SSantosh Shilimkar .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
33593d5bf07SSantosh Shilimkar L_PTE_MT_UNCACHED | L_PTE_XN,
3368fb54284SSantosh Shilimkar .prot_l1 = PMD_TYPE_TABLE,
3378fb54284SSantosh Shilimkar .prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
3388fb54284SSantosh Shilimkar PMD_SECT_UNCACHED | PMD_SECT_XN,
3398fb54284SSantosh Shilimkar .domain = DOMAIN_KERNEL,
3408fb54284SSantosh Shilimkar },
341c7909509SMarek Szyprowski [MT_MEMORY_DMA_READY] = {
34271b55663SRussell King .prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
34371b55663SRussell King L_PTE_XN,
344c7909509SMarek Szyprowski .prot_l1 = PMD_TYPE_TABLE,
345c7909509SMarek Szyprowski .domain = DOMAIN_KERNEL,
346c7909509SMarek Szyprowski },
347ae8f1541SRussell King };
348ae8f1541SRussell King
get_mem_type(unsigned int type)349b29e9f5eSRussell King const struct mem_type *get_mem_type(unsigned int type)
350b29e9f5eSRussell King {
351b29e9f5eSRussell King return type < ARRAY_SIZE(mem_types) ? &mem_types[type] : NULL;
352b29e9f5eSRussell King }
35369d3a84aSHiroshi DOYU EXPORT_SYMBOL(get_mem_type);
354b29e9f5eSRussell King
355a5f4c561SStefan Agner static pte_t *(*pte_offset_fixmap)(pmd_t *dir, unsigned long addr);
356a5f4c561SStefan Agner
357a5f4c561SStefan Agner static pte_t bm_pte[PTRS_PER_PTE + PTE_HWTABLE_PTRS]
358a5f4c561SStefan Agner __aligned(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE) __initdata;
359a5f4c561SStefan Agner
pte_offset_early_fixmap(pmd_t * dir,unsigned long addr)360a5f4c561SStefan Agner static pte_t * __init pte_offset_early_fixmap(pmd_t *dir, unsigned long addr)
361a5f4c561SStefan Agner {
362a5f4c561SStefan Agner return &bm_pte[pte_index(addr)];
363a5f4c561SStefan Agner }
364a5f4c561SStefan Agner
pte_offset_late_fixmap(pmd_t * dir,unsigned long addr)365a5f4c561SStefan Agner static pte_t *pte_offset_late_fixmap(pmd_t *dir, unsigned long addr)
366a5f4c561SStefan Agner {
367a5f4c561SStefan Agner return pte_offset_kernel(dir, addr);
368a5f4c561SStefan Agner }
369a5f4c561SStefan Agner
fixmap_pmd(unsigned long addr)370a5f4c561SStefan Agner static inline pmd_t * __init fixmap_pmd(unsigned long addr)
371a5f4c561SStefan Agner {
372e05c7b1fSMike Rapoport return pmd_off_k(addr);
373a5f4c561SStefan Agner }
374a5f4c561SStefan Agner
early_fixmap_init(void)375a5f4c561SStefan Agner void __init early_fixmap_init(void)
376a5f4c561SStefan Agner {
377a5f4c561SStefan Agner pmd_t *pmd;
378a5f4c561SStefan Agner
379a5f4c561SStefan Agner /*
380a5f4c561SStefan Agner * The early fixmap range spans multiple pmds, for which
381a5f4c561SStefan Agner * we are not prepared:
382a5f4c561SStefan Agner */
3832937367bSArd Biesheuvel BUILD_BUG_ON((__fix_to_virt(__end_of_early_ioremap_region) >> PMD_SHIFT)
384a5f4c561SStefan Agner != FIXADDR_TOP >> PMD_SHIFT);
385a5f4c561SStefan Agner
386a5f4c561SStefan Agner pmd = fixmap_pmd(FIXADDR_TOP);
387a5f4c561SStefan Agner pmd_populate_kernel(&init_mm, pmd, bm_pte);
388a5f4c561SStefan Agner
389a5f4c561SStefan Agner pte_offset_fixmap = pte_offset_early_fixmap;
390a5f4c561SStefan Agner }
391a5f4c561SStefan Agner
392ae8f1541SRussell King /*
39399b4ac9aSKees Cook * To avoid TLB flush broadcasts, this uses local_flush_tlb_kernel_range().
39499b4ac9aSKees Cook * As a result, this can only be called with preemption disabled, as under
39599b4ac9aSKees Cook * stop_machine().
39699b4ac9aSKees Cook */
__set_fixmap(enum fixed_addresses idx,phys_addr_t phys,pgprot_t prot)39799b4ac9aSKees Cook void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot)
39899b4ac9aSKees Cook {
39999b4ac9aSKees Cook unsigned long vaddr = __fix_to_virt(idx);
400a5f4c561SStefan Agner pte_t *pte = pte_offset_fixmap(pmd_off_k(vaddr), vaddr);
40199b4ac9aSKees Cook
40299b4ac9aSKees Cook /* Make sure fixmap region does not exceed available allocation. */
403d624833fSArd Biesheuvel BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) < FIXADDR_START);
40499b4ac9aSKees Cook BUG_ON(idx >= __end_of_fixed_addresses);
40599b4ac9aSKees Cook
4060d08e7bfSMichał Mirosław /* We support only device mappings before pgprot_kernel is set. */
407b089c31cSJon Medhurst if (WARN_ON(pgprot_val(prot) != pgprot_val(FIXMAP_PAGE_IO) &&
4080d08e7bfSMichał Mirosław pgprot_val(prot) && pgprot_val(pgprot_kernel) == 0))
409b089c31cSJon Medhurst return;
410b089c31cSJon Medhurst
41199b4ac9aSKees Cook if (pgprot_val(prot))
41299b4ac9aSKees Cook set_pte_at(NULL, vaddr, pte,
41399b4ac9aSKees Cook pfn_pte(phys >> PAGE_SHIFT, prot));
41499b4ac9aSKees Cook else
41599b4ac9aSKees Cook pte_clear(NULL, vaddr, pte);
41699b4ac9aSKees Cook local_flush_tlb_kernel_range(vaddr, vaddr + PAGE_SIZE);
41799b4ac9aSKees Cook }
41899b4ac9aSKees Cook
419ca26f936SAnshuman Khandual static pgprot_t protection_map[16] __ro_after_init = {
420ca26f936SAnshuman Khandual [VM_NONE] = __PAGE_NONE,
421ca26f936SAnshuman Khandual [VM_READ] = __PAGE_READONLY,
422ca26f936SAnshuman Khandual [VM_WRITE] = __PAGE_COPY,
423ca26f936SAnshuman Khandual [VM_WRITE | VM_READ] = __PAGE_COPY,
424ca26f936SAnshuman Khandual [VM_EXEC] = __PAGE_READONLY_EXEC,
425ca26f936SAnshuman Khandual [VM_EXEC | VM_READ] = __PAGE_READONLY_EXEC,
426ca26f936SAnshuman Khandual [VM_EXEC | VM_WRITE] = __PAGE_COPY_EXEC,
427ca26f936SAnshuman Khandual [VM_EXEC | VM_WRITE | VM_READ] = __PAGE_COPY_EXEC,
428ca26f936SAnshuman Khandual [VM_SHARED] = __PAGE_NONE,
429ca26f936SAnshuman Khandual [VM_SHARED | VM_READ] = __PAGE_READONLY,
430ca26f936SAnshuman Khandual [VM_SHARED | VM_WRITE] = __PAGE_SHARED,
431ca26f936SAnshuman Khandual [VM_SHARED | VM_WRITE | VM_READ] = __PAGE_SHARED,
432ca26f936SAnshuman Khandual [VM_SHARED | VM_EXEC] = __PAGE_READONLY_EXEC,
433ca26f936SAnshuman Khandual [VM_SHARED | VM_EXEC | VM_READ] = __PAGE_READONLY_EXEC,
434ca26f936SAnshuman Khandual [VM_SHARED | VM_EXEC | VM_WRITE] = __PAGE_SHARED_EXEC,
435ca26f936SAnshuman Khandual [VM_SHARED | VM_EXEC | VM_WRITE | VM_READ] = __PAGE_SHARED_EXEC
436ca26f936SAnshuman Khandual };
437ca26f936SAnshuman Khandual DECLARE_VM_GET_PAGE_PROT
438ca26f936SAnshuman Khandual
43999b4ac9aSKees Cook /*
440ae8f1541SRussell King * Adjust the PMD section entries according to the CPU in use.
441ae8f1541SRussell King */
build_mem_type_table(void)442ae8f1541SRussell King static void __init build_mem_type_table(void)
443ae8f1541SRussell King {
444ae8f1541SRussell King struct cachepolicy *cp;
445ae8f1541SRussell King unsigned int cr = get_cr();
446442e70c0SCatalin Marinas pteval_t user_pgprot, kern_pgprot, vecs_pgprot;
447ae8f1541SRussell King int cpu_arch = cpu_architecture();
448ae8f1541SRussell King int i;
449ae8f1541SRussell King
45011179d8cSCatalin Marinas if (cpu_arch < CPU_ARCH_ARMv6) {
451ae8f1541SRussell King #if defined(CONFIG_CPU_DCACHE_DISABLE)
452ae8f1541SRussell King if (cachepolicy > CPOLICY_BUFFERED)
453ae8f1541SRussell King cachepolicy = CPOLICY_BUFFERED;
454ae8f1541SRussell King #elif defined(CONFIG_CPU_DCACHE_WRITETHROUGH)
455ae8f1541SRussell King if (cachepolicy > CPOLICY_WRITETHROUGH)
456ae8f1541SRussell King cachepolicy = CPOLICY_WRITETHROUGH;
457ae8f1541SRussell King #endif
45811179d8cSCatalin Marinas }
459ae8f1541SRussell King if (cpu_arch < CPU_ARCH_ARMv5) {
460ae8f1541SRussell King if (cachepolicy >= CPOLICY_WRITEALLOC)
461ae8f1541SRussell King cachepolicy = CPOLICY_WRITEBACK;
462ae8f1541SRussell King ecc_mask = 0;
463ae8f1541SRussell King }
464ca8f0b0aSRussell King
46520e7e364SRussell King if (is_smp()) {
46620e7e364SRussell King if (cachepolicy != CPOLICY_WRITEALLOC) {
467ca8f0b0aSRussell King pr_warn("Forcing write-allocate cache policy for SMP\n");
468bb30f36fSRussell King cachepolicy = CPOLICY_WRITEALLOC;
469ca8f0b0aSRussell King }
47020e7e364SRussell King if (!(initial_pmd_value & PMD_SECT_S)) {
47120e7e364SRussell King pr_warn("Forcing shared mappings for SMP\n");
47220e7e364SRussell King initial_pmd_value |= PMD_SECT_S;
47320e7e364SRussell King }
47420e7e364SRussell King }
475ae8f1541SRussell King
476ae8f1541SRussell King /*
477b1cce6b1SRussell King * Strip out features not present on earlier architectures.
478b1cce6b1SRussell King * Pre-ARMv5 CPUs don't have TEX bits. Pre-ARMv6 CPUs or those
479b1cce6b1SRussell King * without extended page tables don't have the 'Shared' bit.
4801ad77a87SLennert Buytenhek */
481b1cce6b1SRussell King if (cpu_arch < CPU_ARCH_ARMv5)
482b1cce6b1SRussell King for (i = 0; i < ARRAY_SIZE(mem_types); i++)
483b1cce6b1SRussell King mem_types[i].prot_sect &= ~PMD_SECT_TEX(7);
484b1cce6b1SRussell King if ((cpu_arch < CPU_ARCH_ARMv6 || !(cr & CR_XP)) && !cpu_is_xsc3())
485b1cce6b1SRussell King for (i = 0; i < ARRAY_SIZE(mem_types); i++)
486b1cce6b1SRussell King mem_types[i].prot_sect &= ~PMD_SECT_S;
487ae8f1541SRussell King
488ae8f1541SRussell King /*
489b1cce6b1SRussell King * ARMv5 and lower, bit 4 must be set for page tables (was: cache
490b1cce6b1SRussell King * "update-able on write" bit on ARM610). However, Xscale and
491b1cce6b1SRussell King * Xscale3 require this bit to be cleared.
492ae8f1541SRussell King */
493d33c43acSArnd Bergmann if (cpu_is_xscale_family()) {
4949ef79635SRussell King for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
495ae8f1541SRussell King mem_types[i].prot_sect &= ~PMD_BIT4;
4969ef79635SRussell King mem_types[i].prot_l1 &= ~PMD_BIT4;
4979ef79635SRussell King }
4989ef79635SRussell King } else if (cpu_arch < CPU_ARCH_ARMv6) {
4999ef79635SRussell King for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
500ae8f1541SRussell King if (mem_types[i].prot_l1)
501ae8f1541SRussell King mem_types[i].prot_l1 |= PMD_BIT4;
5029ef79635SRussell King if (mem_types[i].prot_sect)
5039ef79635SRussell King mem_types[i].prot_sect |= PMD_BIT4;
5049ef79635SRussell King }
5059ef79635SRussell King }
506ae8f1541SRussell King
507b1cce6b1SRussell King /*
508b1cce6b1SRussell King * Mark the device areas according to the CPU/architecture.
509b1cce6b1SRussell King */
510b1cce6b1SRussell King if (cpu_is_xsc3() || (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP))) {
511b1cce6b1SRussell King if (!cpu_is_xsc3()) {
512b1cce6b1SRussell King /*
513b1cce6b1SRussell King * Mark device regions on ARMv6+ as execute-never
514b1cce6b1SRussell King * to prevent speculative instruction fetches.
515b1cce6b1SRussell King */
516b1cce6b1SRussell King mem_types[MT_DEVICE].prot_sect |= PMD_SECT_XN;
517b1cce6b1SRussell King mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_XN;
518b1cce6b1SRussell King mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_XN;
519b1cce6b1SRussell King mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_XN;
520ebd4922eSRussell King
521ebd4922eSRussell King /* Also setup NX memory mapping */
522ebd4922eSRussell King mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_XN;
523598f0a99SZhen Lei mem_types[MT_MEMORY_RO].prot_sect |= PMD_SECT_XN;
524b1cce6b1SRussell King }
525b1cce6b1SRussell King if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
526b1cce6b1SRussell King /*
527b1cce6b1SRussell King * For ARMv7 with TEX remapping,
528b1cce6b1SRussell King * - shared device is SXCB=1100
529b1cce6b1SRussell King * - nonshared device is SXCB=0100
530b1cce6b1SRussell King * - write combine device mem is SXCB=0001
531b1cce6b1SRussell King * (Uncached Normal memory)
532b1cce6b1SRussell King */
533b1cce6b1SRussell King mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1);
534b1cce6b1SRussell King mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(1);
535b1cce6b1SRussell King mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
536b1cce6b1SRussell King } else if (cpu_is_xsc3()) {
537b1cce6b1SRussell King /*
538b1cce6b1SRussell King * For Xscale3,
539b1cce6b1SRussell King * - shared device is TEXCB=00101
540b1cce6b1SRussell King * - nonshared device is TEXCB=01000
541b1cce6b1SRussell King * - write combine device mem is TEXCB=00100
542b1cce6b1SRussell King * (Inner/Outer Uncacheable in xsc3 parlance)
543b1cce6b1SRussell King */
544b1cce6b1SRussell King mem_types[MT_DEVICE].prot_sect |= PMD_SECT_TEX(1) | PMD_SECT_BUFFERED;
545b1cce6b1SRussell King mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2);
546b1cce6b1SRussell King mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
547b1cce6b1SRussell King } else {
548b1cce6b1SRussell King /*
549b1cce6b1SRussell King * For ARMv6 and ARMv7 without TEX remapping,
550b1cce6b1SRussell King * - shared device is TEXCB=00001
551b1cce6b1SRussell King * - nonshared device is TEXCB=01000
552b1cce6b1SRussell King * - write combine device mem is TEXCB=00100
553b1cce6b1SRussell King * (Uncached Normal in ARMv6 parlance).
554b1cce6b1SRussell King */
555b1cce6b1SRussell King mem_types[MT_DEVICE].prot_sect |= PMD_SECT_BUFFERED;
556b1cce6b1SRussell King mem_types[MT_DEVICE_NONSHARED].prot_sect |= PMD_SECT_TEX(2);
557b1cce6b1SRussell King mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_TEX(1);
558b1cce6b1SRussell King }
559b1cce6b1SRussell King } else {
560b1cce6b1SRussell King /*
561b1cce6b1SRussell King * On others, write combining is "Uncached/Buffered"
562b1cce6b1SRussell King */
563b1cce6b1SRussell King mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_BUFFERABLE;
564b1cce6b1SRussell King }
565b1cce6b1SRussell King
566b1cce6b1SRussell King /*
567b1cce6b1SRussell King * Now deal with the memory-type mappings
568b1cce6b1SRussell King */
569ae8f1541SRussell King cp = &cache_policies[cachepolicy];
570bb30f36fSRussell King vecs_pgprot = kern_pgprot = user_pgprot = cp->pte;
571bb30f36fSRussell King
5721d4d3715SJungseung Lee #ifndef CONFIG_ARM_LPAE
573bb30f36fSRussell King /*
574b6ccb980SWill Deacon * We don't use domains on ARMv6 (since this causes problems with
575b6ccb980SWill Deacon * v6/v7 kernels), so we must use a separate memory type for user
576b6ccb980SWill Deacon * r/o, kernel r/w to map the vectors page.
577b6ccb980SWill Deacon */
578b6ccb980SWill Deacon if (cpu_arch == CPU_ARCH_ARMv6)
579b6ccb980SWill Deacon vecs_pgprot |= L_PTE_MT_VECTORS;
5801d4d3715SJungseung Lee
5811d4d3715SJungseung Lee /*
5821d4d3715SJungseung Lee * Check is it with support for the PXN bit
5831d4d3715SJungseung Lee * in the Short-descriptor translation table format descriptors.
5841d4d3715SJungseung Lee */
5851d4d3715SJungseung Lee if (cpu_arch == CPU_ARCH_ARMv7 &&
586ad84f56bSJungseung Lee (read_cpuid_ext(CPUID_EXT_MMFR0) & 0xF) >= 4) {
5871d4d3715SJungseung Lee user_pmd_table |= PMD_PXNTABLE;
5881d4d3715SJungseung Lee }
589b6ccb980SWill Deacon #endif
590bb30f36fSRussell King
591bb30f36fSRussell King /*
592ae8f1541SRussell King * ARMv6 and above have extended page tables.
593ae8f1541SRussell King */
594ae8f1541SRussell King if (cpu_arch >= CPU_ARCH_ARMv6 && (cr & CR_XP)) {
5951b6ba46bSCatalin Marinas #ifndef CONFIG_ARM_LPAE
596ae8f1541SRussell King /*
597ae8f1541SRussell King * Mark cache clean areas and XIP ROM read only
598ae8f1541SRussell King * from SVC mode and no access from userspace.
599ae8f1541SRussell King */
600ae8f1541SRussell King mem_types[MT_ROM].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
601ae8f1541SRussell King mem_types[MT_MINICLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
602ae8f1541SRussell King mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
603598f0a99SZhen Lei mem_types[MT_MEMORY_RO].prot_sect |= PMD_SECT_APX|PMD_SECT_AP_WRITE;
6041b6ba46bSCatalin Marinas #endif
605ae8f1541SRussell King
606ae8f1541SRussell King /*
60720e7e364SRussell King * If the initial page tables were created with the S bit
60820e7e364SRussell King * set, then we need to do the same here for the same
60920e7e364SRussell King * reasons given in early_cachepolicy().
610ae8f1541SRussell King */
61120e7e364SRussell King if (initial_pmd_value & PMD_SECT_S) {
612ae8f1541SRussell King user_pgprot |= L_PTE_SHARED;
613ae8f1541SRussell King kern_pgprot |= L_PTE_SHARED;
614bb30f36fSRussell King vecs_pgprot |= L_PTE_SHARED;
61585b3cce8SRussell King mem_types[MT_DEVICE_WC].prot_sect |= PMD_SECT_S;
61685b3cce8SRussell King mem_types[MT_DEVICE_WC].prot_pte |= L_PTE_SHARED;
61785b3cce8SRussell King mem_types[MT_DEVICE_CACHED].prot_sect |= PMD_SECT_S;
61885b3cce8SRussell King mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
6192e2c9de2SRussell King mem_types[MT_MEMORY_RWX].prot_sect |= PMD_SECT_S;
6202e2c9de2SRussell King mem_types[MT_MEMORY_RWX].prot_pte |= L_PTE_SHARED;
621ebd4922eSRussell King mem_types[MT_MEMORY_RW].prot_sect |= PMD_SECT_S;
622ebd4922eSRussell King mem_types[MT_MEMORY_RW].prot_pte |= L_PTE_SHARED;
623598f0a99SZhen Lei mem_types[MT_MEMORY_RO].prot_sect |= PMD_SECT_S;
624598f0a99SZhen Lei mem_types[MT_MEMORY_RO].prot_pte |= L_PTE_SHARED;
625c7909509SMarek Szyprowski mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
6262e2c9de2SRussell King mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_S;
6272e2c9de2SRussell King mem_types[MT_MEMORY_RWX_NONCACHED].prot_pte |= L_PTE_SHARED;
628f00ec48fSRussell King }
629ae8f1541SRussell King }
630ae8f1541SRussell King
631e4707dd3SPaul Walmsley /*
632e4707dd3SPaul Walmsley * Non-cacheable Normal - intended for memory areas that must
633e4707dd3SPaul Walmsley * not cause dirty cache line writebacks when used
634e4707dd3SPaul Walmsley */
635e4707dd3SPaul Walmsley if (cpu_arch >= CPU_ARCH_ARMv6) {
636e4707dd3SPaul Walmsley if (cpu_arch >= CPU_ARCH_ARMv7 && (cr & CR_TRE)) {
637e4707dd3SPaul Walmsley /* Non-cacheable Normal is XCB = 001 */
6382e2c9de2SRussell King mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |=
639e4707dd3SPaul Walmsley PMD_SECT_BUFFERED;
640e4707dd3SPaul Walmsley } else {
641e4707dd3SPaul Walmsley /* For both ARMv6 and non-TEX-remapping ARMv7 */
6422e2c9de2SRussell King mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |=
643e4707dd3SPaul Walmsley PMD_SECT_TEX(1);
644e4707dd3SPaul Walmsley }
645e4707dd3SPaul Walmsley } else {
6462e2c9de2SRussell King mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= PMD_SECT_BUFFERABLE;
647e4707dd3SPaul Walmsley }
648e4707dd3SPaul Walmsley
6491b6ba46bSCatalin Marinas #ifdef CONFIG_ARM_LPAE
6501b6ba46bSCatalin Marinas /*
6511b6ba46bSCatalin Marinas * Do not generate access flag faults for the kernel mappings.
6521b6ba46bSCatalin Marinas */
6531b6ba46bSCatalin Marinas for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
6541b6ba46bSCatalin Marinas mem_types[i].prot_pte |= PTE_EXT_AF;
6551a3abcf4SVitaly Andrianov if (mem_types[i].prot_sect)
6561b6ba46bSCatalin Marinas mem_types[i].prot_sect |= PMD_SECT_AF;
6571b6ba46bSCatalin Marinas }
6581b6ba46bSCatalin Marinas kern_pgprot |= PTE_EXT_AF;
6591b6ba46bSCatalin Marinas vecs_pgprot |= PTE_EXT_AF;
6601d4d3715SJungseung Lee
6611d4d3715SJungseung Lee /*
6621d4d3715SJungseung Lee * Set PXN for user mappings
6631d4d3715SJungseung Lee */
6641d4d3715SJungseung Lee user_pgprot |= PTE_EXT_PXN;
6651b6ba46bSCatalin Marinas #endif
6661b6ba46bSCatalin Marinas
667ae8f1541SRussell King for (i = 0; i < 16; i++) {
668864aa04cSWill Deacon pteval_t v = pgprot_val(protection_map[i]);
669bb30f36fSRussell King protection_map[i] = __pgprot(v | user_pgprot);
670ae8f1541SRussell King }
671ae8f1541SRussell King
672bb30f36fSRussell King mem_types[MT_LOW_VECTORS].prot_pte |= vecs_pgprot;
673bb30f36fSRussell King mem_types[MT_HIGH_VECTORS].prot_pte |= vecs_pgprot;
674ae8f1541SRussell King
67544b18693SImre_Deak pgprot_user = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG | user_pgprot);
676ae8f1541SRussell King pgprot_kernel = __pgprot(L_PTE_PRESENT | L_PTE_YOUNG |
67736bb94baSRussell King L_PTE_DIRTY | kern_pgprot);
678ae8f1541SRussell King
679ae8f1541SRussell King mem_types[MT_LOW_VECTORS].prot_l1 |= ecc_mask;
680ae8f1541SRussell King mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
6812e2c9de2SRussell King mem_types[MT_MEMORY_RWX].prot_sect |= ecc_mask | cp->pmd;
6822e2c9de2SRussell King mem_types[MT_MEMORY_RWX].prot_pte |= kern_pgprot;
683ebd4922eSRussell King mem_types[MT_MEMORY_RW].prot_sect |= ecc_mask | cp->pmd;
684ebd4922eSRussell King mem_types[MT_MEMORY_RW].prot_pte |= kern_pgprot;
685598f0a99SZhen Lei mem_types[MT_MEMORY_RO].prot_sect |= ecc_mask | cp->pmd;
686598f0a99SZhen Lei mem_types[MT_MEMORY_RO].prot_pte |= kern_pgprot;
687c7909509SMarek Szyprowski mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
6882e2c9de2SRussell King mem_types[MT_MEMORY_RWX_NONCACHED].prot_sect |= ecc_mask;
689ae8f1541SRussell King mem_types[MT_ROM].prot_sect |= cp->pmd;
690ae8f1541SRussell King
691ae8f1541SRussell King switch (cp->pmd) {
692ae8f1541SRussell King case PMD_SECT_WT:
693ae8f1541SRussell King mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WT;
694ae8f1541SRussell King break;
695ae8f1541SRussell King case PMD_SECT_WB:
696ae8f1541SRussell King case PMD_SECT_WBWA:
697ae8f1541SRussell King mem_types[MT_CACHECLEAN].prot_sect |= PMD_SECT_WB;
698ae8f1541SRussell King break;
699ae8f1541SRussell King }
700905b5797SMichal Simek pr_info("Memory policy: %sData cache %s\n",
701905b5797SMichal Simek ecc_mask ? "ECC enabled, " : "", cp->policy);
7022497f0a8SRussell King
7032497f0a8SRussell King for (i = 0; i < ARRAY_SIZE(mem_types); i++) {
7042497f0a8SRussell King struct mem_type *t = &mem_types[i];
7052497f0a8SRussell King if (t->prot_l1)
7062497f0a8SRussell King t->prot_l1 |= PMD_DOMAIN(t->domain);
7072497f0a8SRussell King if (t->prot_sect)
7082497f0a8SRussell King t->prot_sect |= PMD_DOMAIN(t->domain);
7092497f0a8SRussell King }
710ae8f1541SRussell King }
711ae8f1541SRussell King
712d907387cSCatalin Marinas #ifdef CONFIG_ARM_DMA_MEM_BUFFERABLE
phys_mem_access_prot(struct file * file,unsigned long pfn,unsigned long size,pgprot_t vma_prot)713d907387cSCatalin Marinas pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
714d907387cSCatalin Marinas unsigned long size, pgprot_t vma_prot)
715d907387cSCatalin Marinas {
716d907387cSCatalin Marinas if (!pfn_valid(pfn))
717d907387cSCatalin Marinas return pgprot_noncached(vma_prot);
718d907387cSCatalin Marinas else if (file->f_flags & O_SYNC)
719d907387cSCatalin Marinas return pgprot_writecombine(vma_prot);
720d907387cSCatalin Marinas return vma_prot;
721d907387cSCatalin Marinas }
722d907387cSCatalin Marinas EXPORT_SYMBOL(phys_mem_access_prot);
723d907387cSCatalin Marinas #endif
724d907387cSCatalin Marinas
725ae8f1541SRussell King #define vectors_base() (vectors_high() ? 0xffff0000 : 0)
726ae8f1541SRussell King
early_alloc(unsigned long sz)7270536bdf3SNicolas Pitre static void __init *early_alloc(unsigned long sz)
7280536bdf3SNicolas Pitre {
7298a7f97b9SMike Rapoport void *ptr = memblock_alloc(sz, sz);
7308a7f97b9SMike Rapoport
7318a7f97b9SMike Rapoport if (!ptr)
7328a7f97b9SMike Rapoport panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
7338a7f97b9SMike Rapoport __func__, sz, sz);
7348a7f97b9SMike Rapoport
7358a7f97b9SMike Rapoport return ptr;
7360536bdf3SNicolas Pitre }
7370536bdf3SNicolas Pitre
late_alloc(unsigned long sz)738c7936206SArd Biesheuvel static void *__init late_alloc(unsigned long sz)
739c7936206SArd Biesheuvel {
740358d1c39SVishal Moola (Oracle) void *ptdesc = pagetable_alloc(GFP_PGTABLE_KERNEL & ~__GFP_HIGHMEM,
741358d1c39SVishal Moola (Oracle) get_order(sz));
742c7936206SArd Biesheuvel
743358d1c39SVishal Moola (Oracle) if (!ptdesc || !pagetable_pte_ctor(ptdesc))
74461444cdeSArd Biesheuvel BUG();
745358d1c39SVishal Moola (Oracle) return ptdesc_to_virt(ptdesc);
746c7936206SArd Biesheuvel }
747c7936206SArd Biesheuvel
arm_pte_alloc(pmd_t * pmd,unsigned long addr,unsigned long prot,void * (* alloc)(unsigned long sz))7483ed3a4f0SKirill A. Shutemov static pte_t * __init arm_pte_alloc(pmd_t *pmd, unsigned long addr,
749f579b2b1SArd Biesheuvel unsigned long prot,
750f579b2b1SArd Biesheuvel void *(*alloc)(unsigned long sz))
7514bb2e27dSRussell King {
7524bb2e27dSRussell King if (pmd_none(*pmd)) {
753f579b2b1SArd Biesheuvel pte_t *pte = alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
75497092e0cSRussell King __pmd_populate(pmd, __pa(pte), prot);
7554bb2e27dSRussell King }
7564bb2e27dSRussell King BUG_ON(pmd_bad(*pmd));
7574bb2e27dSRussell King return pte_offset_kernel(pmd, addr);
7584bb2e27dSRussell King }
7594bb2e27dSRussell King
early_pte_alloc(pmd_t * pmd,unsigned long addr,unsigned long prot)760f579b2b1SArd Biesheuvel static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
761f579b2b1SArd Biesheuvel unsigned long prot)
762f579b2b1SArd Biesheuvel {
7633ed3a4f0SKirill A. Shutemov return arm_pte_alloc(pmd, addr, prot, early_alloc);
764f579b2b1SArd Biesheuvel }
765f579b2b1SArd Biesheuvel
alloc_init_pte(pmd_t * pmd,unsigned long addr,unsigned long end,unsigned long pfn,const struct mem_type * type,void * (* alloc)(unsigned long sz),bool ng)76624e6c699SRussell King static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
76724e6c699SRussell King unsigned long end, unsigned long pfn,
768f579b2b1SArd Biesheuvel const struct mem_type *type,
769b430e55bSArd Biesheuvel void *(*alloc)(unsigned long sz),
770b430e55bSArd Biesheuvel bool ng)
771ae8f1541SRussell King {
7723ed3a4f0SKirill A. Shutemov pte_t *pte = arm_pte_alloc(pmd, addr, type->prot_l1, alloc);
77324e6c699SRussell King do {
774b430e55bSArd Biesheuvel set_pte_ext(pte, pfn_pte(pfn, __pgprot(type->prot_pte)),
775b430e55bSArd Biesheuvel ng ? PTE_EXT_NG : 0);
77624e6c699SRussell King pfn++;
77724e6c699SRussell King } while (pte++, addr += PAGE_SIZE, addr != end);
778ae8f1541SRussell King }
779ae8f1541SRussell King
__map_init_section(pmd_t * pmd,unsigned long addr,unsigned long end,phys_addr_t phys,const struct mem_type * type,bool ng)78037468b30SPo-Yu Chuang static void __init __map_init_section(pmd_t *pmd, unsigned long addr,
78197092e0cSRussell King unsigned long end, phys_addr_t phys,
782b430e55bSArd Biesheuvel const struct mem_type *type, bool ng)
78324e6c699SRussell King {
78437468b30SPo-Yu Chuang pmd_t *p = pmd;
78537468b30SPo-Yu Chuang
7861b6ba46bSCatalin Marinas #ifndef CONFIG_ARM_LPAE
787e651eab0SSricharan R /*
788e651eab0SSricharan R * In classic MMU format, puds and pmds are folded in to
789e651eab0SSricharan R * the pgds. pmd_offset gives the PGD entry. PGDs refer to a
790e651eab0SSricharan R * group of L1 entries making up one logical pointer to
791e651eab0SSricharan R * an L2 table (2MB), where as PMDs refer to the individual
792e651eab0SSricharan R * L1 entries (1MB). Hence increment to get the correct
793e651eab0SSricharan R * offset for odd 1MB sections.
794e651eab0SSricharan R * (See arch/arm/include/asm/pgtable-2level.h)
795e651eab0SSricharan R */
79624e6c699SRussell King if (addr & SECTION_SIZE)
79724e6c699SRussell King pmd++;
7981b6ba46bSCatalin Marinas #endif
79924e6c699SRussell King do {
800b430e55bSArd Biesheuvel *pmd = __pmd(phys | type->prot_sect | (ng ? PMD_SECT_nG : 0));
80124e6c699SRussell King phys += SECTION_SIZE;
80224e6c699SRussell King } while (pmd++, addr += SECTION_SIZE, addr != end);
80324e6c699SRussell King
80437468b30SPo-Yu Chuang flush_pmd_entry(p);
80524e6c699SRussell King }
806e651eab0SSricharan R
alloc_init_pmd(pud_t * pud,unsigned long addr,unsigned long end,phys_addr_t phys,const struct mem_type * type,void * (* alloc)(unsigned long sz),bool ng)807e651eab0SSricharan R static void __init alloc_init_pmd(pud_t *pud, unsigned long addr,
808e651eab0SSricharan R unsigned long end, phys_addr_t phys,
809f579b2b1SArd Biesheuvel const struct mem_type *type,
810b430e55bSArd Biesheuvel void *(*alloc)(unsigned long sz), bool ng)
811e651eab0SSricharan R {
812e651eab0SSricharan R pmd_t *pmd = pmd_offset(pud, addr);
813e651eab0SSricharan R unsigned long next;
814e651eab0SSricharan R
815e651eab0SSricharan R do {
816e651eab0SSricharan R /*
817e651eab0SSricharan R * With LPAE, we must loop over to map
818e651eab0SSricharan R * all the pmds for the given range.
819e651eab0SSricharan R */
820e651eab0SSricharan R next = pmd_addr_end(addr, end);
821e651eab0SSricharan R
822e651eab0SSricharan R /*
823e651eab0SSricharan R * Try a section mapping - addr, next and phys must all be
824e651eab0SSricharan R * aligned to a section boundary.
825e651eab0SSricharan R */
826e651eab0SSricharan R if (type->prot_sect &&
827e651eab0SSricharan R ((addr | next | phys) & ~SECTION_MASK) == 0) {
828b430e55bSArd Biesheuvel __map_init_section(pmd, addr, next, phys, type, ng);
829e651eab0SSricharan R } else {
830e651eab0SSricharan R alloc_init_pte(pmd, addr, next,
831b430e55bSArd Biesheuvel __phys_to_pfn(phys), type, alloc, ng);
832e651eab0SSricharan R }
833e651eab0SSricharan R
834e651eab0SSricharan R phys += next - addr;
835e651eab0SSricharan R
836e651eab0SSricharan R } while (pmd++, addr = next, addr != end);
837ae8f1541SRussell King }
838ae8f1541SRussell King
alloc_init_pud(p4d_t * p4d,unsigned long addr,unsigned long end,phys_addr_t phys,const struct mem_type * type,void * (* alloc)(unsigned long sz),bool ng)83984e6ffb2SMike Rapoport static void __init alloc_init_pud(p4d_t *p4d, unsigned long addr,
84020d6956dSVitaly Andrianov unsigned long end, phys_addr_t phys,
841f579b2b1SArd Biesheuvel const struct mem_type *type,
842b430e55bSArd Biesheuvel void *(*alloc)(unsigned long sz), bool ng)
843516295e5SRussell King {
84484e6ffb2SMike Rapoport pud_t *pud = pud_offset(p4d, addr);
845516295e5SRussell King unsigned long next;
846516295e5SRussell King
847516295e5SRussell King do {
848516295e5SRussell King next = pud_addr_end(addr, end);
849b430e55bSArd Biesheuvel alloc_init_pmd(pud, addr, next, phys, type, alloc, ng);
850516295e5SRussell King phys += next - addr;
851516295e5SRussell King } while (pud++, addr = next, addr != end);
852516295e5SRussell King }
853516295e5SRussell King
alloc_init_p4d(pgd_t * pgd,unsigned long addr,unsigned long end,phys_addr_t phys,const struct mem_type * type,void * (* alloc)(unsigned long sz),bool ng)85484e6ffb2SMike Rapoport static void __init alloc_init_p4d(pgd_t *pgd, unsigned long addr,
85584e6ffb2SMike Rapoport unsigned long end, phys_addr_t phys,
85684e6ffb2SMike Rapoport const struct mem_type *type,
85784e6ffb2SMike Rapoport void *(*alloc)(unsigned long sz), bool ng)
85884e6ffb2SMike Rapoport {
85984e6ffb2SMike Rapoport p4d_t *p4d = p4d_offset(pgd, addr);
86084e6ffb2SMike Rapoport unsigned long next;
86184e6ffb2SMike Rapoport
86284e6ffb2SMike Rapoport do {
86384e6ffb2SMike Rapoport next = p4d_addr_end(addr, end);
86484e6ffb2SMike Rapoport alloc_init_pud(p4d, addr, next, phys, type, alloc, ng);
86584e6ffb2SMike Rapoport phys += next - addr;
86684e6ffb2SMike Rapoport } while (p4d++, addr = next, addr != end);
86784e6ffb2SMike Rapoport }
86884e6ffb2SMike Rapoport
8691b6ba46bSCatalin Marinas #ifndef CONFIG_ARM_LPAE
create_36bit_mapping(struct mm_struct * mm,struct map_desc * md,const struct mem_type * type,bool ng)8701bdb2d4eSArd Biesheuvel static void __init create_36bit_mapping(struct mm_struct *mm,
8711bdb2d4eSArd Biesheuvel struct map_desc *md,
872b430e55bSArd Biesheuvel const struct mem_type *type,
873b430e55bSArd Biesheuvel bool ng)
8744a56c1e4SRussell King {
87597092e0cSRussell King unsigned long addr, length, end;
87697092e0cSRussell King phys_addr_t phys;
8774a56c1e4SRussell King pgd_t *pgd;
8784a56c1e4SRussell King
8794a56c1e4SRussell King addr = md->virtual;
880cae6292bSWill Deacon phys = __pfn_to_phys(md->pfn);
8814a56c1e4SRussell King length = PAGE_ALIGN(md->length);
8824a56c1e4SRussell King
8834a56c1e4SRussell King if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
8844ed89f22SRussell King pr_err("MM: CPU does not support supersection mapping for 0x%08llx at 0x%08lx\n",
88529a38193SWill Deacon (long long)__pfn_to_phys((u64)md->pfn), addr);
8864a56c1e4SRussell King return;
8874a56c1e4SRussell King }
8884a56c1e4SRussell King
8894a56c1e4SRussell King /* N.B. ARMv6 supersections are only defined to work with domain 0.
8904a56c1e4SRussell King * Since domain assignments can in fact be arbitrary, the
8914a56c1e4SRussell King * 'domain == 0' check below is required to insure that ARMv6
8924a56c1e4SRussell King * supersections are only allocated for domain 0 regardless
8934a56c1e4SRussell King * of the actual domain assignments in use.
8944a56c1e4SRussell King */
8954a56c1e4SRussell King if (type->domain) {
8964ed89f22SRussell King pr_err("MM: invalid domain in supersection mapping for 0x%08llx at 0x%08lx\n",
89729a38193SWill Deacon (long long)__pfn_to_phys((u64)md->pfn), addr);
8984a56c1e4SRussell King return;
8994a56c1e4SRussell King }
9004a56c1e4SRussell King
9014a56c1e4SRussell King if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) {
9024ed89f22SRussell King pr_err("MM: cannot create mapping for 0x%08llx at 0x%08lx invalid alignment\n",
90329a38193SWill Deacon (long long)__pfn_to_phys((u64)md->pfn), addr);
9044a56c1e4SRussell King return;
9054a56c1e4SRussell King }
9064a56c1e4SRussell King
9074a56c1e4SRussell King /*
9084a56c1e4SRussell King * Shift bits [35:32] of address into bits [23:20] of PMD
9094a56c1e4SRussell King * (See ARMv6 spec).
9104a56c1e4SRussell King */
9114a56c1e4SRussell King phys |= (((md->pfn >> (32 - PAGE_SHIFT)) & 0xF) << 20);
9124a56c1e4SRussell King
9131bdb2d4eSArd Biesheuvel pgd = pgd_offset(mm, addr);
9144a56c1e4SRussell King end = addr + length;
9154a56c1e4SRussell King do {
91684e6ffb2SMike Rapoport p4d_t *p4d = p4d_offset(pgd, addr);
91784e6ffb2SMike Rapoport pud_t *pud = pud_offset(p4d, addr);
918516295e5SRussell King pmd_t *pmd = pmd_offset(pud, addr);
9194a56c1e4SRussell King int i;
9204a56c1e4SRussell King
9214a56c1e4SRussell King for (i = 0; i < 16; i++)
922b430e55bSArd Biesheuvel *pmd++ = __pmd(phys | type->prot_sect | PMD_SECT_SUPER |
923b430e55bSArd Biesheuvel (ng ? PMD_SECT_nG : 0));
9244a56c1e4SRussell King
9254a56c1e4SRussell King addr += SUPERSECTION_SIZE;
9264a56c1e4SRussell King phys += SUPERSECTION_SIZE;
9274a56c1e4SRussell King pgd += SUPERSECTION_SIZE >> PGDIR_SHIFT;
9284a56c1e4SRussell King } while (addr != end);
9294a56c1e4SRussell King }
9301b6ba46bSCatalin Marinas #endif /* !CONFIG_ARM_LPAE */
9314a56c1e4SRussell King
__create_mapping(struct mm_struct * mm,struct map_desc * md,void * (* alloc)(unsigned long sz),bool ng)932f579b2b1SArd Biesheuvel static void __init __create_mapping(struct mm_struct *mm, struct map_desc *md,
933b430e55bSArd Biesheuvel void *(*alloc)(unsigned long sz),
934b430e55bSArd Biesheuvel bool ng)
935ae8f1541SRussell King {
936cae6292bSWill Deacon unsigned long addr, length, end;
937cae6292bSWill Deacon phys_addr_t phys;
938d5c98176SRussell King const struct mem_type *type;
93924e6c699SRussell King pgd_t *pgd;
940ae8f1541SRussell King
941d5c98176SRussell King type = &mem_types[md->type];
942ae8f1541SRussell King
9431b6ba46bSCatalin Marinas #ifndef CONFIG_ARM_LPAE
944ae8f1541SRussell King /*
945ae8f1541SRussell King * Catch 36-bit addresses
946ae8f1541SRussell King */
947ae8f1541SRussell King if (md->pfn >= 0x100000) {
948b430e55bSArd Biesheuvel create_36bit_mapping(mm, md, type, ng);
949ae8f1541SRussell King return;
950ae8f1541SRussell King }
9511b6ba46bSCatalin Marinas #endif
952ae8f1541SRussell King
9537b9c7b4dSRussell King addr = md->virtual & PAGE_MASK;
954cae6292bSWill Deacon phys = __pfn_to_phys(md->pfn);
9557b9c7b4dSRussell King length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
956ae8f1541SRussell King
95724e6c699SRussell King if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
9584ed89f22SRussell King pr_warn("BUG: map for 0x%08llx at 0x%08lx can not be mapped using pages, ignoring.\n",
95929a38193SWill Deacon (long long)__pfn_to_phys(md->pfn), addr);
960ae8f1541SRussell King return;
961ae8f1541SRussell King }
962ae8f1541SRussell King
9631bdb2d4eSArd Biesheuvel pgd = pgd_offset(mm, addr);
96424e6c699SRussell King end = addr + length;
96524e6c699SRussell King do {
96624e6c699SRussell King unsigned long next = pgd_addr_end(addr, end);
967ae8f1541SRussell King
96884e6ffb2SMike Rapoport alloc_init_p4d(pgd, addr, next, phys, type, alloc, ng);
969ae8f1541SRussell King
97024e6c699SRussell King phys += next - addr;
97124e6c699SRussell King addr = next;
97224e6c699SRussell King } while (pgd++, addr != end);
973ae8f1541SRussell King }
974ae8f1541SRussell King
975ae8f1541SRussell King /*
9761bdb2d4eSArd Biesheuvel * Create the page directory entries and any necessary
9771bdb2d4eSArd Biesheuvel * page tables for the mapping specified by `md'. We
9781bdb2d4eSArd Biesheuvel * are able to cope here with varying sizes and address
9791bdb2d4eSArd Biesheuvel * offsets, and we take full advantage of sections and
9801bdb2d4eSArd Biesheuvel * supersections.
9811bdb2d4eSArd Biesheuvel */
create_mapping(struct map_desc * md)9821bdb2d4eSArd Biesheuvel static void __init create_mapping(struct map_desc *md)
9831bdb2d4eSArd Biesheuvel {
9841bdb2d4eSArd Biesheuvel if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
9851bdb2d4eSArd Biesheuvel pr_warn("BUG: not creating mapping for 0x%08llx at 0x%08lx in user region\n",
9861bdb2d4eSArd Biesheuvel (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
9871bdb2d4eSArd Biesheuvel return;
9881bdb2d4eSArd Biesheuvel }
9891bdb2d4eSArd Biesheuvel
9907a1be318SArd Biesheuvel if (md->type == MT_DEVICE &&
9911bdb2d4eSArd Biesheuvel md->virtual >= PAGE_OFFSET && md->virtual < FIXADDR_START &&
9921bdb2d4eSArd Biesheuvel (md->virtual < VMALLOC_START || md->virtual >= VMALLOC_END)) {
9931bdb2d4eSArd Biesheuvel pr_warn("BUG: mapping for 0x%08llx at 0x%08lx out of vmalloc space\n",
9941bdb2d4eSArd Biesheuvel (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
9951bdb2d4eSArd Biesheuvel }
9961bdb2d4eSArd Biesheuvel
997b430e55bSArd Biesheuvel __create_mapping(&init_mm, md, early_alloc, false);
9981bdb2d4eSArd Biesheuvel }
9991bdb2d4eSArd Biesheuvel
create_mapping_late(struct mm_struct * mm,struct map_desc * md,bool ng)1000c7936206SArd Biesheuvel void __init create_mapping_late(struct mm_struct *mm, struct map_desc *md,
1001c7936206SArd Biesheuvel bool ng)
1002c7936206SArd Biesheuvel {
1003c7936206SArd Biesheuvel #ifdef CONFIG_ARM_LPAE
100484e6ffb2SMike Rapoport p4d_t *p4d;
100584e6ffb2SMike Rapoport pud_t *pud;
100684e6ffb2SMike Rapoport
100784e6ffb2SMike Rapoport p4d = p4d_alloc(mm, pgd_offset(mm, md->virtual), md->virtual);
10085c6360eeSArd Biesheuvel if (WARN_ON(!p4d))
100984e6ffb2SMike Rapoport return;
101084e6ffb2SMike Rapoport pud = pud_alloc(mm, p4d, md->virtual);
1011c7936206SArd Biesheuvel if (WARN_ON(!pud))
1012c7936206SArd Biesheuvel return;
1013c7936206SArd Biesheuvel pmd_alloc(mm, pud, 0);
1014c7936206SArd Biesheuvel #endif
1015c7936206SArd Biesheuvel __create_mapping(mm, md, late_alloc, ng);
1016c7936206SArd Biesheuvel }
1017c7936206SArd Biesheuvel
10181bdb2d4eSArd Biesheuvel /*
1019ae8f1541SRussell King * Create the architecture specific mappings
1020ae8f1541SRussell King */
iotable_init(struct map_desc * io_desc,int nr)1021ae8f1541SRussell King void __init iotable_init(struct map_desc *io_desc, int nr)
1022ae8f1541SRussell King {
10230536bdf3SNicolas Pitre struct map_desc *md;
10240536bdf3SNicolas Pitre struct vm_struct *vm;
1025101eeda3SJoonsoo Kim struct static_vm *svm;
1026ae8f1541SRussell King
10270536bdf3SNicolas Pitre if (!nr)
10280536bdf3SNicolas Pitre return;
10290536bdf3SNicolas Pitre
1030c2938eebSMike Rapoport svm = memblock_alloc(sizeof(*svm) * nr, __alignof__(*svm));
10318a7f97b9SMike Rapoport if (!svm)
10328a7f97b9SMike Rapoport panic("%s: Failed to allocate %zu bytes align=0x%zx\n",
10338a7f97b9SMike Rapoport __func__, sizeof(*svm) * nr, __alignof__(*svm));
10340536bdf3SNicolas Pitre
10350536bdf3SNicolas Pitre for (md = io_desc; nr; md++, nr--) {
10360536bdf3SNicolas Pitre create_mapping(md);
1037101eeda3SJoonsoo Kim
1038101eeda3SJoonsoo Kim vm = &svm->vm;
10390536bdf3SNicolas Pitre vm->addr = (void *)(md->virtual & PAGE_MASK);
10400536bdf3SNicolas Pitre vm->size = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
10410536bdf3SNicolas Pitre vm->phys_addr = __pfn_to_phys(md->pfn);
1042576d2f25SNicolas Pitre vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
1043576d2f25SNicolas Pitre vm->flags |= VM_ARM_MTYPE(md->type);
10440536bdf3SNicolas Pitre vm->caller = iotable_init;
1045101eeda3SJoonsoo Kim add_static_vm_early(svm++);
10460536bdf3SNicolas Pitre }
1047ae8f1541SRussell King }
1048ae8f1541SRussell King
vm_reserve_area_early(unsigned long addr,unsigned long size,void * caller)1049c2794437SRob Herring void __init vm_reserve_area_early(unsigned long addr, unsigned long size,
1050c2794437SRob Herring void *caller)
1051c2794437SRob Herring {
1052c2794437SRob Herring struct vm_struct *vm;
1053101eeda3SJoonsoo Kim struct static_vm *svm;
1054c2794437SRob Herring
1055c2938eebSMike Rapoport svm = memblock_alloc(sizeof(*svm), __alignof__(*svm));
10568a7f97b9SMike Rapoport if (!svm)
10578a7f97b9SMike Rapoport panic("%s: Failed to allocate %zu bytes align=0x%zx\n",
10588a7f97b9SMike Rapoport __func__, sizeof(*svm), __alignof__(*svm));
1059101eeda3SJoonsoo Kim
1060101eeda3SJoonsoo Kim vm = &svm->vm;
1061c2794437SRob Herring vm->addr = (void *)addr;
1062c2794437SRob Herring vm->size = size;
1063863e99a8SArnd Bergmann vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING;
1064c2794437SRob Herring vm->caller = caller;
1065101eeda3SJoonsoo Kim add_static_vm_early(svm);
1066c2794437SRob Herring }
1067c2794437SRob Herring
106819b52abeSNicolas Pitre #ifndef CONFIG_ARM_LPAE
106919b52abeSNicolas Pitre
107019b52abeSNicolas Pitre /*
107119b52abeSNicolas Pitre * The Linux PMD is made of two consecutive section entries covering 2MB
107219b52abeSNicolas Pitre * (see definition in include/asm/pgtable-2level.h). However a call to
107319b52abeSNicolas Pitre * create_mapping() may optimize static mappings by using individual
107419b52abeSNicolas Pitre * 1MB section mappings. This leaves the actual PMD potentially half
107519b52abeSNicolas Pitre * initialized if the top or bottom section entry isn't used, leaving it
107619b52abeSNicolas Pitre * open to problems if a subsequent ioremap() or vmalloc() tries to use
107719b52abeSNicolas Pitre * the virtual space left free by that unused section entry.
107819b52abeSNicolas Pitre *
107919b52abeSNicolas Pitre * Let's avoid the issue by inserting dummy vm entries covering the unused
108019b52abeSNicolas Pitre * PMD halves once the static mappings are in place.
108119b52abeSNicolas Pitre */
108219b52abeSNicolas Pitre
pmd_empty_section_gap(unsigned long addr)108319b52abeSNicolas Pitre static void __init pmd_empty_section_gap(unsigned long addr)
108419b52abeSNicolas Pitre {
1085c2794437SRob Herring vm_reserve_area_early(addr, SECTION_SIZE, pmd_empty_section_gap);
108619b52abeSNicolas Pitre }
108719b52abeSNicolas Pitre
fill_pmd_gaps(void)108819b52abeSNicolas Pitre static void __init fill_pmd_gaps(void)
108919b52abeSNicolas Pitre {
1090101eeda3SJoonsoo Kim struct static_vm *svm;
109119b52abeSNicolas Pitre struct vm_struct *vm;
109219b52abeSNicolas Pitre unsigned long addr, next = 0;
109319b52abeSNicolas Pitre pmd_t *pmd;
109419b52abeSNicolas Pitre
1095101eeda3SJoonsoo Kim list_for_each_entry(svm, &static_vmlist, list) {
1096101eeda3SJoonsoo Kim vm = &svm->vm;
109719b52abeSNicolas Pitre addr = (unsigned long)vm->addr;
109819b52abeSNicolas Pitre if (addr < next)
109919b52abeSNicolas Pitre continue;
110019b52abeSNicolas Pitre
110119b52abeSNicolas Pitre /*
110219b52abeSNicolas Pitre * Check if this vm starts on an odd section boundary.
110319b52abeSNicolas Pitre * If so and the first section entry for this PMD is free
110419b52abeSNicolas Pitre * then we block the corresponding virtual address.
110519b52abeSNicolas Pitre */
110619b52abeSNicolas Pitre if ((addr & ~PMD_MASK) == SECTION_SIZE) {
110719b52abeSNicolas Pitre pmd = pmd_off_k(addr);
110819b52abeSNicolas Pitre if (pmd_none(*pmd))
110919b52abeSNicolas Pitre pmd_empty_section_gap(addr & PMD_MASK);
111019b52abeSNicolas Pitre }
111119b52abeSNicolas Pitre
111219b52abeSNicolas Pitre /*
111319b52abeSNicolas Pitre * Then check if this vm ends on an odd section boundary.
111419b52abeSNicolas Pitre * If so and the second section entry for this PMD is empty
111519b52abeSNicolas Pitre * then we block the corresponding virtual address.
111619b52abeSNicolas Pitre */
111719b52abeSNicolas Pitre addr += vm->size;
111819b52abeSNicolas Pitre if ((addr & ~PMD_MASK) == SECTION_SIZE) {
111919b52abeSNicolas Pitre pmd = pmd_off_k(addr) + 1;
112019b52abeSNicolas Pitre if (pmd_none(*pmd))
112119b52abeSNicolas Pitre pmd_empty_section_gap(addr);
112219b52abeSNicolas Pitre }
112319b52abeSNicolas Pitre
112419b52abeSNicolas Pitre /* no need to look at any vm entry until we hit the next PMD */
112519b52abeSNicolas Pitre next = (addr + PMD_SIZE - 1) & PMD_MASK;
112619b52abeSNicolas Pitre }
112719b52abeSNicolas Pitre }
112819b52abeSNicolas Pitre
112919b52abeSNicolas Pitre #else
113019b52abeSNicolas Pitre #define fill_pmd_gaps() do { } while (0)
113119b52abeSNicolas Pitre #endif
113219b52abeSNicolas Pitre
1133c2794437SRob Herring #if defined(CONFIG_PCI) && !defined(CONFIG_NEED_MACH_IO_H)
pci_reserve_io(void)1134c2794437SRob Herring static void __init pci_reserve_io(void)
1135c2794437SRob Herring {
1136101eeda3SJoonsoo Kim struct static_vm *svm;
1137c2794437SRob Herring
1138101eeda3SJoonsoo Kim svm = find_static_vm_vaddr((void *)PCI_IO_VIRT_BASE);
1139101eeda3SJoonsoo Kim if (svm)
1140c2794437SRob Herring return;
1141c2794437SRob Herring
1142c2794437SRob Herring vm_reserve_area_early(PCI_IO_VIRT_BASE, SZ_2M, pci_reserve_io);
1143c2794437SRob Herring }
1144c2794437SRob Herring #else
1145c2794437SRob Herring #define pci_reserve_io() do { } while (0)
1146c2794437SRob Herring #endif
1147c2794437SRob Herring
1148e5c5f2adSRob Herring #ifdef CONFIG_DEBUG_LL
debug_ll_io_init(void)1149e5c5f2adSRob Herring void __init debug_ll_io_init(void)
1150e5c5f2adSRob Herring {
1151e5c5f2adSRob Herring struct map_desc map;
1152e5c5f2adSRob Herring
1153e5c5f2adSRob Herring debug_ll_addr(&map.pfn, &map.virtual);
1154e5c5f2adSRob Herring if (!map.pfn || !map.virtual)
1155e5c5f2adSRob Herring return;
1156e5c5f2adSRob Herring map.pfn = __phys_to_pfn(map.pfn);
1157e5c5f2adSRob Herring map.virtual &= PAGE_MASK;
1158e5c5f2adSRob Herring map.length = PAGE_SIZE;
1159e5c5f2adSRob Herring map.type = MT_DEVICE;
1160ee4de5d9SStephen Boyd iotable_init(&map, 1);
1161e5c5f2adSRob Herring }
1162e5c5f2adSRob Herring #endif
1163e5c5f2adSRob Herring
116408b84240SRussell King (Oracle) static unsigned long __initdata vmalloc_size = 240 * SZ_1M;
11656c5da7acSRussell King
11666c5da7acSRussell King /*
11676c5da7acSRussell King * vmalloc=size forces the vmalloc area to be exactly 'size'
11686c5da7acSRussell King * bytes. This can be used to increase (or decrease) the vmalloc
1169c01914efSRussell King (Oracle) * area - the default is 240MiB.
11706c5da7acSRussell King */
early_vmalloc(char * arg)11712b0d8c25SJeremy Kerr static int __init early_vmalloc(char *arg)
11726c5da7acSRussell King {
117379612395SRussell King unsigned long vmalloc_reserve = memparse(arg, NULL);
11744f706b07SRussell King (Oracle) unsigned long vmalloc_max;
11756c5da7acSRussell King
11766c5da7acSRussell King if (vmalloc_reserve < SZ_16M) {
11776c5da7acSRussell King vmalloc_reserve = SZ_16M;
1178c01914efSRussell King (Oracle) pr_warn("vmalloc area is too small, limiting to %luMiB\n",
11796c5da7acSRussell King vmalloc_reserve >> 20);
11806c5da7acSRussell King }
11819210807cSNicolas Pitre
1182f572f5cbSRussell King (Oracle) vmalloc_max = VMALLOC_END - (PAGE_OFFSET + SZ_32M + VMALLOC_OFFSET);
11834f706b07SRussell King (Oracle) if (vmalloc_reserve > vmalloc_max) {
11844f706b07SRussell King (Oracle) vmalloc_reserve = vmalloc_max;
1185c01914efSRussell King (Oracle) pr_warn("vmalloc area is too big, limiting to %luMiB\n",
11869210807cSNicolas Pitre vmalloc_reserve >> 20);
11879210807cSNicolas Pitre }
118879612395SRussell King
11894c1b7a76SRussell King (Oracle) vmalloc_size = vmalloc_reserve;
11902b0d8c25SJeremy Kerr return 0;
11916c5da7acSRussell King }
11922b0d8c25SJeremy Kerr early_param("vmalloc", early_vmalloc);
11936c5da7acSRussell King
1194c7909509SMarek Szyprowski phys_addr_t arm_lowmem_limit __initdata = 0;
11958df65168SRussell King
adjust_lowmem_bounds(void)1196374d446dSLaura Abbott void __init adjust_lowmem_bounds(void)
119760296c71SLennert Buytenhek {
1198b10d6bcaSMike Rapoport phys_addr_t block_start, block_end, memblock_limit = 0;
1199b10d6bcaSMike Rapoport u64 vmalloc_limit, i;
120098562656SLaura Abbott phys_addr_t lowmem_limit = 0;
120160296c71SLennert Buytenhek
1202b9a01989SNicolas Pitre /*
1203b9a01989SNicolas Pitre * Let's use our own (unoptimized) equivalent of __pa() that is
1204b9a01989SNicolas Pitre * not affected by wrap-arounds when sizeof(phys_addr_t) == 4.
1205b9a01989SNicolas Pitre * The result is used as the upper bound on physical memory address
1206b9a01989SNicolas Pitre * and may itself be outside the valid range for which phys_addr_t
1207b9a01989SNicolas Pitre * and therefore __pa() is defined.
1208b9a01989SNicolas Pitre */
12094c1b7a76SRussell King (Oracle) vmalloc_limit = (u64)VMALLOC_END - vmalloc_size - VMALLOC_OFFSET -
1210f572f5cbSRussell King (Oracle) PAGE_OFFSET + PHYS_OFFSET;
1211b9a01989SNicolas Pitre
121200d2ec1eSMike Rapoport /*
121300d2ec1eSMike Rapoport * The first usable region must be PMD aligned. Mark its start
121400d2ec1eSMike Rapoport * as MEMBLOCK_NOMAP if it isn't
121500d2ec1eSMike Rapoport */
1216b10d6bcaSMike Rapoport for_each_mem_range(i, &block_start, &block_end) {
1217b10d6bcaSMike Rapoport if (!IS_ALIGNED(block_start, PMD_SIZE)) {
121800d2ec1eSMike Rapoport phys_addr_t len;
121900d2ec1eSMike Rapoport
1220b10d6bcaSMike Rapoport len = round_up(block_start, PMD_SIZE) - block_start;
1221b10d6bcaSMike Rapoport memblock_mark_nomap(block_start, len);
122200d2ec1eSMike Rapoport }
122300d2ec1eSMike Rapoport break;
122400d2ec1eSMike Rapoport }
122500d2ec1eSMike Rapoport
1226b10d6bcaSMike Rapoport for_each_mem_range(i, &block_start, &block_end) {
1227b10d6bcaSMike Rapoport if (block_start < vmalloc_limit) {
122898562656SLaura Abbott if (block_end > lowmem_limit)
1229374d446dSLaura Abbott /*
1230374d446dSLaura Abbott * Compare as u64 to ensure vmalloc_limit does
1231374d446dSLaura Abbott * not get truncated. block_end should always
1232374d446dSLaura Abbott * fit in phys_addr_t so there should be no
1233374d446dSLaura Abbott * issue with assignment.
1234374d446dSLaura Abbott */
123598562656SLaura Abbott lowmem_limit = min_t(u64,
1236374d446dSLaura Abbott vmalloc_limit,
1237374d446dSLaura Abbott block_end);
1238c65b7e98SRussell King
1239c65b7e98SRussell King /*
1240965278dcSMark Rutland * Find the first non-pmd-aligned page, and point
1241c65b7e98SRussell King * memblock_limit at it. This relies on rounding the
1242965278dcSMark Rutland * limit down to be pmd-aligned, which happens at the
1243965278dcSMark Rutland * end of this function.
1244c65b7e98SRussell King *
1245c65b7e98SRussell King * With this algorithm, the start or end of almost any
1246965278dcSMark Rutland * bank can be non-pmd-aligned. The only exception is
1247965278dcSMark Rutland * that the start of the bank 0 must be section-
1248c65b7e98SRussell King * aligned, since otherwise memory would need to be
1249c65b7e98SRussell King * allocated when mapping the start of bank 0, which
1250c65b7e98SRussell King * occurs before any free memory is mapped.
1251c65b7e98SRussell King */
1252c65b7e98SRussell King if (!memblock_limit) {
1253965278dcSMark Rutland if (!IS_ALIGNED(block_start, PMD_SIZE))
12541c2f87c2SLaura Abbott memblock_limit = block_start;
1255965278dcSMark Rutland else if (!IS_ALIGNED(block_end, PMD_SIZE))
125698562656SLaura Abbott memblock_limit = lowmem_limit;
1257c65b7e98SRussell King }
1258e616c591SRussell King
1259e616c591SRussell King }
1260e616c591SRussell King }
12611c2f87c2SLaura Abbott
126298562656SLaura Abbott arm_lowmem_limit = lowmem_limit;
126398562656SLaura Abbott
1264c7909509SMarek Szyprowski high_memory = __va(arm_lowmem_limit - 1) + 1;
1265c65b7e98SRussell King
12669e25ebfeSDoug Berger if (!memblock_limit)
12679e25ebfeSDoug Berger memblock_limit = arm_lowmem_limit;
12689e25ebfeSDoug Berger
1269c65b7e98SRussell King /*
1270965278dcSMark Rutland * Round the memblock limit down to a pmd size. This
1271c65b7e98SRussell King * helps to ensure that we will allocate memory from the
1272965278dcSMark Rutland * last full pmd, which should be mapped.
1273c65b7e98SRussell King */
1274965278dcSMark Rutland memblock_limit = round_down(memblock_limit, PMD_SIZE);
1275c65b7e98SRussell King
1276374d446dSLaura Abbott if (!IS_ENABLED(CONFIG_HIGHMEM) || cache_is_vipt_aliasing()) {
1277374d446dSLaura Abbott if (memblock_end_of_DRAM() > arm_lowmem_limit) {
1278374d446dSLaura Abbott phys_addr_t end = memblock_end_of_DRAM();
1279374d446dSLaura Abbott
1280374d446dSLaura Abbott pr_notice("Ignoring RAM at %pa-%pa\n",
1281374d446dSLaura Abbott &memblock_limit, &end);
1282374d446dSLaura Abbott pr_notice("Consider using a HIGHMEM enabled kernel.\n");
1283374d446dSLaura Abbott
1284374d446dSLaura Abbott memblock_remove(memblock_limit, end - memblock_limit);
1285374d446dSLaura Abbott }
1286374d446dSLaura Abbott }
1287374d446dSLaura Abbott
1288c65b7e98SRussell King memblock_set_current_limit(memblock_limit);
128960296c71SLennert Buytenhek }
129060296c71SLennert Buytenhek
prepare_page_table(void)1291ae7ba761SArnd Bergmann static __init void prepare_page_table(void)
1292d111e8f9SRussell King {
1293d111e8f9SRussell King unsigned long addr;
12948df65168SRussell King phys_addr_t end;
1295d111e8f9SRussell King
1296d111e8f9SRussell King /*
1297d111e8f9SRussell King * Clear out all the mappings below the kernel image.
1298d111e8f9SRussell King */
1299c12366baSLinus Walleij #ifdef CONFIG_KASAN
1300c12366baSLinus Walleij /*
1301c12366baSLinus Walleij * KASan's shadow memory inserts itself between the TASK_SIZE
1302c12366baSLinus Walleij * and MODULES_VADDR. Do not clear the KASan shadow memory mappings.
1303c12366baSLinus Walleij */
1304c12366baSLinus Walleij for (addr = 0; addr < KASAN_SHADOW_START; addr += PMD_SIZE)
1305c12366baSLinus Walleij pmd_clear(pmd_off_k(addr));
1306c12366baSLinus Walleij /*
1307c12366baSLinus Walleij * Skip over the KASan shadow area. KASAN_SHADOW_END is sometimes
1308c12366baSLinus Walleij * equal to MODULES_VADDR and then we exit the pmd clearing. If we
1309c12366baSLinus Walleij * are using a thumb-compiled kernel, there there will be 8MB more
1310c12366baSLinus Walleij * to clear as KASan always offset to 16 MB below MODULES_VADDR.
1311c12366baSLinus Walleij */
1312c12366baSLinus Walleij for (addr = KASAN_SHADOW_END; addr < MODULES_VADDR; addr += PMD_SIZE)
1313c12366baSLinus Walleij pmd_clear(pmd_off_k(addr));
1314c12366baSLinus Walleij #else
1315e73fc88eSCatalin Marinas for (addr = 0; addr < MODULES_VADDR; addr += PMD_SIZE)
1316d111e8f9SRussell King pmd_clear(pmd_off_k(addr));
1317c12366baSLinus Walleij #endif
1318d111e8f9SRussell King
1319d111e8f9SRussell King #ifdef CONFIG_XIP_KERNEL
1320d111e8f9SRussell King /* The XIP kernel is mapped in the module area -- skip over it */
132102afa9a8SChris Brandt addr = ((unsigned long)_exiprom + PMD_SIZE - 1) & PMD_MASK;
1322d111e8f9SRussell King #endif
1323e73fc88eSCatalin Marinas for ( ; addr < PAGE_OFFSET; addr += PMD_SIZE)
1324d111e8f9SRussell King pmd_clear(pmd_off_k(addr));
1325d111e8f9SRussell King
1326d111e8f9SRussell King /*
13278df65168SRussell King * Find the end of the first block of lowmem.
13288df65168SRussell King */
13298df65168SRussell King end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
1330c7909509SMarek Szyprowski if (end >= arm_lowmem_limit)
1331c7909509SMarek Szyprowski end = arm_lowmem_limit;
13328df65168SRussell King
13338df65168SRussell King /*
1334d111e8f9SRussell King * Clear out all the kernel space mappings, except for the first
13350536bdf3SNicolas Pitre * memory bank, up to the vmalloc region.
1336d111e8f9SRussell King */
13378df65168SRussell King for (addr = __phys_to_virt(end);
13380536bdf3SNicolas Pitre addr < VMALLOC_START; addr += PMD_SIZE)
1339d111e8f9SRussell King pmd_clear(pmd_off_k(addr));
1340d111e8f9SRussell King }
1341d111e8f9SRussell King
13421b6ba46bSCatalin Marinas #ifdef CONFIG_ARM_LPAE
13431b6ba46bSCatalin Marinas /* the first page is reserved for pgd */
13441b6ba46bSCatalin Marinas #define SWAPPER_PG_DIR_SIZE (PAGE_SIZE + \
13451b6ba46bSCatalin Marinas PTRS_PER_PGD * PTRS_PER_PMD * sizeof(pmd_t))
13461b6ba46bSCatalin Marinas #else
1347e73fc88eSCatalin Marinas #define SWAPPER_PG_DIR_SIZE (PTRS_PER_PGD * sizeof(pgd_t))
13481b6ba46bSCatalin Marinas #endif
1349e73fc88eSCatalin Marinas
1350d111e8f9SRussell King /*
13512778f620SRussell King * Reserve the special regions of memory
1352d111e8f9SRussell King */
arm_mm_memblock_reserve(void)13532778f620SRussell King void __init arm_mm_memblock_reserve(void)
1354d111e8f9SRussell King {
1355d111e8f9SRussell King /*
1356d111e8f9SRussell King * Reserve the page tables. These are already in use,
1357d111e8f9SRussell King * and can only be in node 0.
1358d111e8f9SRussell King */
1359e73fc88eSCatalin Marinas memblock_reserve(__pa(swapper_pg_dir), SWAPPER_PG_DIR_SIZE);
1360d111e8f9SRussell King
1361d111e8f9SRussell King #ifdef CONFIG_SA1111
1362d111e8f9SRussell King /*
1363d111e8f9SRussell King * Because of the SA1111 DMA bug, we want to preserve our
1364d111e8f9SRussell King * precious DMA-able memory...
1365d111e8f9SRussell King */
13662778f620SRussell King memblock_reserve(PHYS_OFFSET, __pa(swapper_pg_dir) - PHYS_OFFSET);
1367d111e8f9SRussell King #endif
1368d111e8f9SRussell King }
1369d111e8f9SRussell King
1370d111e8f9SRussell King /*
13710536bdf3SNicolas Pitre * Set up the device mappings. Since we clear out the page tables for all
1372a5f4c561SStefan Agner * mappings above VMALLOC_START, except early fixmap, we might remove debug
1373a5f4c561SStefan Agner * device mappings. This means earlycon can be used to debug this function
1374a5f4c561SStefan Agner * Any other function or debugging method which may touch any device _will_
1375a5f4c561SStefan Agner * crash the kernel.
1376d111e8f9SRussell King */
devicemaps_init(const struct machine_desc * mdesc)1377ff69a4c8SRussell King static void __init devicemaps_init(const struct machine_desc *mdesc)
1378d111e8f9SRussell King {
1379d111e8f9SRussell King struct map_desc map;
1380d111e8f9SRussell King unsigned long addr;
138194e5a85bSRussell King void *vectors;
1382d111e8f9SRussell King
1383d111e8f9SRussell King /*
1384d111e8f9SRussell King * Allocate the vector page early.
1385d111e8f9SRussell King */
138619accfd3SRussell King vectors = early_alloc(PAGE_SIZE * 2);
138794e5a85bSRussell King
138894e5a85bSRussell King early_trap_init(vectors);
1389d111e8f9SRussell King
1390a5f4c561SStefan Agner /*
1391a5f4c561SStefan Agner * Clear page table except top pmd used by early fixmaps
1392a5f4c561SStefan Agner */
1393a5f4c561SStefan Agner for (addr = VMALLOC_START; addr < (FIXADDR_TOP & PMD_MASK); addr += PMD_SIZE)
1394d111e8f9SRussell King pmd_clear(pmd_off_k(addr));
1395d111e8f9SRussell King
13967a1be318SArd Biesheuvel if (__atags_pointer) {
13977a1be318SArd Biesheuvel /* create a read-only mapping of the device tree */
13987a1be318SArd Biesheuvel map.pfn = __phys_to_pfn(__atags_pointer & SECTION_MASK);
13997a1be318SArd Biesheuvel map.virtual = FDT_FIXED_BASE;
14007a1be318SArd Biesheuvel map.length = FDT_FIXED_SIZE;
1401598f0a99SZhen Lei map.type = MT_MEMORY_RO;
14027a1be318SArd Biesheuvel create_mapping(&map);
14037a1be318SArd Biesheuvel }
14047a1be318SArd Biesheuvel
1405d111e8f9SRussell King /*
1406d111e8f9SRussell King * Map the cache flushing regions.
1407d111e8f9SRussell King */
1408d111e8f9SRussell King #ifdef FLUSH_BASE
1409d111e8f9SRussell King map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS);
1410d111e8f9SRussell King map.virtual = FLUSH_BASE;
1411d111e8f9SRussell King map.length = SZ_1M;
1412d111e8f9SRussell King map.type = MT_CACHECLEAN;
1413d111e8f9SRussell King create_mapping(&map);
1414d111e8f9SRussell King #endif
1415d111e8f9SRussell King #ifdef FLUSH_BASE_MINICACHE
1416d111e8f9SRussell King map.pfn = __phys_to_pfn(FLUSH_BASE_PHYS + SZ_1M);
1417d111e8f9SRussell King map.virtual = FLUSH_BASE_MINICACHE;
1418d111e8f9SRussell King map.length = SZ_1M;
1419d111e8f9SRussell King map.type = MT_MINICLEAN;
1420d111e8f9SRussell King create_mapping(&map);
1421d111e8f9SRussell King #endif
1422d111e8f9SRussell King
1423d111e8f9SRussell King /*
1424d111e8f9SRussell King * Create a mapping for the machine vectors at the high-vectors
1425d111e8f9SRussell King * location (0xffff0000). If we aren't using high-vectors, also
1426d111e8f9SRussell King * create a mapping at the low-vectors virtual address.
1427d111e8f9SRussell King */
142894e5a85bSRussell King map.pfn = __phys_to_pfn(virt_to_phys(vectors));
1429d111e8f9SRussell King map.virtual = 0xffff0000;
1430d111e8f9SRussell King map.length = PAGE_SIZE;
1431a5463cd3SRussell King #ifdef CONFIG_KUSER_HELPERS
1432d111e8f9SRussell King map.type = MT_HIGH_VECTORS;
1433a5463cd3SRussell King #else
1434a5463cd3SRussell King map.type = MT_LOW_VECTORS;
1435a5463cd3SRussell King #endif
1436d111e8f9SRussell King create_mapping(&map);
1437d111e8f9SRussell King
1438d111e8f9SRussell King if (!vectors_high()) {
1439d111e8f9SRussell King map.virtual = 0;
144019accfd3SRussell King map.length = PAGE_SIZE * 2;
1441d111e8f9SRussell King map.type = MT_LOW_VECTORS;
1442d111e8f9SRussell King create_mapping(&map);
1443d111e8f9SRussell King }
1444d111e8f9SRussell King
144519accfd3SRussell King /* Now create a kernel read-only mapping */
144619accfd3SRussell King map.pfn += 1;
144719accfd3SRussell King map.virtual = 0xffff0000 + PAGE_SIZE;
144819accfd3SRussell King map.length = PAGE_SIZE;
144919accfd3SRussell King map.type = MT_LOW_VECTORS;
145019accfd3SRussell King create_mapping(&map);
145119accfd3SRussell King
1452d111e8f9SRussell King /*
1453d111e8f9SRussell King * Ask the machine support to map in the statically mapped devices.
1454d111e8f9SRussell King */
1455d111e8f9SRussell King if (mdesc->map_io)
1456d111e8f9SRussell King mdesc->map_io();
1457bc37324eSMaxime Ripard else
1458bc37324eSMaxime Ripard debug_ll_io_init();
145919b52abeSNicolas Pitre fill_pmd_gaps();
1460d111e8f9SRussell King
1461c2794437SRob Herring /* Reserve fixed i/o space in VMALLOC region */
1462c2794437SRob Herring pci_reserve_io();
1463c2794437SRob Herring
1464d111e8f9SRussell King /*
1465d111e8f9SRussell King * Finally flush the caches and tlb to ensure that we're in a
1466d111e8f9SRussell King * consistent state wrt the writebuffer. This also ensures that
1467d111e8f9SRussell King * any write-allocated cache lines in the vector page are written
1468d111e8f9SRussell King * back. After this point, we can start to touch devices again.
1469d111e8f9SRussell King */
1470d111e8f9SRussell King local_flush_tlb_all();
1471d111e8f9SRussell King flush_cache_all();
1472bbeb9209SLucas Stach
1473bbeb9209SLucas Stach /* Enable asynchronous aborts */
14749254970cSLucas Stach early_abt_enable();
1475d111e8f9SRussell King }
1476d111e8f9SRussell King
kmap_init(void)1477d73cd428SNicolas Pitre static void __init kmap_init(void)
1478d73cd428SNicolas Pitre {
1479d73cd428SNicolas Pitre #ifdef CONFIG_HIGHMEM
14804bb2e27dSRussell King pkmap_page_table = early_pte_alloc(pmd_off_k(PKMAP_BASE),
14814bb2e27dSRussell King PKMAP_BASE, _PAGE_KERNEL_TABLE);
1482d73cd428SNicolas Pitre #endif
1483836a2418SRob Herring
1484836a2418SRob Herring early_pte_alloc(pmd_off_k(FIXADDR_START), FIXADDR_START,
1485836a2418SRob Herring _PAGE_KERNEL_TABLE);
1486d73cd428SNicolas Pitre }
1487d73cd428SNicolas Pitre
map_lowmem(void)14888df65168SRussell King static void __init map_lowmem(void)
1489a2227120SRussell King {
1490b10d6bcaSMike Rapoport phys_addr_t start, end;
1491b10d6bcaSMike Rapoport u64 i;
14928df65168SRussell King
14938df65168SRussell King /* Map all the lowmem memory banks. */
1494b10d6bcaSMike Rapoport for_each_mem_range(i, &start, &end) {
1495a2227120SRussell King struct map_desc map;
1496a2227120SRussell King
14976e121df1SLinus Walleij pr_debug("map lowmem start: 0x%08llx, end: 0x%08llx\n",
14986e121df1SLinus Walleij (long long)start, (long long)end);
1499c7909509SMarek Szyprowski if (end > arm_lowmem_limit)
1500c7909509SMarek Szyprowski end = arm_lowmem_limit;
15018df65168SRussell King if (start >= end)
15028df65168SRussell King break;
15038df65168SRussell King
15046e121df1SLinus Walleij /*
15056e121df1SLinus Walleij * If our kernel image is in the VMALLOC area we need to remove
15066e121df1SLinus Walleij * the kernel physical memory from lowmem since the kernel will
15076e121df1SLinus Walleij * be mapped separately.
15086e121df1SLinus Walleij *
15096e121df1SLinus Walleij * The kernel will typically be at the very start of lowmem,
15106e121df1SLinus Walleij * but any placement relative to memory ranges is possible.
15116e121df1SLinus Walleij *
15126e121df1SLinus Walleij * If the memblock contains the kernel, we have to chisel out
15136e121df1SLinus Walleij * the kernel memory from it and map each part separately. We
15146e121df1SLinus Walleij * get 6 different theoretical cases:
15156e121df1SLinus Walleij *
15166e121df1SLinus Walleij * +--------+ +--------+
15176e121df1SLinus Walleij * +-- start --+ +--------+ | Kernel | | Kernel |
15186e121df1SLinus Walleij * | | | Kernel | | case 2 | | case 5 |
15196e121df1SLinus Walleij * | | | case 1 | +--------+ | | +--------+
15206e121df1SLinus Walleij * | Memory | +--------+ | | | Kernel |
15216e121df1SLinus Walleij * | range | +--------+ | | | case 6 |
15226e121df1SLinus Walleij * | | | Kernel | +--------+ | | +--------+
15236e121df1SLinus Walleij * | | | case 3 | | Kernel | | |
15246e121df1SLinus Walleij * +-- end ----+ +--------+ | case 4 | | |
15256e121df1SLinus Walleij * +--------+ +--------+
15266e121df1SLinus Walleij */
15276e121df1SLinus Walleij
15286e121df1SLinus Walleij /* Case 5: kernel covers range, don't map anything, should be rare */
15296e121df1SLinus Walleij if ((start > kernel_sec_start) && (end < kernel_sec_end))
15306e121df1SLinus Walleij break;
15316e121df1SLinus Walleij
15326e121df1SLinus Walleij /* Cases where the kernel is starting inside the range */
15336e121df1SLinus Walleij if ((kernel_sec_start >= start) && (kernel_sec_start <= end)) {
15346e121df1SLinus Walleij /* Case 6: kernel is embedded in the range, we need two mappings */
15356e121df1SLinus Walleij if ((start < kernel_sec_start) && (end > kernel_sec_end)) {
15366e121df1SLinus Walleij /* Map memory below the kernel */
15378df65168SRussell King map.pfn = __phys_to_pfn(start);
15388df65168SRussell King map.virtual = __phys_to_virt(start);
15396e121df1SLinus Walleij map.length = kernel_sec_start - start;
15406e121df1SLinus Walleij map.type = MT_MEMORY_RW;
1541a2227120SRussell King create_mapping(&map);
15426e121df1SLinus Walleij /* Map memory above the kernel */
15436e121df1SLinus Walleij map.pfn = __phys_to_pfn(kernel_sec_end);
15446e121df1SLinus Walleij map.virtual = __phys_to_virt(kernel_sec_end);
15456e121df1SLinus Walleij map.length = end - kernel_sec_end;
15466e121df1SLinus Walleij map.type = MT_MEMORY_RW;
15476e121df1SLinus Walleij create_mapping(&map);
15486e121df1SLinus Walleij break;
15496e121df1SLinus Walleij }
15506e121df1SLinus Walleij /* Case 1: kernel and range start at the same address, should be common */
15516e121df1SLinus Walleij if (kernel_sec_start == start)
15526e121df1SLinus Walleij start = kernel_sec_end;
15536e121df1SLinus Walleij /* Case 3: kernel and range end at the same address, should be rare */
15546e121df1SLinus Walleij if (kernel_sec_end == end)
15556e121df1SLinus Walleij end = kernel_sec_start;
15566e121df1SLinus Walleij } else if ((kernel_sec_start < start) && (kernel_sec_end > start) && (kernel_sec_end < end)) {
15576e121df1SLinus Walleij /* Case 2: kernel ends inside range, starts below it */
15586e121df1SLinus Walleij start = kernel_sec_end;
15596e121df1SLinus Walleij } else if ((kernel_sec_start > start) && (kernel_sec_start < end) && (kernel_sec_end > end)) {
15606e121df1SLinus Walleij /* Case 4: kernel starts inside range, ends above it */
15616e121df1SLinus Walleij end = kernel_sec_start;
15626e121df1SLinus Walleij }
15631e6b4811SKees Cook map.pfn = __phys_to_pfn(start);
15641e6b4811SKees Cook map.virtual = __phys_to_virt(start);
15651e6b4811SKees Cook map.length = end - start;
15661e6b4811SKees Cook map.type = MT_MEMORY_RW;
1567ebd4922eSRussell King create_mapping(&map);
1568ebd4922eSRussell King }
15696e121df1SLinus Walleij }
15706e121df1SLinus Walleij
map_kernel(void)15716e121df1SLinus Walleij static void __init map_kernel(void)
15726e121df1SLinus Walleij {
15736e121df1SLinus Walleij /*
15746e121df1SLinus Walleij * We use the well known kernel section start and end and split the area in the
15756e121df1SLinus Walleij * middle like this:
15766e121df1SLinus Walleij * . .
15776e121df1SLinus Walleij * | RW memory |
15786e121df1SLinus Walleij * +----------------+ kernel_x_start
15796e121df1SLinus Walleij * | Executable |
15806e121df1SLinus Walleij * | kernel memory |
15816e121df1SLinus Walleij * +----------------+ kernel_x_end / kernel_nx_start
15826e121df1SLinus Walleij * | Non-executable |
15836e121df1SLinus Walleij * | kernel memory |
15846e121df1SLinus Walleij * +----------------+ kernel_nx_end
15856e121df1SLinus Walleij * | RW memory |
15866e121df1SLinus Walleij * . .
15876e121df1SLinus Walleij *
15886e121df1SLinus Walleij * Notice that we are dealing with section sized mappings here so all of this
15896e121df1SLinus Walleij * will be bumped to the closest section boundary. This means that some of the
15906e121df1SLinus Walleij * non-executable part of the kernel memory is actually mapped as executable.
15916e121df1SLinus Walleij * This will only persist until we turn on proper memory management later on
15926e121df1SLinus Walleij * and we remap the whole kernel with page granularity.
15936e121df1SLinus Walleij */
1594*4b9fb3aeSHarith G #ifdef CONFIG_XIP_KERNEL
1595*4b9fb3aeSHarith G phys_addr_t kernel_nx_start = kernel_sec_start;
1596*4b9fb3aeSHarith G #else
15976e121df1SLinus Walleij phys_addr_t kernel_x_start = kernel_sec_start;
15986e121df1SLinus Walleij phys_addr_t kernel_x_end = round_up(__pa(__init_end), SECTION_SIZE);
15996e121df1SLinus Walleij phys_addr_t kernel_nx_start = kernel_x_end;
1600*4b9fb3aeSHarith G #endif
16016e121df1SLinus Walleij phys_addr_t kernel_nx_end = kernel_sec_end;
16026e121df1SLinus Walleij struct map_desc map;
1603ebd4922eSRussell King
1604*4b9fb3aeSHarith G /*
1605*4b9fb3aeSHarith G * Map the kernel if it is XIP.
1606*4b9fb3aeSHarith G * It is always first in the modulearea.
1607*4b9fb3aeSHarith G */
1608*4b9fb3aeSHarith G #ifdef CONFIG_XIP_KERNEL
1609*4b9fb3aeSHarith G map.pfn = __phys_to_pfn(CONFIG_XIP_PHYS_ADDR & SECTION_MASK);
1610*4b9fb3aeSHarith G map.virtual = MODULES_VADDR;
1611*4b9fb3aeSHarith G map.length = ((unsigned long)_exiprom - map.virtual + ~SECTION_MASK) & SECTION_MASK;
1612*4b9fb3aeSHarith G map.type = MT_ROM;
1613*4b9fb3aeSHarith G create_mapping(&map);
1614*4b9fb3aeSHarith G #else
1615ebd4922eSRussell King map.pfn = __phys_to_pfn(kernel_x_start);
1616ebd4922eSRussell King map.virtual = __phys_to_virt(kernel_x_start);
1617ebd4922eSRussell King map.length = kernel_x_end - kernel_x_start;
1618ebd4922eSRussell King map.type = MT_MEMORY_RWX;
1619ebd4922eSRussell King create_mapping(&map);
1620ebd4922eSRussell King
16216e121df1SLinus Walleij /* If the nx part is small it may end up covered by the tail of the RWX section */
16226e121df1SLinus Walleij if (kernel_x_end == kernel_nx_end)
16236e121df1SLinus Walleij return;
1624*4b9fb3aeSHarith G #endif
16256e121df1SLinus Walleij map.pfn = __phys_to_pfn(kernel_nx_start);
16266e121df1SLinus Walleij map.virtual = __phys_to_virt(kernel_nx_start);
16276e121df1SLinus Walleij map.length = kernel_nx_end - kernel_nx_start;
1628ebd4922eSRussell King map.type = MT_MEMORY_RW;
1629ebd4922eSRussell King create_mapping(&map);
1630ebd4922eSRussell King }
1631a2227120SRussell King
1632d8dc7fbdSRussell King #ifdef CONFIG_ARM_PV_FIXUP
16337a1be318SArd Biesheuvel typedef void pgtables_remap(long long offset, unsigned long pgd);
1634d8dc7fbdSRussell King pgtables_remap lpae_pgtables_remap_asm;
1635d8dc7fbdSRussell King
1636a77e0c7bSSantosh Shilimkar /*
1637a77e0c7bSSantosh Shilimkar * early_paging_init() recreates boot time page table setup, allowing machines
1638a77e0c7bSSantosh Shilimkar * to switch over to a high (>4G) address space on LPAE systems
1639a77e0c7bSSantosh Shilimkar */
early_paging_init(const struct machine_desc * mdesc)1640b089c31cSJon Medhurst static void __init early_paging_init(const struct machine_desc *mdesc)
1641a77e0c7bSSantosh Shilimkar {
1642d8dc7fbdSRussell King pgtables_remap *lpae_pgtables_remap;
1643d8dc7fbdSRussell King unsigned long pa_pgd;
1644d8dc7fbdSRussell King unsigned int cr, ttbcr;
1645c8ca2b4bSRussell King long long offset;
1646a77e0c7bSSantosh Shilimkar
1647c0b759d8SRussell King if (!mdesc->pv_fixup)
1648a77e0c7bSSantosh Shilimkar return;
1649a77e0c7bSSantosh Shilimkar
1650c0b759d8SRussell King offset = mdesc->pv_fixup();
1651c8ca2b4bSRussell King if (offset == 0)
1652c8ca2b4bSRussell King return;
1653a77e0c7bSSantosh Shilimkar
1654d8dc7fbdSRussell King /*
1655463dbba4SLinus Walleij * Offset the kernel section physical offsets so that the kernel
1656463dbba4SLinus Walleij * mapping will work out later on.
1657463dbba4SLinus Walleij */
1658463dbba4SLinus Walleij kernel_sec_start += offset;
1659463dbba4SLinus Walleij kernel_sec_end += offset;
1660463dbba4SLinus Walleij
1661463dbba4SLinus Walleij /*
1662d8dc7fbdSRussell King * Get the address of the remap function in the 1:1 identity
1663d8dc7fbdSRussell King * mapping setup by the early page table assembly code. We
1664d8dc7fbdSRussell King * must get this prior to the pv update. The following barrier
1665d8dc7fbdSRussell King * ensures that this is complete before we fixup any P:V offsets.
1666d8dc7fbdSRussell King */
1667d8dc7fbdSRussell King lpae_pgtables_remap = (pgtables_remap *)(unsigned long)__pa(lpae_pgtables_remap_asm);
1668d8dc7fbdSRussell King pa_pgd = __pa(swapper_pg_dir);
1669d8dc7fbdSRussell King barrier();
1670a77e0c7bSSantosh Shilimkar
167139b74fe8SRussell King pr_info("Switching physical address space to 0x%08llx\n",
167239b74fe8SRussell King (u64)PHYS_OFFSET + offset);
1673a77e0c7bSSantosh Shilimkar
1674c8ca2b4bSRussell King /* Re-set the phys pfn offset, and the pv offset */
1675c8ca2b4bSRussell King __pv_offset += offset;
1676c8ca2b4bSRussell King __pv_phys_pfn_offset += PFN_DOWN(offset);
1677a77e0c7bSSantosh Shilimkar
1678a77e0c7bSSantosh Shilimkar /* Run the patch stub to update the constants */
1679a77e0c7bSSantosh Shilimkar fixup_pv_table(&__pv_table_begin,
1680a77e0c7bSSantosh Shilimkar (&__pv_table_end - &__pv_table_begin) << 2);
1681a77e0c7bSSantosh Shilimkar
1682a77e0c7bSSantosh Shilimkar /*
1683d8dc7fbdSRussell King * We changing not only the virtual to physical mapping, but also
1684d8dc7fbdSRussell King * the physical addresses used to access memory. We need to flush
1685d8dc7fbdSRussell King * all levels of cache in the system with caching disabled to
1686d8dc7fbdSRussell King * ensure that all data is written back, and nothing is prefetched
1687d8dc7fbdSRussell King * into the caches. We also need to prevent the TLB walkers
1688d8dc7fbdSRussell King * allocating into the caches too. Note that this is ARMv7 LPAE
1689d8dc7fbdSRussell King * specific.
1690a77e0c7bSSantosh Shilimkar */
1691d8dc7fbdSRussell King cr = get_cr();
1692d8dc7fbdSRussell King set_cr(cr & ~(CR_I | CR_C));
1693d8dc7fbdSRussell King asm("mrc p15, 0, %0, c2, c0, 2" : "=r" (ttbcr));
1694d8dc7fbdSRussell King asm volatile("mcr p15, 0, %0, c2, c0, 2"
1695d8dc7fbdSRussell King : : "r" (ttbcr & ~(3 << 8 | 3 << 10)));
1696a77e0c7bSSantosh Shilimkar flush_cache_all();
16973bb70de6SRussell King
16983bb70de6SRussell King /*
1699d8dc7fbdSRussell King * Fixup the page tables - this must be in the idmap region as
1700d8dc7fbdSRussell King * we need to disable the MMU to do this safely, and hence it
1701d8dc7fbdSRussell King * needs to be assembly. It's fairly simple, as we're using the
1702d8dc7fbdSRussell King * temporary tables setup by the initial assembly code.
17033bb70de6SRussell King */
17047a1be318SArd Biesheuvel lpae_pgtables_remap(offset, pa_pgd);
17053bb70de6SRussell King
1706d8dc7fbdSRussell King /* Re-enable the caches and cacheable TLB walks */
1707d8dc7fbdSRussell King asm volatile("mcr p15, 0, %0, c2, c0, 2" : : "r" (ttbcr));
1708d8dc7fbdSRussell King set_cr(cr);
1709a77e0c7bSSantosh Shilimkar }
1710a77e0c7bSSantosh Shilimkar
1711a77e0c7bSSantosh Shilimkar #else
1712a77e0c7bSSantosh Shilimkar
early_paging_init(const struct machine_desc * mdesc)1713b089c31cSJon Medhurst static void __init early_paging_init(const struct machine_desc *mdesc)
1714a77e0c7bSSantosh Shilimkar {
1715c8ca2b4bSRussell King long long offset;
1716c8ca2b4bSRussell King
1717c0b759d8SRussell King if (!mdesc->pv_fixup)
1718c8ca2b4bSRussell King return;
1719c8ca2b4bSRussell King
1720c0b759d8SRussell King offset = mdesc->pv_fixup();
1721c8ca2b4bSRussell King if (offset == 0)
1722c8ca2b4bSRussell King return;
1723c8ca2b4bSRussell King
1724c8ca2b4bSRussell King pr_crit("Physical address space modification is only to support Keystone2.\n");
1725c8ca2b4bSRussell King pr_crit("Please enable ARM_LPAE and ARM_PATCH_PHYS_VIRT support to use this\n");
1726c8ca2b4bSRussell King pr_crit("feature. Your kernel may crash now, have a good day.\n");
1727c8ca2b4bSRussell King add_taint(TAINT_CPU_OUT_OF_SPEC, LOCKDEP_STILL_OK);
1728a77e0c7bSSantosh Shilimkar }
1729a77e0c7bSSantosh Shilimkar
1730a77e0c7bSSantosh Shilimkar #endif
1731a77e0c7bSSantosh Shilimkar
early_fixmap_shutdown(void)1732a5f4c561SStefan Agner static void __init early_fixmap_shutdown(void)
1733a5f4c561SStefan Agner {
1734a5f4c561SStefan Agner int i;
1735a5f4c561SStefan Agner unsigned long va = fix_to_virt(__end_of_permanent_fixed_addresses - 1);
1736a5f4c561SStefan Agner
1737a5f4c561SStefan Agner pte_offset_fixmap = pte_offset_late_fixmap;
1738a5f4c561SStefan Agner pmd_clear(fixmap_pmd(va));
1739a5f4c561SStefan Agner local_flush_tlb_kernel_page(va);
1740a5f4c561SStefan Agner
1741a5f4c561SStefan Agner for (i = 0; i < __end_of_permanent_fixed_addresses; i++) {
1742a5f4c561SStefan Agner pte_t *pte;
1743a5f4c561SStefan Agner struct map_desc map;
1744a5f4c561SStefan Agner
1745a5f4c561SStefan Agner map.virtual = fix_to_virt(i);
1746a5f4c561SStefan Agner pte = pte_offset_early_fixmap(pmd_off_k(map.virtual), map.virtual);
1747a5f4c561SStefan Agner
1748a5f4c561SStefan Agner /* Only i/o device mappings are supported ATM */
1749a5f4c561SStefan Agner if (pte_none(*pte) ||
1750a5f4c561SStefan Agner (pte_val(*pte) & L_PTE_MT_MASK) != L_PTE_MT_DEV_SHARED)
1751a5f4c561SStefan Agner continue;
1752a5f4c561SStefan Agner
1753a5f4c561SStefan Agner map.pfn = pte_pfn(*pte);
1754a5f4c561SStefan Agner map.type = MT_DEVICE;
1755a5f4c561SStefan Agner map.length = PAGE_SIZE;
1756a5f4c561SStefan Agner
1757a5f4c561SStefan Agner create_mapping(&map);
1758a5f4c561SStefan Agner }
1759a5f4c561SStefan Agner }
1760a5f4c561SStefan Agner
1761d111e8f9SRussell King /*
1762d111e8f9SRussell King * paging_init() sets up the page tables, initialises the zone memory
1763d111e8f9SRussell King * maps, and sets up the zero page, bad page and bad page tables.
1764d111e8f9SRussell King */
paging_init(const struct machine_desc * mdesc)1765ff69a4c8SRussell King void __init paging_init(const struct machine_desc *mdesc)
1766d111e8f9SRussell King {
1767d111e8f9SRussell King void *zero_page;
1768d111e8f9SRussell King
1769*4b9fb3aeSHarith G #ifdef CONFIG_XIP_KERNEL
1770*4b9fb3aeSHarith G /* Store the kernel RW RAM region start/end in these variables */
1771*4b9fb3aeSHarith G kernel_sec_start = CONFIG_PHYS_OFFSET & SECTION_MASK;
1772*4b9fb3aeSHarith G kernel_sec_end = round_up(__pa(_end), SECTION_SIZE);
1773*4b9fb3aeSHarith G #endif
1774463dbba4SLinus Walleij pr_debug("physical kernel sections: 0x%08llx-0x%08llx\n",
17756e121df1SLinus Walleij kernel_sec_start, kernel_sec_end);
17766e121df1SLinus Walleij
17774b5f32ceSNicolas Pitre prepare_page_table();
1778a2227120SRussell King map_lowmem();
17793de1f52aSLaura Abbott memblock_set_current_limit(arm_lowmem_limit);
17806e121df1SLinus Walleij pr_debug("lowmem limit is %08llx\n", (long long)arm_lowmem_limit);
17816e121df1SLinus Walleij /*
17826e121df1SLinus Walleij * After this point early_alloc(), i.e. the memblock allocator, can
17836e121df1SLinus Walleij * be used
17846e121df1SLinus Walleij */
17856e121df1SLinus Walleij map_kernel();
1786c7909509SMarek Szyprowski dma_contiguous_remap();
1787a5f4c561SStefan Agner early_fixmap_shutdown();
1788d111e8f9SRussell King devicemaps_init(mdesc);
1789d73cd428SNicolas Pitre kmap_init();
1790de40614eSJoonsoo Kim tcm_init();
1791d111e8f9SRussell King
1792d111e8f9SRussell King top_pmd = pmd_off_k(0xffff0000);
1793d111e8f9SRussell King
17943abe9d33SRussell King /* allocate the zero page. */
17953abe9d33SRussell King zero_page = early_alloc(PAGE_SIZE);
17962778f620SRussell King
17978d717a52SRussell King bootmem_init();
17982778f620SRussell King
1799d111e8f9SRussell King empty_zero_page = virt_to_page(zero_page);
18008b5989f3SMatthew Wilcox (Oracle) __flush_dcache_folio(NULL, page_folio(empty_zero_page));
1801d111e8f9SRussell King }
1802b089c31cSJon Medhurst
early_mm_init(const struct machine_desc * mdesc)1803b089c31cSJon Medhurst void __init early_mm_init(const struct machine_desc *mdesc)
1804b089c31cSJon Medhurst {
1805b089c31cSJon Medhurst build_mem_type_table();
1806b089c31cSJon Medhurst early_paging_init(mdesc);
1807b089c31cSJon Medhurst }
180878e7c5afSAnshuman Khandual
set_ptes(struct mm_struct * mm,unsigned long addr,pte_t * ptep,pte_t pteval,unsigned int nr)18098b5989f3SMatthew Wilcox (Oracle) void set_ptes(struct mm_struct *mm, unsigned long addr,
18108b5989f3SMatthew Wilcox (Oracle) pte_t *ptep, pte_t pteval, unsigned int nr)
181178e7c5afSAnshuman Khandual {
181278e7c5afSAnshuman Khandual unsigned long ext = 0;
181378e7c5afSAnshuman Khandual
181478e7c5afSAnshuman Khandual if (addr < TASK_SIZE && pte_valid_user(pteval)) {
181578e7c5afSAnshuman Khandual if (!pte_special(pteval))
181678e7c5afSAnshuman Khandual __sync_icache_dcache(pteval);
181778e7c5afSAnshuman Khandual ext |= PTE_EXT_NG;
181878e7c5afSAnshuman Khandual }
181978e7c5afSAnshuman Khandual
18208b5989f3SMatthew Wilcox (Oracle) for (;;) {
182178e7c5afSAnshuman Khandual set_pte_ext(ptep, pteval, ext);
18228b5989f3SMatthew Wilcox (Oracle) if (--nr == 0)
18238b5989f3SMatthew Wilcox (Oracle) break;
18248b5989f3SMatthew Wilcox (Oracle) ptep++;
18258b5989f3SMatthew Wilcox (Oracle) pte_val(pteval) += PAGE_SIZE;
18268b5989f3SMatthew Wilcox (Oracle) }
182778e7c5afSAnshuman Khandual }
1828