diff options
Diffstat (limited to 'arch/sparc/mm/init_64.c')
-rw-r--r-- | arch/sparc/mm/init_64.c | 551 |
1 files changed, 487 insertions, 64 deletions
diff --git a/arch/sparc/mm/init_64.c b/arch/sparc/mm/init_64.c index d58edf5fefdb..9e28a118e6a4 100644 --- a/arch/sparc/mm/init_64.c +++ b/arch/sparc/mm/init_64.c | |||
@@ -51,22 +51,40 @@ | |||
51 | 51 | ||
52 | #include "init_64.h" | 52 | #include "init_64.h" |
53 | 53 | ||
54 | unsigned long kern_linear_pte_xor[2] __read_mostly; | 54 | unsigned long kern_linear_pte_xor[4] __read_mostly; |
55 | 55 | ||
56 | /* A bitmap, one bit for every 256MB of physical memory. If the bit | 56 | /* A bitmap, two bits for every 256MB of physical memory. These two |
57 | * is clear, we should use a 4MB page (via kern_linear_pte_xor[0]) else | 57 | * bits determine what page size we use for kernel linear |
58 | * if set we should use a 256MB page (via kern_linear_pte_xor[1]). | 58 | * translations. They form an index into kern_linear_pte_xor[]. The |
59 | * value in the indexed slot is XOR'd with the TLB miss virtual | ||
60 | * address to form the resulting TTE. The mapping is: | ||
61 | * | ||
62 | * 0 ==> 4MB | ||
63 | * 1 ==> 256MB | ||
64 | * 2 ==> 2GB | ||
65 | * 3 ==> 16GB | ||
66 | * | ||
67 | * All sun4v chips support 256MB pages. Only SPARC-T4 and later | ||
68 | * support 2GB pages, and hopefully future cpus will support the 16GB | ||
69 | * pages as well. For slots 2 and 3, we encode a 256MB TTE xor there | ||
70 | * if these larger page sizes are not supported by the cpu. | ||
71 | * | ||
72 | * It would be nice to determine this from the machine description | ||
73 | * 'cpu' properties, but we need to have this table setup before the | ||
74 | * MDESC is initialized. | ||
59 | */ | 75 | */ |
60 | unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | 76 | unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; |
61 | 77 | ||
62 | #ifndef CONFIG_DEBUG_PAGEALLOC | 78 | #ifndef CONFIG_DEBUG_PAGEALLOC |
63 | /* A special kernel TSB for 4MB and 256MB linear mappings. | 79 | /* A special kernel TSB for 4MB, 256MB, 2GB and 16GB linear mappings. |
64 | * Space is allocated for this right after the trap table | 80 | * Space is allocated for this right after the trap table in |
65 | * in arch/sparc64/kernel/head.S | 81 | * arch/sparc64/kernel/head.S |
66 | */ | 82 | */ |
67 | extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; | 83 | extern struct tsb swapper_4m_tsb[KERNEL_TSB4M_NENTRIES]; |
68 | #endif | 84 | #endif |
69 | 85 | ||
86 | static unsigned long cpu_pgsz_mask; | ||
87 | |||
70 | #define MAX_BANKS 32 | 88 | #define MAX_BANKS 32 |
71 | 89 | ||
72 | static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata; | 90 | static struct linux_prom64_registers pavail[MAX_BANKS] __devinitdata; |
@@ -101,7 +119,8 @@ static void __init read_obp_memory(const char *property, | |||
101 | 119 | ||
102 | ret = prom_getproperty(node, property, (char *) regs, prop_size); | 120 | ret = prom_getproperty(node, property, (char *) regs, prop_size); |
103 | if (ret == -1) { | 121 | if (ret == -1) { |
104 | prom_printf("Couldn't get %s property from /memory.\n"); | 122 | prom_printf("Couldn't get %s property from /memory.\n", |
123 | property); | ||
105 | prom_halt(); | 124 | prom_halt(); |
106 | } | 125 | } |
107 | 126 | ||
@@ -257,7 +276,6 @@ static inline void tsb_insert(struct tsb *ent, unsigned long tag, unsigned long | |||
257 | } | 276 | } |
258 | 277 | ||
259 | unsigned long _PAGE_ALL_SZ_BITS __read_mostly; | 278 | unsigned long _PAGE_ALL_SZ_BITS __read_mostly; |
260 | unsigned long _PAGE_SZBITS __read_mostly; | ||
261 | 279 | ||
262 | static void flush_dcache(unsigned long pfn) | 280 | static void flush_dcache(unsigned long pfn) |
263 | { | 281 | { |
@@ -288,12 +306,24 @@ static void flush_dcache(unsigned long pfn) | |||
288 | } | 306 | } |
289 | } | 307 | } |
290 | 308 | ||
309 | /* mm->context.lock must be held */ | ||
310 | static void __update_mmu_tsb_insert(struct mm_struct *mm, unsigned long tsb_index, | ||
311 | unsigned long tsb_hash_shift, unsigned long address, | ||
312 | unsigned long tte) | ||
313 | { | ||
314 | struct tsb *tsb = mm->context.tsb_block[tsb_index].tsb; | ||
315 | unsigned long tag; | ||
316 | |||
317 | tsb += ((address >> tsb_hash_shift) & | ||
318 | (mm->context.tsb_block[tsb_index].tsb_nentries - 1UL)); | ||
319 | tag = (address >> 22UL); | ||
320 | tsb_insert(tsb, tag, tte); | ||
321 | } | ||
322 | |||
291 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) | 323 | void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t *ptep) |
292 | { | 324 | { |
325 | unsigned long tsb_index, tsb_hash_shift, flags; | ||
293 | struct mm_struct *mm; | 326 | struct mm_struct *mm; |
294 | struct tsb *tsb; | ||
295 | unsigned long tag, flags; | ||
296 | unsigned long tsb_index, tsb_hash_shift; | ||
297 | pte_t pte = *ptep; | 327 | pte_t pte = *ptep; |
298 | 328 | ||
299 | if (tlb_type != hypervisor) { | 329 | if (tlb_type != hypervisor) { |
@@ -310,7 +340,7 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t * | |||
310 | 340 | ||
311 | spin_lock_irqsave(&mm->context.lock, flags); | 341 | spin_lock_irqsave(&mm->context.lock, flags); |
312 | 342 | ||
313 | #ifdef CONFIG_HUGETLB_PAGE | 343 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) |
314 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb != NULL) { | 344 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb != NULL) { |
315 | if ((tlb_type == hypervisor && | 345 | if ((tlb_type == hypervisor && |
316 | (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) || | 346 | (pte_val(pte) & _PAGE_SZALL_4V) == _PAGE_SZHUGE_4V) || |
@@ -322,11 +352,8 @@ void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t * | |||
322 | } | 352 | } |
323 | #endif | 353 | #endif |
324 | 354 | ||
325 | tsb = mm->context.tsb_block[tsb_index].tsb; | 355 | __update_mmu_tsb_insert(mm, tsb_index, tsb_hash_shift, |
326 | tsb += ((address >> tsb_hash_shift) & | 356 | address, pte_val(pte)); |
327 | (mm->context.tsb_block[tsb_index].tsb_nentries - 1UL)); | ||
328 | tag = (address >> 22UL); | ||
329 | tsb_insert(tsb, tag, pte_val(pte)); | ||
330 | 357 | ||
331 | spin_unlock_irqrestore(&mm->context.lock, flags); | 358 | spin_unlock_irqrestore(&mm->context.lock, flags); |
332 | } | 359 | } |
@@ -403,6 +430,12 @@ EXPORT_SYMBOL(flush_icache_range); | |||
403 | 430 | ||
404 | void mmu_info(struct seq_file *m) | 431 | void mmu_info(struct seq_file *m) |
405 | { | 432 | { |
433 | static const char *pgsz_strings[] = { | ||
434 | "8K", "64K", "512K", "4MB", "32MB", | ||
435 | "256MB", "2GB", "16GB", | ||
436 | }; | ||
437 | int i, printed; | ||
438 | |||
406 | if (tlb_type == cheetah) | 439 | if (tlb_type == cheetah) |
407 | seq_printf(m, "MMU Type\t: Cheetah\n"); | 440 | seq_printf(m, "MMU Type\t: Cheetah\n"); |
408 | else if (tlb_type == cheetah_plus) | 441 | else if (tlb_type == cheetah_plus) |
@@ -414,6 +447,17 @@ void mmu_info(struct seq_file *m) | |||
414 | else | 447 | else |
415 | seq_printf(m, "MMU Type\t: ???\n"); | 448 | seq_printf(m, "MMU Type\t: ???\n"); |
416 | 449 | ||
450 | seq_printf(m, "MMU PGSZs\t: "); | ||
451 | printed = 0; | ||
452 | for (i = 0; i < ARRAY_SIZE(pgsz_strings); i++) { | ||
453 | if (cpu_pgsz_mask & (1UL << i)) { | ||
454 | seq_printf(m, "%s%s", | ||
455 | printed ? "," : "", pgsz_strings[i]); | ||
456 | printed++; | ||
457 | } | ||
458 | } | ||
459 | seq_putc(m, '\n'); | ||
460 | |||
417 | #ifdef CONFIG_DEBUG_DCFLUSH | 461 | #ifdef CONFIG_DEBUG_DCFLUSH |
418 | seq_printf(m, "DCPageFlushes\t: %d\n", | 462 | seq_printf(m, "DCPageFlushes\t: %d\n", |
419 | atomic_read(&dcpage_flushes)); | 463 | atomic_read(&dcpage_flushes)); |
@@ -462,7 +506,7 @@ static void __init read_obp_translations(void) | |||
462 | prom_halt(); | 506 | prom_halt(); |
463 | } | 507 | } |
464 | if (unlikely(n > sizeof(prom_trans))) { | 508 | if (unlikely(n > sizeof(prom_trans))) { |
465 | prom_printf("prom_mappings: Size %Zd is too big.\n", n); | 509 | prom_printf("prom_mappings: Size %d is too big.\n", n); |
466 | prom_halt(); | 510 | prom_halt(); |
467 | } | 511 | } |
468 | 512 | ||
@@ -524,7 +568,7 @@ static void __init hypervisor_tlb_lock(unsigned long vaddr, | |||
524 | unsigned long ret = sun4v_mmu_map_perm_addr(vaddr, 0, pte, mmu); | 568 | unsigned long ret = sun4v_mmu_map_perm_addr(vaddr, 0, pte, mmu); |
525 | 569 | ||
526 | if (ret != 0) { | 570 | if (ret != 0) { |
527 | prom_printf("hypervisor_tlb_lock[%lx:%lx:%lx:%lx]: " | 571 | prom_printf("hypervisor_tlb_lock[%lx:%x:%lx:%lx]: " |
528 | "errors with %lx\n", vaddr, 0, pte, mmu, ret); | 572 | "errors with %lx\n", vaddr, 0, pte, mmu, ret); |
529 | prom_halt(); | 573 | prom_halt(); |
530 | } | 574 | } |
@@ -1358,32 +1402,75 @@ static unsigned long __ref kernel_map_range(unsigned long pstart, | |||
1358 | extern unsigned int kvmap_linear_patch[1]; | 1402 | extern unsigned int kvmap_linear_patch[1]; |
1359 | #endif /* CONFIG_DEBUG_PAGEALLOC */ | 1403 | #endif /* CONFIG_DEBUG_PAGEALLOC */ |
1360 | 1404 | ||
1361 | static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) | 1405 | static void __init kpte_set_val(unsigned long index, unsigned long val) |
1362 | { | 1406 | { |
1363 | const unsigned long shift_256MB = 28; | 1407 | unsigned long *ptr = kpte_linear_bitmap; |
1364 | const unsigned long mask_256MB = ((1UL << shift_256MB) - 1UL); | ||
1365 | const unsigned long size_256MB = (1UL << shift_256MB); | ||
1366 | 1408 | ||
1367 | while (start < end) { | 1409 | val <<= ((index % (BITS_PER_LONG / 2)) * 2); |
1368 | long remains; | 1410 | ptr += (index / (BITS_PER_LONG / 2)); |
1369 | 1411 | ||
1370 | remains = end - start; | 1412 | *ptr |= val; |
1371 | if (remains < size_256MB) | 1413 | } |
1372 | break; | ||
1373 | 1414 | ||
1374 | if (start & mask_256MB) { | 1415 | static const unsigned long kpte_shift_min = 28; /* 256MB */ |
1375 | start = (start + size_256MB) & ~mask_256MB; | 1416 | static const unsigned long kpte_shift_max = 34; /* 16GB */ |
1376 | continue; | 1417 | static const unsigned long kpte_shift_incr = 3; |
1377 | } | ||
1378 | 1418 | ||
1379 | while (remains >= size_256MB) { | 1419 | static unsigned long kpte_mark_using_shift(unsigned long start, unsigned long end, |
1380 | unsigned long index = start >> shift_256MB; | 1420 | unsigned long shift) |
1421 | { | ||
1422 | unsigned long size = (1UL << shift); | ||
1423 | unsigned long mask = (size - 1UL); | ||
1424 | unsigned long remains = end - start; | ||
1425 | unsigned long val; | ||
1381 | 1426 | ||
1382 | __set_bit(index, kpte_linear_bitmap); | 1427 | if (remains < size || (start & mask)) |
1428 | return start; | ||
1383 | 1429 | ||
1384 | start += size_256MB; | 1430 | /* VAL maps: |
1385 | remains -= size_256MB; | 1431 | * |
1432 | * shift 28 --> kern_linear_pte_xor index 1 | ||
1433 | * shift 31 --> kern_linear_pte_xor index 2 | ||
1434 | * shift 34 --> kern_linear_pte_xor index 3 | ||
1435 | */ | ||
1436 | val = ((shift - kpte_shift_min) / kpte_shift_incr) + 1; | ||
1437 | |||
1438 | remains &= ~mask; | ||
1439 | if (shift != kpte_shift_max) | ||
1440 | remains = size; | ||
1441 | |||
1442 | while (remains) { | ||
1443 | unsigned long index = start >> kpte_shift_min; | ||
1444 | |||
1445 | kpte_set_val(index, val); | ||
1446 | |||
1447 | start += 1UL << kpte_shift_min; | ||
1448 | remains -= 1UL << kpte_shift_min; | ||
1449 | } | ||
1450 | |||
1451 | return start; | ||
1452 | } | ||
1453 | |||
1454 | static void __init mark_kpte_bitmap(unsigned long start, unsigned long end) | ||
1455 | { | ||
1456 | unsigned long smallest_size, smallest_mask; | ||
1457 | unsigned long s; | ||
1458 | |||
1459 | smallest_size = (1UL << kpte_shift_min); | ||
1460 | smallest_mask = (smallest_size - 1UL); | ||
1461 | |||
1462 | while (start < end) { | ||
1463 | unsigned long orig_start = start; | ||
1464 | |||
1465 | for (s = kpte_shift_max; s >= kpte_shift_min; s -= kpte_shift_incr) { | ||
1466 | start = kpte_mark_using_shift(start, end, s); | ||
1467 | |||
1468 | if (start != orig_start) | ||
1469 | break; | ||
1386 | } | 1470 | } |
1471 | |||
1472 | if (start == orig_start) | ||
1473 | start = (start + smallest_size) & ~smallest_mask; | ||
1387 | } | 1474 | } |
1388 | } | 1475 | } |
1389 | 1476 | ||
@@ -1577,13 +1664,16 @@ static void __init sun4v_ktsb_init(void) | |||
1577 | ktsb_descr[0].resv = 0; | 1664 | ktsb_descr[0].resv = 0; |
1578 | 1665 | ||
1579 | #ifndef CONFIG_DEBUG_PAGEALLOC | 1666 | #ifndef CONFIG_DEBUG_PAGEALLOC |
1580 | /* Second KTSB for 4MB/256MB mappings. */ | 1667 | /* Second KTSB for 4MB/256MB/2GB/16GB mappings. */ |
1581 | ktsb_pa = (kern_base + | 1668 | ktsb_pa = (kern_base + |
1582 | ((unsigned long)&swapper_4m_tsb[0] - KERNBASE)); | 1669 | ((unsigned long)&swapper_4m_tsb[0] - KERNBASE)); |
1583 | 1670 | ||
1584 | ktsb_descr[1].pgsz_idx = HV_PGSZ_IDX_4MB; | 1671 | ktsb_descr[1].pgsz_idx = HV_PGSZ_IDX_4MB; |
1585 | ktsb_descr[1].pgsz_mask = (HV_PGSZ_MASK_4MB | | 1672 | ktsb_descr[1].pgsz_mask = ((HV_PGSZ_MASK_4MB | |
1586 | HV_PGSZ_MASK_256MB); | 1673 | HV_PGSZ_MASK_256MB | |
1674 | HV_PGSZ_MASK_2GB | | ||
1675 | HV_PGSZ_MASK_16GB) & | ||
1676 | cpu_pgsz_mask); | ||
1587 | ktsb_descr[1].assoc = 1; | 1677 | ktsb_descr[1].assoc = 1; |
1588 | ktsb_descr[1].num_ttes = KERNEL_TSB4M_NENTRIES; | 1678 | ktsb_descr[1].num_ttes = KERNEL_TSB4M_NENTRIES; |
1589 | ktsb_descr[1].ctx_idx = 0; | 1679 | ktsb_descr[1].ctx_idx = 0; |
@@ -1606,6 +1696,47 @@ void __cpuinit sun4v_ktsb_register(void) | |||
1606 | } | 1696 | } |
1607 | } | 1697 | } |
1608 | 1698 | ||
1699 | static void __init sun4u_linear_pte_xor_finalize(void) | ||
1700 | { | ||
1701 | #ifndef CONFIG_DEBUG_PAGEALLOC | ||
1702 | /* This is where we would add Panther support for | ||
1703 | * 32MB and 256MB pages. | ||
1704 | */ | ||
1705 | #endif | ||
1706 | } | ||
1707 | |||
1708 | static void __init sun4v_linear_pte_xor_finalize(void) | ||
1709 | { | ||
1710 | #ifndef CONFIG_DEBUG_PAGEALLOC | ||
1711 | if (cpu_pgsz_mask & HV_PGSZ_MASK_256MB) { | ||
1712 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ | ||
1713 | 0xfffff80000000000UL; | ||
1714 | kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | | ||
1715 | _PAGE_P_4V | _PAGE_W_4V); | ||
1716 | } else { | ||
1717 | kern_linear_pte_xor[1] = kern_linear_pte_xor[0]; | ||
1718 | } | ||
1719 | |||
1720 | if (cpu_pgsz_mask & HV_PGSZ_MASK_2GB) { | ||
1721 | kern_linear_pte_xor[2] = (_PAGE_VALID | _PAGE_SZ2GB_4V) ^ | ||
1722 | 0xfffff80000000000UL; | ||
1723 | kern_linear_pte_xor[2] |= (_PAGE_CP_4V | _PAGE_CV_4V | | ||
1724 | _PAGE_P_4V | _PAGE_W_4V); | ||
1725 | } else { | ||
1726 | kern_linear_pte_xor[2] = kern_linear_pte_xor[1]; | ||
1727 | } | ||
1728 | |||
1729 | if (cpu_pgsz_mask & HV_PGSZ_MASK_16GB) { | ||
1730 | kern_linear_pte_xor[3] = (_PAGE_VALID | _PAGE_SZ16GB_4V) ^ | ||
1731 | 0xfffff80000000000UL; | ||
1732 | kern_linear_pte_xor[3] |= (_PAGE_CP_4V | _PAGE_CV_4V | | ||
1733 | _PAGE_P_4V | _PAGE_W_4V); | ||
1734 | } else { | ||
1735 | kern_linear_pte_xor[3] = kern_linear_pte_xor[2]; | ||
1736 | } | ||
1737 | #endif | ||
1738 | } | ||
1739 | |||
1609 | /* paging_init() sets up the page tables */ | 1740 | /* paging_init() sets up the page tables */ |
1610 | 1741 | ||
1611 | static unsigned long last_valid_pfn; | 1742 | static unsigned long last_valid_pfn; |
@@ -1665,10 +1796,8 @@ void __init paging_init(void) | |||
1665 | ktsb_phys_patch(); | 1796 | ktsb_phys_patch(); |
1666 | } | 1797 | } |
1667 | 1798 | ||
1668 | if (tlb_type == hypervisor) { | 1799 | if (tlb_type == hypervisor) |
1669 | sun4v_patch_tlb_handlers(); | 1800 | sun4v_patch_tlb_handlers(); |
1670 | sun4v_ktsb_init(); | ||
1671 | } | ||
1672 | 1801 | ||
1673 | /* Find available physical memory... | 1802 | /* Find available physical memory... |
1674 | * | 1803 | * |
@@ -1727,9 +1856,6 @@ void __init paging_init(void) | |||
1727 | 1856 | ||
1728 | __flush_tlb_all(); | 1857 | __flush_tlb_all(); |
1729 | 1858 | ||
1730 | if (tlb_type == hypervisor) | ||
1731 | sun4v_ktsb_register(); | ||
1732 | |||
1733 | prom_build_devicetree(); | 1859 | prom_build_devicetree(); |
1734 | of_populate_present_mask(); | 1860 | of_populate_present_mask(); |
1735 | #ifndef CONFIG_SMP | 1861 | #ifndef CONFIG_SMP |
@@ -1742,8 +1868,36 @@ void __init paging_init(void) | |||
1742 | #ifndef CONFIG_SMP | 1868 | #ifndef CONFIG_SMP |
1743 | mdesc_fill_in_cpu_data(cpu_all_mask); | 1869 | mdesc_fill_in_cpu_data(cpu_all_mask); |
1744 | #endif | 1870 | #endif |
1871 | mdesc_get_page_sizes(cpu_all_mask, &cpu_pgsz_mask); | ||
1872 | |||
1873 | sun4v_linear_pte_xor_finalize(); | ||
1874 | |||
1875 | sun4v_ktsb_init(); | ||
1876 | sun4v_ktsb_register(); | ||
1877 | } else { | ||
1878 | unsigned long impl, ver; | ||
1879 | |||
1880 | cpu_pgsz_mask = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K | | ||
1881 | HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB); | ||
1882 | |||
1883 | __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); | ||
1884 | impl = ((ver >> 32) & 0xffff); | ||
1885 | if (impl == PANTHER_IMPL) | ||
1886 | cpu_pgsz_mask |= (HV_PGSZ_MASK_32MB | | ||
1887 | HV_PGSZ_MASK_256MB); | ||
1888 | |||
1889 | sun4u_linear_pte_xor_finalize(); | ||
1745 | } | 1890 | } |
1746 | 1891 | ||
1892 | /* Flush the TLBs and the 4M TSB so that the updated linear | ||
1893 | * pte XOR settings are realized for all mappings. | ||
1894 | */ | ||
1895 | __flush_tlb_all(); | ||
1896 | #ifndef CONFIG_DEBUG_PAGEALLOC | ||
1897 | memset(swapper_4m_tsb, 0x40, sizeof(swapper_4m_tsb)); | ||
1898 | #endif | ||
1899 | __flush_tlb_all(); | ||
1900 | |||
1747 | /* Setup bootmem... */ | 1901 | /* Setup bootmem... */ |
1748 | last_valid_pfn = end_pfn = bootmem_init(phys_base); | 1902 | last_valid_pfn = end_pfn = bootmem_init(phys_base); |
1749 | 1903 | ||
@@ -2110,6 +2264,7 @@ static void __init sun4u_pgprot_init(void) | |||
2110 | { | 2264 | { |
2111 | unsigned long page_none, page_shared, page_copy, page_readonly; | 2265 | unsigned long page_none, page_shared, page_copy, page_readonly; |
2112 | unsigned long page_exec_bit; | 2266 | unsigned long page_exec_bit; |
2267 | int i; | ||
2113 | 2268 | ||
2114 | PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID | | 2269 | PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4U | _PAGE_VALID | |
2115 | _PAGE_CACHE_4U | _PAGE_P_4U | | 2270 | _PAGE_CACHE_4U | _PAGE_P_4U | |
@@ -2128,8 +2283,7 @@ static void __init sun4u_pgprot_init(void) | |||
2128 | __ACCESS_BITS_4U | _PAGE_E_4U); | 2283 | __ACCESS_BITS_4U | _PAGE_E_4U); |
2129 | 2284 | ||
2130 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2285 | #ifdef CONFIG_DEBUG_PAGEALLOC |
2131 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4U) ^ | 2286 | kern_linear_pte_xor[0] = _PAGE_VALID ^ 0xfffff80000000000UL; |
2132 | 0xfffff80000000000UL; | ||
2133 | #else | 2287 | #else |
2134 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ | 2288 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ |
2135 | 0xfffff80000000000UL; | 2289 | 0xfffff80000000000UL; |
@@ -2137,10 +2291,9 @@ static void __init sun4u_pgprot_init(void) | |||
2137 | kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | | 2291 | kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | |
2138 | _PAGE_P_4U | _PAGE_W_4U); | 2292 | _PAGE_P_4U | _PAGE_W_4U); |
2139 | 2293 | ||
2140 | /* XXX Should use 256MB on Panther. XXX */ | 2294 | for (i = 1; i < 4; i++) |
2141 | kern_linear_pte_xor[1] = kern_linear_pte_xor[0]; | 2295 | kern_linear_pte_xor[i] = kern_linear_pte_xor[0]; |
2142 | 2296 | ||
2143 | _PAGE_SZBITS = _PAGE_SZBITS_4U; | ||
2144 | _PAGE_ALL_SZ_BITS = (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U | | 2297 | _PAGE_ALL_SZ_BITS = (_PAGE_SZ4MB_4U | _PAGE_SZ512K_4U | |
2145 | _PAGE_SZ64K_4U | _PAGE_SZ8K_4U | | 2298 | _PAGE_SZ64K_4U | _PAGE_SZ8K_4U | |
2146 | _PAGE_SZ32MB_4U | _PAGE_SZ256MB_4U); | 2299 | _PAGE_SZ32MB_4U | _PAGE_SZ256MB_4U); |
@@ -2164,6 +2317,7 @@ static void __init sun4v_pgprot_init(void) | |||
2164 | { | 2317 | { |
2165 | unsigned long page_none, page_shared, page_copy, page_readonly; | 2318 | unsigned long page_none, page_shared, page_copy, page_readonly; |
2166 | unsigned long page_exec_bit; | 2319 | unsigned long page_exec_bit; |
2320 | int i; | ||
2167 | 2321 | ||
2168 | PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | | 2322 | PAGE_KERNEL = __pgprot (_PAGE_PRESENT_4V | _PAGE_VALID | |
2169 | _PAGE_CACHE_4V | _PAGE_P_4V | | 2323 | _PAGE_CACHE_4V | _PAGE_P_4V | |
@@ -2176,8 +2330,7 @@ static void __init sun4v_pgprot_init(void) | |||
2176 | _PAGE_CACHE = _PAGE_CACHE_4V; | 2330 | _PAGE_CACHE = _PAGE_CACHE_4V; |
2177 | 2331 | ||
2178 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2332 | #ifdef CONFIG_DEBUG_PAGEALLOC |
2179 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ | 2333 | kern_linear_pte_xor[0] = _PAGE_VALID ^ 0xfffff80000000000UL; |
2180 | 0xfffff80000000000UL; | ||
2181 | #else | 2334 | #else |
2182 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ | 2335 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ |
2183 | 0xfffff80000000000UL; | 2336 | 0xfffff80000000000UL; |
@@ -2185,20 +2338,12 @@ static void __init sun4v_pgprot_init(void) | |||
2185 | kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | | 2338 | kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | |
2186 | _PAGE_P_4V | _PAGE_W_4V); | 2339 | _PAGE_P_4V | _PAGE_W_4V); |
2187 | 2340 | ||
2188 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2341 | for (i = 1; i < 4; i++) |
2189 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ | 2342 | kern_linear_pte_xor[i] = kern_linear_pte_xor[0]; |
2190 | 0xfffff80000000000UL; | ||
2191 | #else | ||
2192 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ | ||
2193 | 0xfffff80000000000UL; | ||
2194 | #endif | ||
2195 | kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | | ||
2196 | _PAGE_P_4V | _PAGE_W_4V); | ||
2197 | 2343 | ||
2198 | pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V | | 2344 | pg_iobits = (_PAGE_VALID | _PAGE_PRESENT_4V | __DIRTY_BITS_4V | |
2199 | __ACCESS_BITS_4V | _PAGE_E_4V); | 2345 | __ACCESS_BITS_4V | _PAGE_E_4V); |
2200 | 2346 | ||
2201 | _PAGE_SZBITS = _PAGE_SZBITS_4V; | ||
2202 | _PAGE_ALL_SZ_BITS = (_PAGE_SZ16GB_4V | _PAGE_SZ2GB_4V | | 2347 | _PAGE_ALL_SZ_BITS = (_PAGE_SZ16GB_4V | _PAGE_SZ2GB_4V | |
2203 | _PAGE_SZ256MB_4V | _PAGE_SZ32MB_4V | | 2348 | _PAGE_SZ256MB_4V | _PAGE_SZ32MB_4V | |
2204 | _PAGE_SZ4MB_4V | _PAGE_SZ512K_4V | | 2349 | _PAGE_SZ4MB_4V | _PAGE_SZ512K_4V | |
@@ -2331,3 +2476,281 @@ void __flush_tlb_all(void) | |||
2331 | __asm__ __volatile__("wrpr %0, 0, %%pstate" | 2476 | __asm__ __volatile__("wrpr %0, 0, %%pstate" |
2332 | : : "r" (pstate)); | 2477 | : : "r" (pstate)); |
2333 | } | 2478 | } |
2479 | |||
2480 | static pte_t *get_from_cache(struct mm_struct *mm) | ||
2481 | { | ||
2482 | struct page *page; | ||
2483 | pte_t *ret; | ||
2484 | |||
2485 | spin_lock(&mm->page_table_lock); | ||
2486 | page = mm->context.pgtable_page; | ||
2487 | ret = NULL; | ||
2488 | if (page) { | ||
2489 | void *p = page_address(page); | ||
2490 | |||
2491 | mm->context.pgtable_page = NULL; | ||
2492 | |||
2493 | ret = (pte_t *) (p + (PAGE_SIZE / 2)); | ||
2494 | } | ||
2495 | spin_unlock(&mm->page_table_lock); | ||
2496 | |||
2497 | return ret; | ||
2498 | } | ||
2499 | |||
2500 | static struct page *__alloc_for_cache(struct mm_struct *mm) | ||
2501 | { | ||
2502 | struct page *page = alloc_page(GFP_KERNEL | __GFP_NOTRACK | | ||
2503 | __GFP_REPEAT | __GFP_ZERO); | ||
2504 | |||
2505 | if (page) { | ||
2506 | spin_lock(&mm->page_table_lock); | ||
2507 | if (!mm->context.pgtable_page) { | ||
2508 | atomic_set(&page->_count, 2); | ||
2509 | mm->context.pgtable_page = page; | ||
2510 | } | ||
2511 | spin_unlock(&mm->page_table_lock); | ||
2512 | } | ||
2513 | return page; | ||
2514 | } | ||
2515 | |||
2516 | pte_t *pte_alloc_one_kernel(struct mm_struct *mm, | ||
2517 | unsigned long address) | ||
2518 | { | ||
2519 | struct page *page; | ||
2520 | pte_t *pte; | ||
2521 | |||
2522 | pte = get_from_cache(mm); | ||
2523 | if (pte) | ||
2524 | return pte; | ||
2525 | |||
2526 | page = __alloc_for_cache(mm); | ||
2527 | if (page) | ||
2528 | pte = (pte_t *) page_address(page); | ||
2529 | |||
2530 | return pte; | ||
2531 | } | ||
2532 | |||
2533 | pgtable_t pte_alloc_one(struct mm_struct *mm, | ||
2534 | unsigned long address) | ||
2535 | { | ||
2536 | struct page *page; | ||
2537 | pte_t *pte; | ||
2538 | |||
2539 | pte = get_from_cache(mm); | ||
2540 | if (pte) | ||
2541 | return pte; | ||
2542 | |||
2543 | page = __alloc_for_cache(mm); | ||
2544 | if (page) { | ||
2545 | pgtable_page_ctor(page); | ||
2546 | pte = (pte_t *) page_address(page); | ||
2547 | } | ||
2548 | |||
2549 | return pte; | ||
2550 | } | ||
2551 | |||
2552 | void pte_free_kernel(struct mm_struct *mm, pte_t *pte) | ||
2553 | { | ||
2554 | struct page *page = virt_to_page(pte); | ||
2555 | if (put_page_testzero(page)) | ||
2556 | free_hot_cold_page(page, 0); | ||
2557 | } | ||
2558 | |||
2559 | static void __pte_free(pgtable_t pte) | ||
2560 | { | ||
2561 | struct page *page = virt_to_page(pte); | ||
2562 | if (put_page_testzero(page)) { | ||
2563 | pgtable_page_dtor(page); | ||
2564 | free_hot_cold_page(page, 0); | ||
2565 | } | ||
2566 | } | ||
2567 | |||
2568 | void pte_free(struct mm_struct *mm, pgtable_t pte) | ||
2569 | { | ||
2570 | __pte_free(pte); | ||
2571 | } | ||
2572 | |||
2573 | void pgtable_free(void *table, bool is_page) | ||
2574 | { | ||
2575 | if (is_page) | ||
2576 | __pte_free(table); | ||
2577 | else | ||
2578 | kmem_cache_free(pgtable_cache, table); | ||
2579 | } | ||
2580 | |||
2581 | #ifdef CONFIG_TRANSPARENT_HUGEPAGE | ||
2582 | static pmd_t pmd_set_protbits(pmd_t pmd, pgprot_t pgprot, bool for_modify) | ||
2583 | { | ||
2584 | if (pgprot_val(pgprot) & _PAGE_VALID) | ||
2585 | pmd_val(pmd) |= PMD_HUGE_PRESENT; | ||
2586 | if (tlb_type == hypervisor) { | ||
2587 | if (pgprot_val(pgprot) & _PAGE_WRITE_4V) | ||
2588 | pmd_val(pmd) |= PMD_HUGE_WRITE; | ||
2589 | if (pgprot_val(pgprot) & _PAGE_EXEC_4V) | ||
2590 | pmd_val(pmd) |= PMD_HUGE_EXEC; | ||
2591 | |||
2592 | if (!for_modify) { | ||
2593 | if (pgprot_val(pgprot) & _PAGE_ACCESSED_4V) | ||
2594 | pmd_val(pmd) |= PMD_HUGE_ACCESSED; | ||
2595 | if (pgprot_val(pgprot) & _PAGE_MODIFIED_4V) | ||
2596 | pmd_val(pmd) |= PMD_HUGE_DIRTY; | ||
2597 | } | ||
2598 | } else { | ||
2599 | if (pgprot_val(pgprot) & _PAGE_WRITE_4U) | ||
2600 | pmd_val(pmd) |= PMD_HUGE_WRITE; | ||
2601 | if (pgprot_val(pgprot) & _PAGE_EXEC_4U) | ||
2602 | pmd_val(pmd) |= PMD_HUGE_EXEC; | ||
2603 | |||
2604 | if (!for_modify) { | ||
2605 | if (pgprot_val(pgprot) & _PAGE_ACCESSED_4U) | ||
2606 | pmd_val(pmd) |= PMD_HUGE_ACCESSED; | ||
2607 | if (pgprot_val(pgprot) & _PAGE_MODIFIED_4U) | ||
2608 | pmd_val(pmd) |= PMD_HUGE_DIRTY; | ||
2609 | } | ||
2610 | } | ||
2611 | |||
2612 | return pmd; | ||
2613 | } | ||
2614 | |||
2615 | pmd_t pfn_pmd(unsigned long page_nr, pgprot_t pgprot) | ||
2616 | { | ||
2617 | pmd_t pmd; | ||
2618 | |||
2619 | pmd_val(pmd) = (page_nr << ((PAGE_SHIFT - PMD_PADDR_SHIFT))); | ||
2620 | pmd_val(pmd) |= PMD_ISHUGE; | ||
2621 | pmd = pmd_set_protbits(pmd, pgprot, false); | ||
2622 | return pmd; | ||
2623 | } | ||
2624 | |||
2625 | pmd_t pmd_modify(pmd_t pmd, pgprot_t newprot) | ||
2626 | { | ||
2627 | pmd_val(pmd) &= ~(PMD_HUGE_PRESENT | | ||
2628 | PMD_HUGE_WRITE | | ||
2629 | PMD_HUGE_EXEC); | ||
2630 | pmd = pmd_set_protbits(pmd, newprot, true); | ||
2631 | return pmd; | ||
2632 | } | ||
2633 | |||
2634 | pgprot_t pmd_pgprot(pmd_t entry) | ||
2635 | { | ||
2636 | unsigned long pte = 0; | ||
2637 | |||
2638 | if (pmd_val(entry) & PMD_HUGE_PRESENT) | ||
2639 | pte |= _PAGE_VALID; | ||
2640 | |||
2641 | if (tlb_type == hypervisor) { | ||
2642 | if (pmd_val(entry) & PMD_HUGE_PRESENT) | ||
2643 | pte |= _PAGE_PRESENT_4V; | ||
2644 | if (pmd_val(entry) & PMD_HUGE_EXEC) | ||
2645 | pte |= _PAGE_EXEC_4V; | ||
2646 | if (pmd_val(entry) & PMD_HUGE_WRITE) | ||
2647 | pte |= _PAGE_W_4V; | ||
2648 | if (pmd_val(entry) & PMD_HUGE_ACCESSED) | ||
2649 | pte |= _PAGE_ACCESSED_4V; | ||
2650 | if (pmd_val(entry) & PMD_HUGE_DIRTY) | ||
2651 | pte |= _PAGE_MODIFIED_4V; | ||
2652 | pte |= _PAGE_CP_4V|_PAGE_CV_4V; | ||
2653 | } else { | ||
2654 | if (pmd_val(entry) & PMD_HUGE_PRESENT) | ||
2655 | pte |= _PAGE_PRESENT_4U; | ||
2656 | if (pmd_val(entry) & PMD_HUGE_EXEC) | ||
2657 | pte |= _PAGE_EXEC_4U; | ||
2658 | if (pmd_val(entry) & PMD_HUGE_WRITE) | ||
2659 | pte |= _PAGE_W_4U; | ||
2660 | if (pmd_val(entry) & PMD_HUGE_ACCESSED) | ||
2661 | pte |= _PAGE_ACCESSED_4U; | ||
2662 | if (pmd_val(entry) & PMD_HUGE_DIRTY) | ||
2663 | pte |= _PAGE_MODIFIED_4U; | ||
2664 | pte |= _PAGE_CP_4U|_PAGE_CV_4U; | ||
2665 | } | ||
2666 | |||
2667 | return __pgprot(pte); | ||
2668 | } | ||
2669 | |||
2670 | void update_mmu_cache_pmd(struct vm_area_struct *vma, unsigned long addr, | ||
2671 | pmd_t *pmd) | ||
2672 | { | ||
2673 | unsigned long pte, flags; | ||
2674 | struct mm_struct *mm; | ||
2675 | pmd_t entry = *pmd; | ||
2676 | pgprot_t prot; | ||
2677 | |||
2678 | if (!pmd_large(entry) || !pmd_young(entry)) | ||
2679 | return; | ||
2680 | |||
2681 | pte = (pmd_val(entry) & ~PMD_HUGE_PROTBITS); | ||
2682 | pte <<= PMD_PADDR_SHIFT; | ||
2683 | pte |= _PAGE_VALID; | ||
2684 | |||
2685 | prot = pmd_pgprot(entry); | ||
2686 | |||
2687 | if (tlb_type == hypervisor) | ||
2688 | pgprot_val(prot) |= _PAGE_SZHUGE_4V; | ||
2689 | else | ||
2690 | pgprot_val(prot) |= _PAGE_SZHUGE_4U; | ||
2691 | |||
2692 | pte |= pgprot_val(prot); | ||
2693 | |||
2694 | mm = vma->vm_mm; | ||
2695 | |||
2696 | spin_lock_irqsave(&mm->context.lock, flags); | ||
2697 | |||
2698 | if (mm->context.tsb_block[MM_TSB_HUGE].tsb != NULL) | ||
2699 | __update_mmu_tsb_insert(mm, MM_TSB_HUGE, HPAGE_SHIFT, | ||
2700 | addr, pte); | ||
2701 | |||
2702 | spin_unlock_irqrestore(&mm->context.lock, flags); | ||
2703 | } | ||
2704 | #endif /* CONFIG_TRANSPARENT_HUGEPAGE */ | ||
2705 | |||
2706 | #if defined(CONFIG_HUGETLB_PAGE) || defined(CONFIG_TRANSPARENT_HUGEPAGE) | ||
2707 | static void context_reload(void *__data) | ||
2708 | { | ||
2709 | struct mm_struct *mm = __data; | ||
2710 | |||
2711 | if (mm == current->mm) | ||
2712 | load_secondary_context(mm); | ||
2713 | } | ||
2714 | |||
2715 | void hugetlb_setup(struct mm_struct *mm) | ||
2716 | { | ||
2717 | struct tsb_config *tp = &mm->context.tsb_block[MM_TSB_HUGE]; | ||
2718 | |||
2719 | if (likely(tp->tsb != NULL)) | ||
2720 | return; | ||
2721 | |||
2722 | tsb_grow(mm, MM_TSB_HUGE, 0); | ||
2723 | tsb_context_switch(mm); | ||
2724 | smp_tsb_sync(mm); | ||
2725 | |||
2726 | /* On UltraSPARC-III+ and later, configure the second half of | ||
2727 | * the Data-TLB for huge pages. | ||
2728 | */ | ||
2729 | if (tlb_type == cheetah_plus) { | ||
2730 | unsigned long ctx; | ||
2731 | |||
2732 | spin_lock(&ctx_alloc_lock); | ||
2733 | ctx = mm->context.sparc64_ctx_val; | ||
2734 | ctx &= ~CTX_PGSZ_MASK; | ||
2735 | ctx |= CTX_PGSZ_BASE << CTX_PGSZ0_SHIFT; | ||
2736 | ctx |= CTX_PGSZ_HUGE << CTX_PGSZ1_SHIFT; | ||
2737 | |||
2738 | if (ctx != mm->context.sparc64_ctx_val) { | ||
2739 | /* When changing the page size fields, we | ||
2740 | * must perform a context flush so that no | ||
2741 | * stale entries match. This flush must | ||
2742 | * occur with the original context register | ||
2743 | * settings. | ||
2744 | */ | ||
2745 | do_flush_tlb_mm(mm); | ||
2746 | |||
2747 | /* Reload the context register of all processors | ||
2748 | * also executing in this address space. | ||
2749 | */ | ||
2750 | mm->context.sparc64_ctx_val = ctx; | ||
2751 | on_each_cpu(context_reload, mm, 0); | ||
2752 | } | ||
2753 | spin_unlock(&ctx_alloc_lock); | ||
2754 | } | ||
2755 | } | ||
2756 | #endif | ||