diff options
Diffstat (limited to 'arch/arm/mm')
-rw-r--r-- | arch/arm/mm/idmap.c | 8 | ||||
-rw-r--r-- | arch/arm/mm/mmu.c | 82 |
2 files changed, 86 insertions, 4 deletions
diff --git a/arch/arm/mm/idmap.c b/arch/arm/mm/idmap.c index 83cb3ac27095..8e0e52eb76b5 100644 --- a/arch/arm/mm/idmap.c +++ b/arch/arm/mm/idmap.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <asm/system_info.h> | 10 | #include <asm/system_info.h> |
11 | 11 | ||
12 | pgd_t *idmap_pgd; | 12 | pgd_t *idmap_pgd; |
13 | phys_addr_t (*arch_virt_to_idmap) (unsigned long x); | ||
13 | 14 | ||
14 | #ifdef CONFIG_ARM_LPAE | 15 | #ifdef CONFIG_ARM_LPAE |
15 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, | 16 | static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end, |
@@ -67,8 +68,9 @@ static void identity_mapping_add(pgd_t *pgd, const char *text_start, | |||
67 | unsigned long addr, end; | 68 | unsigned long addr, end; |
68 | unsigned long next; | 69 | unsigned long next; |
69 | 70 | ||
70 | addr = virt_to_phys(text_start); | 71 | addr = virt_to_idmap(text_start); |
71 | end = virt_to_phys(text_end); | 72 | end = virt_to_idmap(text_end); |
73 | pr_info("Setting up static identity map for 0x%lx - 0x%lx\n", addr, end); | ||
72 | 74 | ||
73 | prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; | 75 | prot |= PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_AF; |
74 | 76 | ||
@@ -90,8 +92,6 @@ static int __init init_static_idmap(void) | |||
90 | if (!idmap_pgd) | 92 | if (!idmap_pgd) |
91 | return -ENOMEM; | 93 | return -ENOMEM; |
92 | 94 | ||
93 | pr_info("Setting up static identity map for 0x%p - 0x%p\n", | ||
94 | __idmap_text_start, __idmap_text_end); | ||
95 | identity_mapping_add(idmap_pgd, __idmap_text_start, | 95 | identity_mapping_add(idmap_pgd, __idmap_text_start, |
96 | __idmap_text_end, 0); | 96 | __idmap_text_end, 0); |
97 | 97 | ||
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 | */ | ||
1325 | void __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 | |||
1391 | void __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. |