|
28 | 28 | #include <asm/highmem.h>
|
29 | 29 | #include <asm/system_info.h>
|
30 | 30 | #include <asm/traps.h>
|
| 31 | +#include <asm/procinfo.h> |
| 32 | +#include <asm/memory.h> |
31 | 33 |
|
32 | 34 | #include <asm/mach/arch.h>
|
33 | 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 | 1401 | * paging_init() sets up the page tables, initialises the zone memory
|
1320 | 1402 | * maps, and sets up the zero page, bad page and bad page tables.
|
|
0 commit comments