aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/mm
diff options
context:
space:
mode:
authorIan Munsie <imunsie@au1.ibm.com>2014-10-08 04:54:58 -0400
committerMichael Ellerman <mpe@ellerman.id.au>2014-10-08 05:15:44 -0400
commita1dca3465a7be53980abab1e0d6646176fdc075f (patch)
treee01d711450175ec03ce894a0e9ec8969ce0ecedd /arch/powerpc/mm
parent80c49c7e4a397bb245d72a78e41640eeb0b6e953 (diff)
powerpc/mm: Add new hash_page_mm()
This adds a new function hash_page_mm() based on the existing hash_page(). This version allows any struct mm to be passed in, rather than assuming current. This is useful for servicing co-processor faults which are not in the context of the current running process. We need to be careful here as the current hash_page() assumes current in a few places. Signed-off-by: Ian Munsie <imunsie@au1.ibm.com> Signed-off-by: Michael Neuling <mikey@neuling.org> Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/mm')
-rw-r--r--arch/powerpc/mm/hash_utils_64.c24
1 files changed, 17 insertions, 7 deletions
diff --git a/arch/powerpc/mm/hash_utils_64.c b/arch/powerpc/mm/hash_utils_64.c
index fe5609d7a9d7..d5339a3b9945 100644
--- a/arch/powerpc/mm/hash_utils_64.c
+++ b/arch/powerpc/mm/hash_utils_64.c
@@ -904,7 +904,7 @@ void demote_segment_4k(struct mm_struct *mm, unsigned long addr)
904 return; 904 return;
905 slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K); 905 slice_set_range_psize(mm, addr, 1, MMU_PAGE_4K);
906 copro_flush_all_slbs(mm); 906 copro_flush_all_slbs(mm);
907 if (get_paca_psize(addr) != MMU_PAGE_4K) { 907 if ((get_paca_psize(addr) != MMU_PAGE_4K) && (current->mm == mm)) {
908 get_paca()->context = mm->context; 908 get_paca()->context = mm->context;
909 slb_flush_and_rebolt(); 909 slb_flush_and_rebolt();
910 } 910 }
@@ -989,12 +989,11 @@ static void check_paca_psize(unsigned long ea, struct mm_struct *mm,
989 * -1 - critical hash insertion error 989 * -1 - critical hash insertion error
990 * -2 - access not permitted by subpage protection mechanism 990 * -2 - access not permitted by subpage protection mechanism
991 */ 991 */
992int 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)
993{ 993{
994 enum ctx_state prev_state = exception_enter(); 994 enum ctx_state prev_state = exception_enter();
995 pgd_t *pgdir; 995 pgd_t *pgdir;
996 unsigned long vsid; 996 unsigned long vsid;
997 struct mm_struct *mm;
998 pte_t *ptep; 997 pte_t *ptep;
999 unsigned hugeshift; 998 unsigned hugeshift;
1000 const struct cpumask *tmp; 999 const struct cpumask *tmp;
@@ -1008,7 +1007,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1008 switch (REGION_ID(ea)) { 1007 switch (REGION_ID(ea)) {
1009 case USER_REGION_ID: 1008 case USER_REGION_ID:
1010 user_region = 1; 1009 user_region = 1;
1011 mm = current->mm;
1012 if (! mm) { 1010 if (! mm) {
1013 DBG_LOW(" user region with no mm !\n"); 1011 DBG_LOW(" user region with no mm !\n");
1014 rc = 1; 1012 rc = 1;
@@ -1019,7 +1017,6 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1019 vsid = get_vsid(mm->context.id, ea, ssize); 1017 vsid = get_vsid(mm->context.id, ea, ssize);
1020 break; 1018 break;
1021 case VMALLOC_REGION_ID: 1019 case VMALLOC_REGION_ID:
1022 mm = &init_mm;
1023 vsid = get_kernel_vsid(ea, mmu_kernel_ssize); 1020 vsid = get_kernel_vsid(ea, mmu_kernel_ssize);
1024 if (ea < VMALLOC_END) 1021 if (ea < VMALLOC_END)
1025 psize = mmu_vmalloc_psize; 1022 psize = mmu_vmalloc_psize;
@@ -1104,7 +1101,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1104 WARN_ON(1); 1101 WARN_ON(1);
1105 } 1102 }
1106#endif 1103#endif
1107 check_paca_psize(ea, mm, psize, user_region); 1104 if (current->mm == mm)
1105 check_paca_psize(ea, mm, psize, user_region);
1108 1106
1109 goto bail; 1107 goto bail;
1110 } 1108 }
@@ -1145,7 +1143,8 @@ int hash_page(unsigned long ea, unsigned long access, unsigned long trap)
1145 } 1143 }
1146 } 1144 }
1147 1145
1148 check_paca_psize(ea, mm, psize, user_region); 1146 if (current->mm == mm)
1147 check_paca_psize(ea, mm, psize, user_region);
1149#endif /* CONFIG_PPC_64K_PAGES */ 1148#endif /* CONFIG_PPC_64K_PAGES */
1150 1149
1151#ifdef CONFIG_PPC_HAS_HASH_64K 1150#ifdef CONFIG_PPC_HAS_HASH_64K
@@ -1180,6 +1179,17 @@ bail:
1180 exception_exit(prev_state); 1179 exception_exit(prev_state);
1181 return rc; 1180 return rc;
1182} 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}
1183EXPORT_SYMBOL_GPL(hash_page); 1193EXPORT_SYMBOL_GPL(hash_page);
1184 1194
1185void hash_preload(struct mm_struct *mm, unsigned long ea, 1195void hash_preload(struct mm_struct *mm, unsigned long ea,