aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390/lib/uaccess_pt.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/lib/uaccess_pt.c')
-rw-r--r--arch/s390/lib/uaccess_pt.c90
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
18static 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
18static int __handle_fault(struct mm_struct *mm, unsigned long address, 39static 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,
94retry: 113retry:
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;
151retry: 160retry:
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)
240retry: 239retry:
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,
317retry: 306retry:
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;