aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/mm/fault.c30
1 files changed, 13 insertions, 17 deletions
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 0dcfcfb5b5be..5a9e9a77dc16 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -286,7 +286,7 @@ static noinline void do_fault_error(struct pt_regs *regs, long int_code,
286 * 11 Page translation -> Not present (nullification) 286 * 11 Page translation -> Not present (nullification)
287 * 3b Region third trans. -> Not present (nullification) 287 * 3b Region third trans. -> Not present (nullification)
288 */ 288 */
289static inline int do_exception(struct pt_regs *regs, int write, 289static inline int do_exception(struct pt_regs *regs, int access,
290 unsigned long trans_exc_code) 290 unsigned long trans_exc_code)
291{ 291{
292 struct task_struct *tsk; 292 struct task_struct *tsk;
@@ -337,19 +337,8 @@ static inline int do_exception(struct pt_regs *regs, int write,
337 * we can handle it.. 337 * we can handle it..
338 */ 338 */
339 fault = VM_FAULT_BADACCESS; 339 fault = VM_FAULT_BADACCESS;
340#ifdef CONFIG_S390_EXEC_PROTECT 340 if (unlikely(!(vma->vm_flags & access)))
341 if (unlikely((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY &&
342 (trans_exc_code & 3) == 0 && !(vma->vm_flags & VM_EXEC)))
343 goto out_up; 341 goto out_up;
344#endif
345 if (!write) {
346 /* page not present, check vm flags */
347 if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE)))
348 goto out_up;
349 } else {
350 if (!(vma->vm_flags & VM_WRITE))
351 goto out_up;
352 }
353 342
354 if (is_vm_hugetlb_page(vma)) 343 if (is_vm_hugetlb_page(vma))
355 address &= HPAGE_MASK; 344 address &= HPAGE_MASK;
@@ -358,7 +347,8 @@ static inline int do_exception(struct pt_regs *regs, int write,
358 * make sure we exit gracefully rather than endlessly redo 347 * make sure we exit gracefully rather than endlessly redo
359 * the fault. 348 * the fault.
360 */ 349 */
361 fault = handle_mm_fault(mm, vma, address, write ? FAULT_FLAG_WRITE : 0); 350 fault = handle_mm_fault(mm, vma, address,
351 (access == VM_WRITE) ? FAULT_FLAG_WRITE : 0);
362 if (unlikely(fault & VM_FAULT_ERROR)) 352 if (unlikely(fault & VM_FAULT_ERROR))
363 goto out_up; 353 goto out_up;
364 354
@@ -399,7 +389,7 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long int_code)
399 do_low_address(regs, int_code, trans_exc_code); 389 do_low_address(regs, int_code, trans_exc_code);
400 return; 390 return;
401 } 391 }
402 fault = do_exception(regs, 1, trans_exc_code); 392 fault = do_exception(regs, VM_WRITE, trans_exc_code);
403 if (unlikely(fault)) 393 if (unlikely(fault))
404 do_fault_error(regs, 4, trans_exc_code, fault); 394 do_fault_error(regs, 4, trans_exc_code, fault);
405} 395}
@@ -407,9 +397,15 @@ void __kprobes do_protection_exception(struct pt_regs *regs, long int_code)
407void __kprobes do_dat_exception(struct pt_regs *regs, long int_code) 397void __kprobes do_dat_exception(struct pt_regs *regs, long int_code)
408{ 398{
409 unsigned long trans_exc_code = S390_lowcore.trans_exc_code; 399 unsigned long trans_exc_code = S390_lowcore.trans_exc_code;
410 int fault; 400 int access, fault;
411 401
412 fault = do_exception(regs, 0, trans_exc_code); 402 access = VM_READ | VM_EXEC | VM_WRITE;
403#ifdef CONFIG_S390_EXEC_PROTECT
404 if ((regs->psw.mask & PSW_MASK_ASC) == PSW_ASC_SECONDARY &&
405 (trans_exc_code & 3) == 0)
406 access = VM_EXEC;
407#endif
408 fault = do_exception(regs, access, trans_exc_code);
413 if (unlikely(fault)) 409 if (unlikely(fault))
414 do_fault_error(regs, int_code & 255, trans_exc_code, fault); 410 do_fault_error(regs, int_code & 255, trans_exc_code, fault);
415} 411}