diff options
Diffstat (limited to 'arch/powerpc/mm/tlb_nohash.c')
-rw-r--r-- | arch/powerpc/mm/tlb_nohash.c | 68 |
1 files changed, 63 insertions, 5 deletions
diff --git a/arch/powerpc/mm/tlb_nohash.c b/arch/powerpc/mm/tlb_nohash.c index d32ec643c231..4e13d6f9023e 100644 --- a/arch/powerpc/mm/tlb_nohash.c +++ b/arch/powerpc/mm/tlb_nohash.c | |||
@@ -28,6 +28,7 @@ | |||
28 | */ | 28 | */ |
29 | 29 | ||
30 | #include <linux/kernel.h> | 30 | #include <linux/kernel.h> |
31 | #include <linux/export.h> | ||
31 | #include <linux/mm.h> | 32 | #include <linux/mm.h> |
32 | #include <linux/init.h> | 33 | #include <linux/init.h> |
33 | #include <linux/highmem.h> | 34 | #include <linux/highmem.h> |
@@ -36,14 +37,49 @@ | |||
36 | #include <linux/spinlock.h> | 37 | #include <linux/spinlock.h> |
37 | #include <linux/memblock.h> | 38 | #include <linux/memblock.h> |
38 | #include <linux/of_fdt.h> | 39 | #include <linux/of_fdt.h> |
40 | #include <linux/hugetlb.h> | ||
39 | 41 | ||
40 | #include <asm/tlbflush.h> | 42 | #include <asm/tlbflush.h> |
41 | #include <asm/tlb.h> | 43 | #include <asm/tlb.h> |
42 | #include <asm/code-patching.h> | 44 | #include <asm/code-patching.h> |
45 | #include <asm/hugetlb.h> | ||
43 | 46 | ||
44 | #include "mmu_decl.h" | 47 | #include "mmu_decl.h" |
45 | 48 | ||
46 | #ifdef CONFIG_PPC_BOOK3E | 49 | /* |
50 | * This struct lists the sw-supported page sizes. The hardawre MMU may support | ||
51 | * other sizes not listed here. The .ind field is only used on MMUs that have | ||
52 | * indirect page table entries. | ||
53 | */ | ||
54 | #ifdef CONFIG_PPC_BOOK3E_MMU | ||
55 | #ifdef CONFIG_FSL_BOOKE | ||
56 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { | ||
57 | [MMU_PAGE_4K] = { | ||
58 | .shift = 12, | ||
59 | .enc = BOOK3E_PAGESZ_4K, | ||
60 | }, | ||
61 | [MMU_PAGE_4M] = { | ||
62 | .shift = 22, | ||
63 | .enc = BOOK3E_PAGESZ_4M, | ||
64 | }, | ||
65 | [MMU_PAGE_16M] = { | ||
66 | .shift = 24, | ||
67 | .enc = BOOK3E_PAGESZ_16M, | ||
68 | }, | ||
69 | [MMU_PAGE_64M] = { | ||
70 | .shift = 26, | ||
71 | .enc = BOOK3E_PAGESZ_64M, | ||
72 | }, | ||
73 | [MMU_PAGE_256M] = { | ||
74 | .shift = 28, | ||
75 | .enc = BOOK3E_PAGESZ_256M, | ||
76 | }, | ||
77 | [MMU_PAGE_1G] = { | ||
78 | .shift = 30, | ||
79 | .enc = BOOK3E_PAGESZ_1GB, | ||
80 | }, | ||
81 | }; | ||
82 | #else | ||
47 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { | 83 | struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { |
48 | [MMU_PAGE_4K] = { | 84 | [MMU_PAGE_4K] = { |
49 | .shift = 12, | 85 | .shift = 12, |
@@ -77,6 +113,8 @@ struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT] = { | |||
77 | .enc = BOOK3E_PAGESZ_1GB, | 113 | .enc = BOOK3E_PAGESZ_1GB, |
78 | }, | 114 | }, |
79 | }; | 115 | }; |
116 | #endif /* CONFIG_FSL_BOOKE */ | ||
117 | |||
80 | static inline int mmu_get_tsize(int psize) | 118 | static inline int mmu_get_tsize(int psize) |
81 | { | 119 | { |
82 | return mmu_psize_defs[psize].enc; | 120 | return mmu_psize_defs[psize].enc; |
@@ -87,7 +125,7 @@ static inline int mmu_get_tsize(int psize) | |||
87 | /* This isn't used on !Book3E for now */ | 125 | /* This isn't used on !Book3E for now */ |
88 | return 0; | 126 | return 0; |
89 | } | 127 | } |
90 | #endif | 128 | #endif /* CONFIG_PPC_BOOK3E_MMU */ |
91 | 129 | ||
92 | /* The variables below are currently only used on 64-bit Book3E | 130 | /* The variables below are currently only used on 64-bit Book3E |
93 | * though this will probably be made common with other nohash | 131 | * though this will probably be made common with other nohash |
@@ -266,6 +304,11 @@ void __flush_tlb_page(struct mm_struct *mm, unsigned long vmaddr, | |||
266 | 304 | ||
267 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) | 305 | void flush_tlb_page(struct vm_area_struct *vma, unsigned long vmaddr) |
268 | { | 306 | { |
307 | #ifdef CONFIG_HUGETLB_PAGE | ||
308 | if (is_vm_hugetlb_page(vma)) | ||
309 | flush_hugetlb_page(vma, vmaddr); | ||
310 | #endif | ||
311 | |||
269 | __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, | 312 | __flush_tlb_page(vma ? vma->vm_mm : NULL, vmaddr, |
270 | mmu_get_tsize(mmu_virtual_psize), 0); | 313 | mmu_get_tsize(mmu_virtual_psize), 0); |
271 | } | 314 | } |
@@ -600,13 +643,28 @@ void __cpuinit early_init_mmu_secondary(void) | |||
600 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, | 643 | void setup_initial_memory_limit(phys_addr_t first_memblock_base, |
601 | phys_addr_t first_memblock_size) | 644 | phys_addr_t first_memblock_size) |
602 | { | 645 | { |
603 | /* On Embedded 64-bit, we adjust the RMA size to match | 646 | /* On non-FSL Embedded 64-bit, we adjust the RMA size to match |
604 | * the bolted TLB entry. We know for now that only 1G | 647 | * the bolted TLB entry. We know for now that only 1G |
605 | * entries are supported though that may eventually | 648 | * entries are supported though that may eventually |
606 | * change. We crop it to the size of the first MEMBLOCK to | 649 | * change. |
650 | * | ||
651 | * on FSL Embedded 64-bit, we adjust the RMA size to match the | ||
652 | * first bolted TLB entry size. We still limit max to 1G even if | ||
653 | * the TLB could cover more. This is due to what the early init | ||
654 | * code is setup to do. | ||
655 | * | ||
656 | * We crop it to the size of the first MEMBLOCK to | ||
607 | * avoid going over total available memory just in case... | 657 | * avoid going over total available memory just in case... |
608 | */ | 658 | */ |
609 | ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); | 659 | #ifdef CONFIG_PPC_FSL_BOOK3E |
660 | if (mmu_has_feature(MMU_FTR_TYPE_FSL_E)) { | ||
661 | unsigned long linear_sz; | ||
662 | linear_sz = calc_cam_sz(first_memblock_size, PAGE_OFFSET, | ||
663 | first_memblock_base); | ||
664 | ppc64_rma_size = min_t(u64, linear_sz, 0x40000000); | ||
665 | } else | ||
666 | #endif | ||
667 | ppc64_rma_size = min_t(u64, first_memblock_size, 0x40000000); | ||
610 | 668 | ||
611 | /* Finally limit subsequent allocations */ | 669 | /* Finally limit subsequent allocations */ |
612 | memblock_set_current_limit(first_memblock_base + ppc64_rma_size); | 670 | memblock_set_current_limit(first_memblock_base + ppc64_rma_size); |