diff options
Diffstat (limited to 'arch/s390/lib/uaccess_pt.c')
-rw-r--r-- | arch/s390/lib/uaccess_pt.c | 90 |
1 files changed, 27 insertions, 63 deletions
diff --git a/arch/s390/lib/uaccess_pt.c b/arch/s390/lib/uaccess_pt.c index b159a9d65680..7e8efaade2ea 100644 --- a/arch/s390/lib/uaccess_pt.c +++ b/arch/s390/lib/uaccess_pt.c | |||
@@ -15,6 +15,27 @@ | |||
15 | #include <asm/futex.h> | 15 | #include <asm/futex.h> |
16 | #include "uaccess.h" | 16 | #include "uaccess.h" |
17 | 17 | ||
18 | static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr) | ||
19 | { | ||
20 | pgd_t *pgd; | ||
21 | pud_t *pud; | ||
22 | pmd_t *pmd; | ||
23 | |||
24 | pgd = pgd_offset(mm, addr); | ||
25 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | ||
26 | return NULL; | ||
27 | |||
28 | pud = pud_offset(pgd, addr); | ||
29 | if (pud_none(*pud) || unlikely(pud_bad(*pud))) | ||
30 | return NULL; | ||
31 | |||
32 | pmd = pmd_offset(pud, addr); | ||
33 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | ||
34 | return NULL; | ||
35 | |||
36 | return pte_offset_map(pmd, addr); | ||
37 | } | ||
38 | |||
18 | static int __handle_fault(struct mm_struct *mm, unsigned long address, | 39 | static int __handle_fault(struct mm_struct *mm, unsigned long address, |
19 | int write_access) | 40 | int write_access) |
20 | { | 41 | { |
@@ -85,8 +106,6 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr, | |||
85 | { | 106 | { |
86 | struct mm_struct *mm = current->mm; | 107 | struct mm_struct *mm = current->mm; |
87 | unsigned long offset, pfn, done, size; | 108 | unsigned long offset, pfn, done, size; |
88 | pgd_t *pgd; | ||
89 | pmd_t *pmd; | ||
90 | pte_t *pte; | 109 | pte_t *pte; |
91 | void *from, *to; | 110 | void *from, *to; |
92 | 111 | ||
@@ -94,15 +113,7 @@ static size_t __user_copy_pt(unsigned long uaddr, void *kptr, | |||
94 | retry: | 113 | retry: |
95 | spin_lock(&mm->page_table_lock); | 114 | spin_lock(&mm->page_table_lock); |
96 | do { | 115 | do { |
97 | pgd = pgd_offset(mm, uaddr); | 116 | pte = follow_table(mm, uaddr); |
98 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | ||
99 | goto fault; | ||
100 | |||
101 | pmd = pmd_offset(pgd, uaddr); | ||
102 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | ||
103 | goto fault; | ||
104 | |||
105 | pte = pte_offset_map(pmd, uaddr); | ||
106 | if (!pte || !pte_present(*pte) || | 117 | if (!pte || !pte_present(*pte) || |
107 | (write_user && !pte_write(*pte))) | 118 | (write_user && !pte_write(*pte))) |
108 | goto fault; | 119 | goto fault; |
@@ -142,22 +153,12 @@ static unsigned long __dat_user_addr(unsigned long uaddr) | |||
142 | { | 153 | { |
143 | struct mm_struct *mm = current->mm; | 154 | struct mm_struct *mm = current->mm; |
144 | unsigned long pfn, ret; | 155 | unsigned long pfn, ret; |
145 | pgd_t *pgd; | ||
146 | pmd_t *pmd; | ||
147 | pte_t *pte; | 156 | pte_t *pte; |
148 | int rc; | 157 | int rc; |
149 | 158 | ||
150 | ret = 0; | 159 | ret = 0; |
151 | retry: | 160 | retry: |
152 | pgd = pgd_offset(mm, uaddr); | 161 | pte = follow_table(mm, uaddr); |
153 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | ||
154 | goto fault; | ||
155 | |||
156 | pmd = pmd_offset(pgd, uaddr); | ||
157 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | ||
158 | goto fault; | ||
159 | |||
160 | pte = pte_offset_map(pmd, uaddr); | ||
161 | if (!pte || !pte_present(*pte)) | 162 | if (!pte || !pte_present(*pte)) |
162 | goto fault; | 163 | goto fault; |
163 | 164 | ||
@@ -229,8 +230,6 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) | |||
229 | unsigned long uaddr = (unsigned long) src; | 230 | unsigned long uaddr = (unsigned long) src; |
230 | struct mm_struct *mm = current->mm; | 231 | struct mm_struct *mm = current->mm; |
231 | unsigned long offset, pfn, done, len; | 232 | unsigned long offset, pfn, done, len; |
232 | pgd_t *pgd; | ||
233 | pmd_t *pmd; | ||
234 | pte_t *pte; | 233 | pte_t *pte; |
235 | size_t len_str; | 234 | size_t len_str; |
236 | 235 | ||
@@ -240,15 +239,7 @@ static size_t strnlen_user_pt(size_t count, const char __user *src) | |||
240 | retry: | 239 | retry: |
241 | spin_lock(&mm->page_table_lock); | 240 | spin_lock(&mm->page_table_lock); |
242 | do { | 241 | do { |
243 | pgd = pgd_offset(mm, uaddr); | 242 | pte = follow_table(mm, uaddr); |
244 | if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd))) | ||
245 | goto fault; | ||
246 | |||
247 | pmd = pmd_offset(pgd, uaddr); | ||
248 | if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd))) | ||
249 | goto fault; | ||
250 | |||
251 | pte = pte_offset_map(pmd, uaddr); | ||
252 | if (!pte || !pte_present(*pte)) | 243 | if (!pte || !pte_present(*pte)) |
253 | goto fault; | 244 | goto fault; |
254 | 245 | ||
@@ -308,8 +299,6 @@ static size_t copy_in_user_pt(size_t n, void __user *to, | |||
308 | uaddr, done, size; | 299 | uaddr, done, size; |
309 | unsigned long uaddr_from = (unsigned long) from; | 300 | unsigned long uaddr_from = (unsigned long) from; |
310 | unsigned long uaddr_to = (unsigned long) to; | 301 | unsigned long uaddr_to = (unsigned long) to; |
311 | pgd_t *pgd_from, *pgd_to; | ||
312 | pmd_t *pmd_from, *pmd_to; | ||
313 | pte_t *pte_from, *pte_to; | 302 | pte_t *pte_from, *pte_to; |
314 | int write_user; | 303 | int write_user; |
315 | 304 | ||
@@ -317,39 +306,14 @@ static size_t copy_in_user_pt(size_t n, void __user *to, | |||
317 | retry: | 306 | retry: |
318 | spin_lock(&mm->page_table_lock); | 307 | spin_lock(&mm->page_table_lock); |
319 | do { | 308 | do { |
320 | pgd_from = pgd_offset(mm, uaddr_from); | 309 | pte_from = follow_table(mm, uaddr_from); |
321 | if (pgd_none(*pgd_from) || unlikely(pgd_bad(*pgd_from))) { | ||
322 | uaddr = uaddr_from; | ||
323 | write_user = 0; | ||
324 | goto fault; | ||
325 | } | ||
326 | pgd_to = pgd_offset(mm, uaddr_to); | ||
327 | if (pgd_none(*pgd_to) || unlikely(pgd_bad(*pgd_to))) { | ||
328 | uaddr = uaddr_to; | ||
329 | write_user = 1; | ||
330 | goto fault; | ||
331 | } | ||
332 | |||
333 | pmd_from = pmd_offset(pgd_from, uaddr_from); | ||
334 | if (pmd_none(*pmd_from) || unlikely(pmd_bad(*pmd_from))) { | ||
335 | uaddr = uaddr_from; | ||
336 | write_user = 0; | ||
337 | goto fault; | ||
338 | } | ||
339 | pmd_to = pmd_offset(pgd_to, uaddr_to); | ||
340 | if (pmd_none(*pmd_to) || unlikely(pmd_bad(*pmd_to))) { | ||
341 | uaddr = uaddr_to; | ||
342 | write_user = 1; | ||
343 | goto fault; | ||
344 | } | ||
345 | |||
346 | pte_from = pte_offset_map(pmd_from, uaddr_from); | ||
347 | if (!pte_from || !pte_present(*pte_from)) { | 310 | if (!pte_from || !pte_present(*pte_from)) { |
348 | uaddr = uaddr_from; | 311 | uaddr = uaddr_from; |
349 | write_user = 0; | 312 | write_user = 0; |
350 | goto fault; | 313 | goto fault; |
351 | } | 314 | } |
352 | pte_to = pte_offset_map(pmd_to, uaddr_to); | 315 | |
316 | pte_to = follow_table(mm, uaddr_to); | ||
353 | if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) { | 317 | if (!pte_to || !pte_present(*pte_to) || !pte_write(*pte_to)) { |
354 | uaddr = uaddr_to; | 318 | uaddr = uaddr_to; |
355 | write_user = 1; | 319 | write_user = 1; |