aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64')
-rw-r--r--arch/sparc64/mm/init.c114
1 files changed, 15 insertions, 99 deletions
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c
index 598bfb3b0053..92d095802958 100644
--- a/arch/sparc64/mm/init.c
+++ b/arch/sparc64/mm/init.c
@@ -43,7 +43,7 @@ extern void device_scan(void);
43 43
44struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS]; 44struct sparc_phys_banks sp_banks[SPARC_PHYS_BANKS];
45 45
46unsigned long *sparc64_valid_addr_bitmap; 46unsigned long *sparc64_valid_addr_bitmap __read_mostly;
47 47
48/* Ugly, but necessary... -DaveM */ 48/* Ugly, but necessary... -DaveM */
49unsigned long phys_base __read_mostly; 49unsigned long phys_base __read_mostly;
@@ -51,15 +51,6 @@ unsigned long kern_base __read_mostly;
51unsigned long kern_size __read_mostly; 51unsigned long kern_size __read_mostly;
52unsigned long pfn_base __read_mostly; 52unsigned long pfn_base __read_mostly;
53 53
54/* This is even uglier. We have a problem where the kernel may not be
55 * located at phys_base. However, initial __alloc_bootmem() calls need to
56 * be adjusted to be within the 4-8Megs that the kernel is mapped to, else
57 * those page mappings wont work. Things are ok after inherit_prom_mappings
58 * is called though. Dave says he'll clean this up some other time.
59 * -- BenC
60 */
61static unsigned long bootmap_base;
62
63/* get_new_mmu_context() uses "cache + 1". */ 54/* get_new_mmu_context() uses "cache + 1". */
64DEFINE_SPINLOCK(ctx_alloc_lock); 55DEFINE_SPINLOCK(ctx_alloc_lock);
65unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1; 56unsigned long tlb_context_cache = CTX_FIRST_VERSION - 1;
@@ -1415,8 +1406,6 @@ unsigned long __init bootmem_init(unsigned long *pages_avail)
1415#endif 1406#endif
1416 bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn); 1407 bootmap_size = init_bootmem_node(NODE_DATA(0), bootmap_pfn, pfn_base, end_pfn);
1417 1408
1418 bootmap_base = bootmap_pfn << PAGE_SHIFT;
1419
1420 /* Now register the available physical memory with the 1409 /* Now register the available physical memory with the
1421 * allocator. 1410 * allocator.
1422 */ 1411 */
@@ -1475,89 +1464,22 @@ static unsigned long last_valid_pfn;
1475void __init paging_init(void) 1464void __init paging_init(void)
1476{ 1465{
1477 extern pmd_t swapper_pmd_dir[1024]; 1466 extern pmd_t swapper_pmd_dir[1024];
1478 unsigned long alias_base = kern_base + PAGE_OFFSET; 1467 unsigned long end_pfn, pages_avail, shift;
1479 unsigned long second_alias_page = 0;
1480 unsigned long pt, flags, end_pfn, pages_avail;
1481 unsigned long shift = alias_base - ((unsigned long)KERNBASE);
1482 unsigned long real_end; 1468 unsigned long real_end;
1483 1469
1484 set_bit(0, mmu_context_bmap); 1470 set_bit(0, mmu_context_bmap);
1485 1471
1472 shift = kern_base + PAGE_OFFSET - ((unsigned long)KERNBASE);
1473
1486 real_end = (unsigned long)_end; 1474 real_end = (unsigned long)_end;
1487 if ((real_end > ((unsigned long)KERNBASE + 0x400000))) 1475 if ((real_end > ((unsigned long)KERNBASE + 0x400000)))
1488 bigkernel = 1; 1476 bigkernel = 1;
1489#ifdef CONFIG_BLK_DEV_INITRD 1477 if ((real_end > ((unsigned long)KERNBASE + 0x800000))) {
1490 if (sparc_ramdisk_image || sparc_ramdisk_image64) 1478 prom_printf("paging_init: Kernel > 8MB, too large.\n");
1491 real_end = (PAGE_ALIGN(real_end) + PAGE_ALIGN(sparc_ramdisk_size)); 1479 prom_halt();
1492#endif
1493
1494 /* We assume physical memory starts at some 4mb multiple,
1495 * if this were not true we wouldn't boot up to this point
1496 * anyways.
1497 */
1498 pt = kern_base | _PAGE_VALID | _PAGE_SZ4MB;
1499 pt |= _PAGE_CP | _PAGE_CV | _PAGE_P | _PAGE_L | _PAGE_W;
1500 local_irq_save(flags);
1501 if (tlb_type == spitfire) {
1502 __asm__ __volatile__(
1503 " stxa %1, [%0] %3\n"
1504 " stxa %2, [%5] %4\n"
1505 " membar #Sync\n"
1506 " flush %%g6\n"
1507 " nop\n"
1508 " nop\n"
1509 " nop\n"
1510 : /* No outputs */
1511 : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
1512 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (61 << 3)
1513 : "memory");
1514 if (real_end >= KERNBASE + 0x340000) {
1515 second_alias_page = alias_base + 0x400000;
1516 __asm__ __volatile__(
1517 " stxa %1, [%0] %3\n"
1518 " stxa %2, [%5] %4\n"
1519 " membar #Sync\n"
1520 " flush %%g6\n"
1521 " nop\n"
1522 " nop\n"
1523 " nop\n"
1524 : /* No outputs */
1525 : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
1526 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" (60 << 3)
1527 : "memory");
1528 }
1529 } else if (tlb_type == cheetah || tlb_type == cheetah_plus) {
1530 __asm__ __volatile__(
1531 " stxa %1, [%0] %3\n"
1532 " stxa %2, [%5] %4\n"
1533 " membar #Sync\n"
1534 " flush %%g6\n"
1535 " nop\n"
1536 " nop\n"
1537 " nop\n"
1538 : /* No outputs */
1539 : "r" (TLB_TAG_ACCESS), "r" (alias_base), "r" (pt),
1540 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (13<<3))
1541 : "memory");
1542 if (real_end >= KERNBASE + 0x340000) {
1543 second_alias_page = alias_base + 0x400000;
1544 __asm__ __volatile__(
1545 " stxa %1, [%0] %3\n"
1546 " stxa %2, [%5] %4\n"
1547 " membar #Sync\n"
1548 " flush %%g6\n"
1549 " nop\n"
1550 " nop\n"
1551 " nop\n"
1552 : /* No outputs */
1553 : "r" (TLB_TAG_ACCESS), "r" (second_alias_page), "r" (pt + 0x400000),
1554 "i" (ASI_DMMU), "i" (ASI_DTLB_DATA_ACCESS), "r" ((0<<16) | (12<<3))
1555 : "memory");
1556 }
1557 } 1480 }
1558 local_irq_restore(flags); 1481
1559 1482 /* Set kernel pgd to upper alias so physical page computations
1560 /* Now set kernel pgd to upper alias so physical page computations
1561 * work. 1483 * work.
1562 */ 1484 */
1563 init_mm.pgd += ((shift) / (sizeof(pgd_t))); 1485 init_mm.pgd += ((shift) / (sizeof(pgd_t)));
@@ -1568,15 +1490,11 @@ void __init paging_init(void)
1568 pud_set(pud_offset(&swapper_pg_dir[0], 0), 1490 pud_set(pud_offset(&swapper_pg_dir[0], 0),
1569 swapper_pmd_dir + (shift / sizeof(pgd_t))); 1491 swapper_pmd_dir + (shift / sizeof(pgd_t)));
1570 1492
1571 swapper_pgd_zero = pgd_val(init_mm.pgd[0]); 1493 swapper_pgd_zero = pgd_val(swapper_pg_dir[0]);
1572 1494
1573 /* Inherit non-locked OBP mappings. */ 1495 /* Inherit non-locked OBP mappings. */
1574 inherit_prom_mappings(); 1496 inherit_prom_mappings();
1575 1497
1576 /* Setup bootmem... */
1577 pages_avail = 0;
1578 last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
1579
1580 /* Ok, we can use our TLB miss and window trap handlers safely. 1498 /* Ok, we can use our TLB miss and window trap handlers safely.
1581 * We need to do a quick peek here to see if we are on StarFire 1499 * We need to do a quick peek here to see if we are on StarFire
1582 * or not, so setup_tba can setup the IRQ globals correctly (it 1500 * or not, so setup_tba can setup the IRQ globals correctly (it
@@ -1589,13 +1507,12 @@ void __init paging_init(void)
1589 1507
1590 inherit_locked_prom_mappings(1); 1508 inherit_locked_prom_mappings(1);
1591 1509
1592 /* We only created DTLB mapping of this stuff. */
1593 spitfire_flush_dtlb_nucleus_page(alias_base);
1594 if (second_alias_page)
1595 spitfire_flush_dtlb_nucleus_page(second_alias_page);
1596
1597 __flush_tlb_all(); 1510 __flush_tlb_all();
1598 1511
1512 /* Setup bootmem... */
1513 pages_avail = 0;
1514 last_valid_pfn = end_pfn = bootmem_init(&pages_avail);
1515
1599 { 1516 {
1600 unsigned long zones_size[MAX_NR_ZONES]; 1517 unsigned long zones_size[MAX_NR_ZONES];
1601 unsigned long zholes_size[MAX_NR_ZONES]; 1518 unsigned long zholes_size[MAX_NR_ZONES];
@@ -1757,8 +1674,7 @@ void __init mem_init(void)
1757 1674
1758 i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6); 1675 i = last_valid_pfn >> ((22 - PAGE_SHIFT) + 6);
1759 i += 1; 1676 i += 1;
1760 sparc64_valid_addr_bitmap = (unsigned long *) 1677 sparc64_valid_addr_bitmap = (unsigned long *) alloc_bootmem(i << 3);
1761 __alloc_bootmem(i << 3, SMP_CACHE_BYTES, bootmap_base);
1762 if (sparc64_valid_addr_bitmap == NULL) { 1678 if (sparc64_valid_addr_bitmap == NULL) {
1763 prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n"); 1679 prom_printf("mem_init: Cannot alloc valid_addr_bitmap.\n");
1764 prom_halt(); 1680 prom_halt();