diff options
Diffstat (limited to 'arch/sparc64/mm/init.c')
-rw-r--r-- | arch/sparc64/mm/init.c | 109 |
1 files changed, 106 insertions, 3 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index cf747372f0c9..8d72f8a1268e 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
@@ -1332,15 +1332,114 @@ unsigned long __init bootmem_init(unsigned long *pages_avail) | |||
1332 | return end_pfn; | 1332 | return end_pfn; |
1333 | } | 1333 | } |
1334 | 1334 | ||
1335 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
1336 | static unsigned long kernel_map_range(unsigned long pstart, unsigned long pend, pgprot_t prot) | ||
1337 | { | ||
1338 | unsigned long vstart = PAGE_OFFSET + pstart; | ||
1339 | unsigned long vend = PAGE_OFFSET + pend; | ||
1340 | unsigned long alloc_bytes = 0UL; | ||
1341 | |||
1342 | if ((vstart & ~PAGE_MASK) || (vend & ~PAGE_MASK)) { | ||
1343 | prom_printf("kernel_map: Unaligned sp_banks[%lx:%lx]\n", | ||
1344 | vstart, vend); | ||
1345 | prom_halt(); | ||
1346 | } | ||
1347 | |||
1348 | while (vstart < vend) { | ||
1349 | unsigned long this_end, paddr = __pa(vstart); | ||
1350 | pgd_t *pgd = pgd_offset_k(vstart); | ||
1351 | pud_t *pud; | ||
1352 | pmd_t *pmd; | ||
1353 | pte_t *pte; | ||
1354 | |||
1355 | pud = pud_offset(pgd, vstart); | ||
1356 | if (pud_none(*pud)) { | ||
1357 | pmd_t *new; | ||
1358 | |||
1359 | new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); | ||
1360 | alloc_bytes += PAGE_SIZE; | ||
1361 | pud_populate(&init_mm, pud, new); | ||
1362 | } | ||
1363 | |||
1364 | pmd = pmd_offset(pud, vstart); | ||
1365 | if (!pmd_present(*pmd)) { | ||
1366 | pte_t *new; | ||
1367 | |||
1368 | new = __alloc_bootmem(PAGE_SIZE, PAGE_SIZE, PAGE_SIZE); | ||
1369 | alloc_bytes += PAGE_SIZE; | ||
1370 | pmd_populate_kernel(&init_mm, pmd, new); | ||
1371 | } | ||
1372 | |||
1373 | pte = pte_offset_kernel(pmd, vstart); | ||
1374 | this_end = (vstart + PMD_SIZE) & PMD_MASK; | ||
1375 | if (this_end > vend) | ||
1376 | this_end = vend; | ||
1377 | |||
1378 | while (vstart < this_end) { | ||
1379 | pte_val(*pte) = (paddr | pgprot_val(prot)); | ||
1380 | |||
1381 | vstart += PAGE_SIZE; | ||
1382 | paddr += PAGE_SIZE; | ||
1383 | pte++; | ||
1384 | } | ||
1385 | } | ||
1386 | |||
1387 | return alloc_bytes; | ||
1388 | } | ||
1389 | |||
1390 | extern struct linux_mlist_p1275 *prom_ptot_ptr; | ||
1391 | extern unsigned int kvmap_linear_patch[1]; | ||
1392 | |||
1393 | static void __init kernel_physical_mapping_init(void) | ||
1394 | { | ||
1395 | struct linux_mlist_p1275 *p = prom_ptot_ptr; | ||
1396 | unsigned long mem_alloced = 0UL; | ||
1397 | |||
1398 | while (p) { | ||
1399 | unsigned long phys_start, phys_end; | ||
1400 | |||
1401 | phys_start = p->start_adr; | ||
1402 | phys_end = phys_start + p->num_bytes; | ||
1403 | mem_alloced += kernel_map_range(phys_start, phys_end, | ||
1404 | PAGE_KERNEL); | ||
1405 | |||
1406 | p = p->theres_more; | ||
1407 | } | ||
1408 | |||
1409 | printk("Allocated %ld bytes for kernel page tables.\n", | ||
1410 | mem_alloced); | ||
1411 | |||
1412 | kvmap_linear_patch[0] = 0x01000000; /* nop */ | ||
1413 | flushi(&kvmap_linear_patch[0]); | ||
1414 | |||
1415 | __flush_tlb_all(); | ||
1416 | } | ||
1417 | |||
1418 | void kernel_map_pages(struct page *page, int numpages, int enable) | ||
1419 | { | ||
1420 | unsigned long phys_start = page_to_pfn(page) << PAGE_SHIFT; | ||
1421 | unsigned long phys_end = phys_start + (numpages * PAGE_SIZE); | ||
1422 | |||
1423 | kernel_map_range(phys_start, phys_end, | ||
1424 | (enable ? PAGE_KERNEL : __pgprot(0))); | ||
1425 | |||
1426 | /* we should perform an IPI and flush all tlbs, | ||
1427 | * but that can deadlock->flush only current cpu. | ||
1428 | */ | ||
1429 | __flush_tlb_kernel_range(PAGE_OFFSET + phys_start, | ||
1430 | PAGE_OFFSET + phys_end); | ||
1431 | } | ||
1432 | #endif | ||
1433 | |||
1335 | /* paging_init() sets up the page tables */ | 1434 | /* paging_init() sets up the page tables */ |
1336 | 1435 | ||
1337 | extern void cheetah_ecache_flush_init(void); | 1436 | extern void cheetah_ecache_flush_init(void); |
1338 | 1437 | ||
1339 | static unsigned long last_valid_pfn; | 1438 | static unsigned long last_valid_pfn; |
1439 | pgd_t swapper_pg_dir[2048]; | ||
1340 | 1440 | ||
1341 | void __init paging_init(void) | 1441 | void __init paging_init(void) |
1342 | { | 1442 | { |
1343 | extern pmd_t swapper_pmd_dir[1024]; | ||
1344 | unsigned long end_pfn, pages_avail, shift; | 1443 | unsigned long end_pfn, pages_avail, shift; |
1345 | unsigned long real_end; | 1444 | unsigned long real_end; |
1346 | 1445 | ||
@@ -1361,11 +1460,11 @@ void __init paging_init(void) | |||
1361 | */ | 1460 | */ |
1362 | init_mm.pgd += ((shift) / (sizeof(pgd_t))); | 1461 | init_mm.pgd += ((shift) / (sizeof(pgd_t))); |
1363 | 1462 | ||
1364 | memset(swapper_pmd_dir, 0, sizeof(swapper_pmd_dir)); | 1463 | memset(swapper_low_pmd_dir, 0, sizeof(swapper_low_pmd_dir)); |
1365 | 1464 | ||
1366 | /* Now can init the kernel/bad page tables. */ | 1465 | /* Now can init the kernel/bad page tables. */ |
1367 | pud_set(pud_offset(&swapper_pg_dir[0], 0), | 1466 | pud_set(pud_offset(&swapper_pg_dir[0], 0), |
1368 | swapper_pmd_dir + (shift / sizeof(pgd_t))); | 1467 | swapper_low_pmd_dir + (shift / sizeof(pgd_t))); |
1369 | 1468 | ||
1370 | swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); | 1469 | swapper_pgd_zero = pgd_val(swapper_pg_dir[0]); |
1371 | 1470 | ||
@@ -1390,6 +1489,10 @@ void __init paging_init(void) | |||
1390 | pages_avail = 0; | 1489 | pages_avail = 0; |
1391 | last_valid_pfn = end_pfn = bootmem_init(&pages_avail); | 1490 | last_valid_pfn = end_pfn = bootmem_init(&pages_avail); |
1392 | 1491 | ||
1492 | #ifdef CONFIG_DEBUG_PAGEALLOC | ||
1493 | kernel_physical_mapping_init(); | ||
1494 | #endif | ||
1495 | |||
1393 | { | 1496 | { |
1394 | unsigned long zones_size[MAX_NR_ZONES]; | 1497 | unsigned long zones_size[MAX_NR_ZONES]; |
1395 | unsigned long zholes_size[MAX_NR_ZONES]; | 1498 | unsigned long zholes_size[MAX_NR_ZONES]; |