aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm/hash_utils_64.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/mm/hash_utils_64.c')
-rw-r--r--arch/powerpc/mm/hash_utils_64.c186
1 files changed, 91 insertions, 95 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index 88fdd9d25077..d5339a3b9945 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -51,7 +51,7 @@
51#include <asm/cacheflush.h> 51#include <asm/cacheflush.h>
52#include <asm/cputable.h> 52#include <asm/cputable.h>
53#include <asm/sections.h> 53#include <asm/sections.h>
54#include <asm/spu.h> 54#include <asm/copro.h>
55#include <asm/udbg.h> 55#include <asm/udbg.h>
56#include <asm/code-patching.h> 56#include <asm/code-patching.h>
57#include <asm/fadump.h> 57#include <asm/fadump.h>
@@ -92,12 +92,14 @@ extern unsigned long dart_tablebase;
92 92
93static unsigned long _SDR1; 93static unsigned long _SDR1;
94struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT]; 94struct mmu_psize_def mmu_psize_defs[MMU_PAGE_COUNT];
95EXPORT_SYMBOL_GPL(mmu_psize_defs);
95 96
96struct hash_pte *htab_address; 97struct hash_pte *htab_address;
97unsigned long htab_size_bytes; 98unsigned long htab_size_bytes;
98unsigned long htab_hash_mask; 99unsigned long htab_hash_mask;
99EXPORT_SYMBOL_GPL(htab_hash_mask); 100EXPORT_SYMBOL_GPL(htab_hash_mask);
100int mmu_linear_psize = MMU_PAGE_4K; 101int mmu_linear_psize = MMU_PAGE_4K;
102EXPORT_SYMBOL_GPL(mmu_linear_psize);
101int mmu_virtual_psize = MMU_PAGE_4K; 103int mmu_virtual_psize = MMU_PAGE_4K;
102int mmu_vmalloc_psize = MMU_PAGE_4K; 104int mmu_vmalloc_psize = MMU_PAGE_4K;
103#ifdef CONFIG_SPARSEMEM_VMEMMAP 105#ifdef CONFIG_SPARSEMEM_VMEMMAP
@@ -105,6 +107,7 @@ int mmu_vmemmap_psize = MMU_PAGE_4K;
105#endif 107#endif
106int mmu_io_psize = MMU_PAGE_4K; 108int mmu_io_psize = MMU_PAGE_4K;
107int mmu_kernel_ssize = MMU_SEGSIZE_256M; 109int mmu_kernel_ssize = MMU_SEGSIZE_256M;
110EXPORT_SYMBOL_GPL(mmu_kernel_ssize);
108int mmu_highuser_ssize = MMU_SEGSIZE_256M; 111int mmu_highuser_ssize = MMU_SEGSIZE_256M;
109u16 mmu_slb_size = 64; 112u16 mmu_slb_size = 64;
110EXPORT_SYMBOL_GPL(mmu_slb_size); 113EXPORT_SYMBOL_GPL(mmu_slb_size);
@@ -243,7 +246,7 @@ int htab_bolt_mapping(unsigned long vstart, unsigned long vend,
243} 246}
244 247
245#ifdef CONFIG_MEMORY_HOTPLUG 248#ifdef CONFIG_MEMORY_HOTPLUG
246static int htab_remove_mapping(unsigned long vstart, unsigned long vend, 249int htab_remove_mapping(unsigned long vstart, unsigned long vend,
247 int psize, int ssize) 250 int psize, int ssize)
248{ 251{
249 unsigned long vaddr; 252 unsigned long vaddr;
@@ -333,70 +336,69 @@ static int __init htab_dt_scan_page_sizes(unsigned long node,
333 return 0; 336 return 0;
334 337
335 prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size); 338 prop = of_get_flat_dt_prop(node, "ibm,segment-page-sizes", &size);
336 if (prop != NULL) { 339 if (!prop)
337 pr_info("Page sizes from device-tree:\n"); 340 return 0;
338 size /= 4; 341
339 cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE); 342 pr_info("Page sizes from device-tree:\n");
340 while(size > 0) { 343 size /= 4;
341 unsigned int base_shift = be32_to_cpu(prop[0]); 344 cur_cpu_spec->mmu_features &= ~(MMU_FTR_16M_PAGE);
342 unsigned int slbenc = be32_to_cpu(prop[1]); 345 while(size > 0) {
343 unsigned int lpnum = be32_to_cpu(prop[2]); 346 unsigned int base_shift = be32_to_cpu(prop[0]);
344 struct mmu_psize_def *def; 347 unsigned int slbenc = be32_to_cpu(prop[1]);
345 int idx, base_idx; 348 unsigned int lpnum = be32_to_cpu(prop[2]);
346 349 struct mmu_psize_def *def;
347 size -= 3; prop += 3; 350 int idx, base_idx;
348 base_idx = get_idx_from_shift(base_shift); 351
349 if (base_idx < 0) { 352 size -= 3; prop += 3;
350 /* 353 base_idx = get_idx_from_shift(base_shift);
351 * skip the pte encoding also 354 if (base_idx < 0) {
352 */ 355 /* skip the pte encoding also */
353 prop += lpnum * 2; size -= lpnum * 2; 356 prop += lpnum * 2; size -= lpnum * 2;
357 continue;
358 }
359 def = &mmu_psize_defs[base_idx];
360 if (base_idx == MMU_PAGE_16M)
361 cur_cpu_spec->mmu_features |= MMU_FTR_16M_PAGE;
362
363 def->shift = base_shift;
364 if (base_shift <= 23)
365 def->avpnm = 0;
366 else
367 def->avpnm = (1 << (base_shift - 23)) - 1;
368 def->sllp = slbenc;
369 /*
370 * We don't know for sure what's up with tlbiel, so
371 * for now we only set it for 4K and 64K pages
372 */
373 if (base_idx == MMU_PAGE_4K || base_idx == MMU_PAGE_64K)
374 def->tlbiel = 1;
375 else
376 def->tlbiel = 0;
377
378 while (size > 0 && lpnum) {
379 unsigned int shift = be32_to_cpu(prop[0]);
380 int penc = be32_to_cpu(prop[1]);
381
382 prop += 2; size -= 2;
383 lpnum--;
384
385 idx = get_idx_from_shift(shift);
386 if (idx < 0)
354 continue; 387 continue;
355 } 388
356 def = &mmu_psize_defs[base_idx]; 389 if (penc == -1)
357 if (base_idx == MMU_PAGE_16M) 390 pr_err("Invalid penc for base_shift=%d "
358 cur_cpu_spec->mmu_features |= MMU_FTR_16M_PAGE; 391 "shift=%d\n", base_shift, shift);
359 392
360 def->shift = base_shift; 393 def->penc[idx] = penc;
361 if (base_shift <= 23) 394 pr_info("base_shift=%d: shift=%d, sllp=0x%04lx,"
362 def->avpnm = 0; 395 " avpnm=0x%08lx, tlbiel=%d, penc=%d\n",
363 else 396 base_shift, shift, def->sllp,
364 def->avpnm = (1 << (base_shift - 23)) - 1; 397 def->avpnm, def->tlbiel, def->penc[idx]);
365 def->sllp = slbenc;
366 /*
367 * We don't know for sure what's up with tlbiel, so
368 * for now we only set it for 4K and 64K pages
369 */
370 if (base_idx == MMU_PAGE_4K || base_idx == MMU_PAGE_64K)
371 def->tlbiel = 1;
372 else
373 def->tlbiel = 0;
374
375 while (size > 0 && lpnum) {
376 unsigned int shift = be32_to_cpu(prop[0]);
377 int penc = be32_to_cpu(prop[1]);
378
379 prop += 2; size -= 2;
380 lpnum--;
381
382 idx = get_idx_from_shift(shift);
383 if (idx < 0)
384 continue;
385
386 if (penc == -1)
387 pr_err("Invalid penc for base_shift=%d "
388 "shift=%d\n", base_shift, shift);
389
390 def->penc[idx] = penc;
391 pr_info("base_shift=%d: shift=%d, sllp=0x%04lx,"
392 " avpnm=0x%08lx, tlbiel=%d, penc=%d\n",
393 base_shift, shift, def->sllp,
394 def->avpnm, def->tlbiel, def->penc[idx]);
395 }
396 } 398 }
397 return 1;
398 } 399 }
399 return 0; 400
401 return 1;
400} 402}
401 403
402#ifdef CONFIG_HUGETLB_PAGE 404#ifdef CONFIG_HUGETLB_PAGE
@@ -821,21 +823,14 @@ static void __init htab_initialize(void)
821 823
822void __init early_init_mmu(void) 824void __init early_init_mmu(void)
823{ 825{
824 /* Setup initial STAB address in the PACA */
825 get_paca()->stab_real = __pa((u64)&initial_stab);
826 get_paca()->stab_addr = (u64)&initial_stab;
827
828 /* Initialize the MMU Hash table and create the linear mapping 826 /* Initialize the MMU Hash table and create the linear mapping
829 * of memory. Has to be done before stab/slb initialization as 827 * of memory. Has to be done before SLB initialization as this is
830 * this is currently where the page size encoding is obtained 828 * currently where the page size encoding is obtained.
831 */ 829 */
832 htab_initialize(); 830 htab_initialize();
833 831
834 /* Initialize stab / SLB management */ 832 /* Initialize SLB management */
835 if (mmu_has_feature(MMU_FTR_SLB)) 833 slb_initialize();
836 slb_initialize();
837 else
838 stab_initialize(get_paca()->stab_real);
839} 834}
840 835
841#ifdef CONFIG_SMP 836#ifdef CONFIG_SMP
@@ -845,13 +840,8 @@ void early_init_mmu_secondary(void)
845 if (!firmware_has_feature(FW_FEATURE_LPAR)) 840 if (!firmware_has_feature(FW_FEATURE_LPAR))
846 mtspr(SPRN_SDR1, _SDR1); 841 mtspr(SPRN_SDR1, _SDR1);
847 842
848 /* Initialize STAB/SLB. We use a virtual address as it works 843 /* Initialize SLB */
849 * in real mode on pSeries. 844 slb_initialize();
850 */
851 if (mmu_has_feature(MMU_FTR_SLB))
852 slb_initialize();
853 else
854 stab_initialize(get_paca()->stab_addr);
855} 845}
856#endif /* CONFIG_SMP */ 846#endif /* CONFIG_SMP */
857 847
@@ -879,7 +869,7 @@ unsigned int hash_page_do_lazy_icache(unsigned int pp, pte_t pte, int trap)
879} 869}
880 870
881#ifdef CONFIG_PPC_MM_SLICES 871#ifdef CONFIG_PPC_MM_SLICES
882unsigned int get_paca_psize(unsigned long addr) 872static unsigned int get_paca_psize(unsigned long addr)
883{ 873{
884 u64 lpsizes; 874 u64 lpsizes;
885 unsigned char *hpsizes; 875 unsigned char *hpsizes;
@@ -913,10 +903,8 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
913 if (get_slice_psize(mm, addr) == MMU_PAGE_4K) 903 if (get_slice_psize(mm, addr) == MMU_PAGE_4K)
914 return; 904 return;
915 slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K); 905 slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K);
916#ifdef CONFIG_SPU_BASE 906 copro_flush_all_slbs(mm);
917 spu_flush_all_slbs(mm); 907 if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) {
918#endif
919 if (get_paca_psize(addr) != MMU_PAGE_4K) {
920 get_paca()->context = mm->context; 908 get_paca()->context = mm->context;
921 slb_flush_and_rebolt(); 909 slb_flush_and_rebolt();
922 } 910 }
@@ -1001,12 +989,11 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
1001 * -1 - critical hash insertion error 989 * -1 - critical hash insertion error
1002 * -2 - access not permitted by subpage protection mechanism 990 * -2 - access not permitted by subpage protection mechanism
1003 */ 991 */
1004int hash_page(unsigned long ea, unsigned long access, unsigned long trap) 992int hash_page_mm(struct mm_struct *mm, unsigned long ea, unsigned long access, unsigned long trap)
1005{ 993{
1006 enum ctx_state prev_state = exception_enter(); 994 enum ctx_state prev_state = exception_enter();
1007 pgd_t *pgdir; 995 pgd_t *pgdir;
1008 unsigned long vsid; 996 unsigned long vsid;
1009 struct mm_struct *mm;
1010 pte_t *ptep; 997 pte_t *ptep;
1011 unsigned hugeshift; 998 unsigned hugeshift;
1012 const struct cpumask *tmp; 999 const struct cpumask *tmp;
@@ -1020,7 +1007,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1020 switch (REGION_ID(ea)) { 1007 switch (REGION_ID(ea)) {
1021 case USER_REGION_ID: 1008 case USER_REGION_ID:
1022 user_region = 1; 1009 user_region = 1;
1023 mm = current->mm;
1024 if (! mm) { 1010 if (! mm) {
1025 DBG_LOW(" user region with no mm !\n"); 1011 DBG_LOW(" user region with no mm !\n");
1026 rc = 1; 1012 rc = 1;
@@ -1031,7 +1017,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1031 vsid = get_vsid(mm->context.id, ea, ssize); 1017 vsid = get_vsid(mm->context.id, ea, ssize);
1032 break; 1018 break;
1033 case VMALLOC_REGION_ID: 1019 case VMALLOC_REGION_ID:
1034 mm = &init_mm;
1035 vsid = get_kernel_vsid(ea, mmu_kernel_ssize); 1020 vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
1036 if (ea < VMALLOC_END) 1021 if (ea < VMALLOC_END)
1037 psize = mmu_vmalloc_psize; 1022 psize = mmu_vmalloc_psize;
@@ -1116,7 +1101,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1116 WARN_ON(1); 1101 WARN_ON(1);
1117 } 1102 }
1118#endif 1103#endif
1119 check_paca_psize(ea, mm, psize, user_region); 1104 if (current->mm == mm)
1105 check_paca_psize(ea, mm, psize, user_region);
1120 1106
1121 goto bail; 1107 goto bail;
1122 } 1108 }
@@ -1153,13 +1139,12 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1153 "to 4kB pages because of " 1139 "to 4kB pages because of "
1154 "non-cacheable mapping\n"); 1140 "non-cacheable mapping\n");
1155 psize = mmu_vmalloc_psize = MMU_PAGE_4K; 1141 psize = mmu_vmalloc_psize = MMU_PAGE_4K;
1156#ifdef CONFIG_SPU_BASE 1142 copro_flush_all_slbs(mm);
1157 spu_flush_all_slbs(mm);
1158#endif
1159 } 1143 }
1160 } 1144 }
1161 1145
1162 check_paca_psize(ea, mm, psize, user_region); 1146 if (current->mm == mm)
1147 check_paca_psize(ea, mm, psize, user_region);
1163#endif /* CONFIG_PPC_64K_PAGES */ 1148#endif /* CONFIG_PPC_64K_PAGES */
1164 1149
1165#ifdef CONFIG_PPC_HAS_HASH_64K 1150#ifdef CONFIG_PPC_HAS_HASH_64K
@@ -1194,6 +1179,17 @@ bail:
1194 exception_exit(prev_state); 1179 exception_exit(prev_state);
1195 return rc; 1180 return rc;
1196} 1181}
1182EXPORT_SYMBOL_GPL(hash_page_mm);
1183
1184int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1185{
1186 struct mm_struct *mm = current->mm;
1187
1188 if (REGION_ID(ea) == VMALLOC_REGION_ID)
1189 mm = &init_mm;
1190
1191 return hash_page_mm(mm, ea, access, trap);
1192}
1197EXPORT_SYMBOL_GPL(hash_page); 1193EXPORT_SYMBOL_GPL(hash_page);
1198 1194
1199void hash_preload(struct mm_struct *mm, unsigned long ea, 1195void hash_preload(struct mm_struct *mm, unsigned long ea,