aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mm/mmu.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/mm/mmu.c')
-rw-r--r--arch/arm/mm/mmu.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index b1d17eeb59b8..78eeeca78f5a 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -28,6 +28,8 @@
28#include <asm/highmem.h> 28#include <asm/highmem.h>
29#include <asm/system_info.h> 29#include <asm/system_info.h>
30#include <asm/traps.h> 30#include <asm/traps.h>
31#include <asm/procinfo.h>
32#include <asm/memory.h>
31 33
32#include <asm/mach/arch.h> 34#include <asm/mach/arch.h>
33#include <asm/mach/map.h> 35#include <asm/mach/map.h>
@@ -1315,6 +1317,86 @@ static void __init map_lowmem(void)
1315 } 1317 }
1316} 1318}
1317 1319
1320#ifdef CONFIG_ARM_LPAE
1321/*
1322 * early_paging_init() recreates boot time page table setup, allowing machines
1323 * to switch over to a high (>4G) address space on LPAE systems
1324 */
1325void __init early_paging_init(const struct machine_desc *mdesc,
1326 struct proc_info_list *procinfo)
1327{
1328 pmdval_t pmdprot = procinfo->__cpu_mm_mmu_flags;
1329 unsigned long map_start, map_end;
1330 pgd_t *pgd0, *pgdk;
1331 pud_t *pud0, *pudk, *pud_start;
1332 pmd_t *pmd0, *pmdk;
1333 phys_addr_t phys;
1334 int i;
1335
1336 if (!(mdesc->init_meminfo))
1337 return;
1338
1339 /* remap kernel code and data */
1340 map_start = init_mm.start_code;
1341 map_end = init_mm.brk;
1342
1343 /* get a handle on things... */
1344 pgd0 = pgd_offset_k(0);
1345 pud_start = pud0 = pud_offset(pgd0, 0);
1346 pmd0 = pmd_offset(pud0, 0);
1347
1348 pgdk = pgd_offset_k(map_start);
1349 pudk = pud_offset(pgdk, map_start);
1350 pmdk = pmd_offset(pudk, map_start);
1351
1352 mdesc->init_meminfo();
1353
1354 /* Run the patch stub to update the constants */
1355 fixup_pv_table(&__pv_table_begin,
1356 (&__pv_table_end - &__pv_table_begin) << 2);
1357
1358 /*
1359 * Cache cleaning operations for self-modifying code
1360 * We should clean the entries by MVA but running a
1361 * for loop over every pv_table entry pointer would
1362 * just complicate the code.
1363 */
1364 flush_cache_louis();
1365 dsb();
1366 isb();
1367
1368 /* remap level 1 table */
1369 for (i = 0; i < PTRS_PER_PGD; pud0++, i++) {
1370 set_pud(pud0,
1371 __pud(__pa(pmd0) | PMD_TYPE_TABLE | L_PGD_SWAPPER));
1372 pmd0 += PTRS_PER_PMD;
1373 }
1374
1375 /* remap pmds for kernel mapping */
1376 phys = __pa(map_start) & PMD_MASK;
1377 do {
1378 *pmdk++ = __pmd(phys | pmdprot);
1379 phys += PMD_SIZE;
1380 } while (phys < map_end);
1381
1382 flush_cache_all();
1383 cpu_switch_mm(pgd0, &init_mm);
1384 cpu_set_ttbr(1, __pa(pgd0) + TTBR1_OFFSET);
1385 local_flush_bp_all();
1386 local_flush_tlb_all();
1387}
1388
1389#else
1390
1391void __init early_paging_init(const struct machine_desc *mdesc,
1392 struct proc_info_list *procinfo)
1393{
1394 if (mdesc->init_meminfo)
1395 mdesc->init_meminfo();
1396}
1397
1398#endif
1399
1318/* 1400/*
1319 * paging_init() sets up the page tables, initialises the zone memory 1401 * paging_init() sets up the page tables, initialises the zone memory
1320 * maps, and sets up the zero page, bad page and bad page tables. 1402 * maps, and sets up the zero page, bad page and bad page tables.