aboutsummaryrefslogtreecommitdiffstats
path: root/arch/s390
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390')
-rw-r--r--arch/s390/mm/pgtable.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index 5c1aea97cd12..3d98ba82ea67 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -254,36 +254,46 @@ void disable_noexec(struct mm_struct *mm, struct task_struct *tsk)
254int s390_enable_sie(void) 254int s390_enable_sie(void)
255{ 255{
256 struct task_struct *tsk = current; 256 struct task_struct *tsk = current;
257 struct mm_struct *mm; 257 struct mm_struct *mm, *old_mm;
258 int rc;
259 258
260 task_lock(tsk); 259 /* Do we have pgstes? if yes, we are done */
261
262 rc = 0;
263 if (tsk->mm->context.pgstes) 260 if (tsk->mm->context.pgstes)
264 goto unlock; 261 return 0;
265 262
266 rc = -EINVAL; 263 /* lets check if we are allowed to replace the mm */
264 task_lock(tsk);
267 if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 || 265 if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
268 tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) 266 tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) {
269 goto unlock; 267 task_unlock(tsk);
268 return -EINVAL;
269 }
270 task_unlock(tsk);
270 271
271 tsk->mm->context.pgstes = 1; /* dirty little tricks .. */ 272 /* we copy the mm with pgstes enabled */
273 tsk->mm->context.pgstes = 1;
272 mm = dup_mm(tsk); 274 mm = dup_mm(tsk);
273 tsk->mm->context.pgstes = 0; 275 tsk->mm->context.pgstes = 0;
274
275 rc = -ENOMEM;
276 if (!mm) 276 if (!mm)
277 goto unlock; 277 return -ENOMEM;
278 mmput(tsk->mm); 278
279 /* Now lets check again if somebody attached ptrace etc */
280 task_lock(tsk);
281 if (!tsk->mm || atomic_read(&tsk->mm->mm_users) > 1 ||
282 tsk->mm != tsk->active_mm || tsk->mm->ioctx_list) {
283 mmput(mm);
284 task_unlock(tsk);
285 return -EINVAL;
286 }
287
288 /* ok, we are alone. No ptrace, no threads, etc. */
289 old_mm = tsk->mm;
279 tsk->mm = tsk->active_mm = mm; 290 tsk->mm = tsk->active_mm = mm;
280 preempt_disable(); 291 preempt_disable();
281 update_mm(mm, tsk); 292 update_mm(mm, tsk);
282 cpu_set(smp_processor_id(), mm->cpu_vm_mask); 293 cpu_set(smp_processor_id(), mm->cpu_vm_mask);
283 preempt_enable(); 294 preempt_enable();
284 rc = 0;
285unlock:
286 task_unlock(tsk); 295 task_unlock(tsk);
287 return rc; 296 mmput(old_mm);
297 return 0;
288} 298}
289EXPORT_SYMBOL_GPL(s390_enable_sie); 299EXPORT_SYMBOL_GPL(s390_enable_sie);