aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arc/mm/fault.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/arch/arc/mm/fault.c b/arch/arc/mm/fault.c
index a3a292c58e50..8c7c81ce7f6a 100644
--- a/arch/arc/mm/fault.c
+++ b/arch/arc/mm/fault.c
@@ -64,9 +64,9 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
64 struct task_struct *tsk = current; 64 struct task_struct *tsk = current;
65 struct mm_struct *mm = tsk->mm; 65 struct mm_struct *mm = tsk->mm;
66 int si_code = SEGV_MAPERR; 66 int si_code = SEGV_MAPERR;
67 unsigned int write = 0, exec = 0, mask;
67 vm_fault_t fault; 68 vm_fault_t fault;
68 int write = regs->ecr_cause & ECR_C_PROTV_STORE; /* ST/EX */ 69 unsigned int flags;
69 unsigned int flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
70 70
71 /* 71 /*
72 * NOTE! We MUST NOT take any locks for this case. We may 72 * NOTE! We MUST NOT take any locks for this case. We may
@@ -88,8 +88,18 @@ void do_page_fault(unsigned long address, struct pt_regs *regs)
88 if (faulthandler_disabled() || !mm) 88 if (faulthandler_disabled() || !mm)
89 goto no_context; 89 goto no_context;
90 90
91 if (regs->ecr_cause & ECR_C_PROTV_STORE) /* ST/EX */
92 write = 1;
93 else if ((regs->ecr_vec == ECR_V_PROTV) &&
94 (regs->ecr_cause == ECR_C_PROTV_INST_FETCH))
95 exec = 1;
96
97 flags = FAULT_FLAG_ALLOW_RETRY | FAULT_FLAG_KILLABLE;
91 if (user_mode(regs)) 98 if (user_mode(regs))
92 flags |= FAULT_FLAG_USER; 99 flags |= FAULT_FLAG_USER;
100 if (write)
101 flags |= FAULT_FLAG_WRITE;
102
93retry: 103retry:
94 down_read(&mm->mmap_sem); 104 down_read(&mm->mmap_sem);
95 105
@@ -102,24 +112,17 @@ retry:
102 } 112 }
103 113
104 /* 114 /*
105 * Ok, we have a good vm_area for this memory access, so 115 * vm_area is good, now check permissions for this memory access
106 * we can handle it..
107 */ 116 */
108 si_code = SEGV_ACCERR; 117 mask = VM_READ;
109 118 if (write)
110 /* Handle protection violation, execute on heap or stack */ 119 mask = VM_WRITE;
111 120 if (exec)
112 if ((regs->ecr_vec == ECR_V_PROTV) && 121 mask = VM_EXEC;
113 (regs->ecr_cause == ECR_C_PROTV_INST_FETCH)) 122
123 if (!(vma->vm_flags & mask)) {
124 si_code = SEGV_ACCERR;
114 goto bad_area; 125 goto bad_area;
115
116 if (write) {
117 if (!(vma->vm_flags & VM_WRITE))
118 goto bad_area;
119 flags |= FAULT_FLAG_WRITE;
120 } else {
121 if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
122 goto bad_area;
123 } 126 }
124 127
125 /* 128 /*