aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/processor.h2
-rw-r--r--arch/s390/kernel/entry.h1
-rw-r--r--arch/s390/kernel/pgm_check.S2
-rw-r--r--arch/s390/mm/fault.c37
-rw-r--r--arch/s390/mm/mmap.c12
-rw-r--r--arch/s390/mm/pgtable.c18
6 files changed, 21 insertions, 51 deletions
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h
index a56e63483e0f..0a876bc543d3 100644
--- a/arch/s390/include/asm/processor.h
+++ b/arch/s390/include/asm/processor.h
@@ -144,9 +144,7 @@ struct stack_frame {
144 regs->psw.mask = PSW_USER_BITS | PSW_MASK_BA; \ 144 regs->psw.mask = PSW_USER_BITS | PSW_MASK_BA; \
145 regs->psw.addr = new_psw | PSW_ADDR_AMODE; \ 145 regs->psw.addr = new_psw | PSW_ADDR_AMODE; \
146 regs->gprs[15] = new_stackp; \ 146 regs->gprs[15] = new_stackp; \
147 __tlb_flush_mm(current->mm); \
148 crst_table_downgrade(current->mm, 1UL << 31); \ 147 crst_table_downgrade(current->mm, 1UL << 31); \
149 update_mm(current->mm, current); \
150 execve_tail(); \ 148 execve_tail(); \
151} while (0) 149} while (0)
152 150
diff --git a/arch/s390/kernel/entry.h b/arch/s390/kernel/entry.h
index e9b04c33d383..cb533f78c09e 100644
--- a/arch/s390/kernel/entry.h
+++ b/arch/s390/kernel/entry.h
@@ -23,7 +23,6 @@ asmlinkage void do_syscall_trace_exit(struct pt_regs *regs);
23 23
24void do_protection_exception(struct pt_regs *regs); 24void do_protection_exception(struct pt_regs *regs);
25void do_dat_exception(struct pt_regs *regs); 25void do_dat_exception(struct pt_regs *regs);
26void do_asce_exception(struct pt_regs *regs);
27 26
28void addressing_exception(struct pt_regs *regs); 27void addressing_exception(struct pt_regs *regs);
29void data_exception(struct pt_regs *regs); 28void data_exception(struct pt_regs *regs);
diff --git a/arch/s390/kernel/pgm_check.S b/arch/s390/kernel/pgm_check.S
index 14bdecb61923..4a460c44e17e 100644
--- a/arch/s390/kernel/pgm_check.S
+++ b/arch/s390/kernel/pgm_check.S
@@ -78,7 +78,7 @@ PGM_CHECK_DEFAULT /* 34 */
78PGM_CHECK_DEFAULT /* 35 */ 78PGM_CHECK_DEFAULT /* 35 */
79PGM_CHECK_DEFAULT /* 36 */ 79PGM_CHECK_DEFAULT /* 36 */
80PGM_CHECK_DEFAULT /* 37 */ 80PGM_CHECK_DEFAULT /* 37 */
81PGM_CHECK_64BIT(do_asce_exception) /* 38 */ 81PGM_CHECK_DEFAULT /* 38 */
82PGM_CHECK_64BIT(do_dat_exception) /* 39 */ 82PGM_CHECK_64BIT(do_dat_exception) /* 39 */
83PGM_CHECK_64BIT(do_dat_exception) /* 3a */ 83PGM_CHECK_64BIT(do_dat_exception) /* 3a */
84PGM_CHECK_64BIT(do_dat_exception) /* 3b */ 84PGM_CHECK_64BIT(do_dat_exception) /* 3b */
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 8f29762671cf..d95265b2719f 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -423,43 +423,6 @@ void __kprobes do_dat_exception(struct pt_regs *regs)
423 do_fault_error(regs, fault); 423 do_fault_error(regs, fault);
424} 424}
425 425
426#ifdef CONFIG_64BIT
427void __kprobes do_asce_exception(struct pt_regs *regs)
428{
429 struct mm_struct *mm = current->mm;
430 struct vm_area_struct *vma;
431 unsigned long trans_exc_code;
432
433 /*
434 * The instruction that caused the program check has
435 * been nullified. Don't signal single step via SIGTRAP.
436 */
437 clear_tsk_thread_flag(current, TIF_PER_TRAP);
438
439 trans_exc_code = regs->int_parm_long;
440 if (unlikely(!user_space_fault(trans_exc_code) || in_atomic() || !mm))
441 goto no_context;
442
443 down_read(&mm->mmap_sem);
444 vma = find_vma(mm, trans_exc_code & __FAIL_ADDR_MASK);
445 up_read(&mm->mmap_sem);
446
447 if (vma) {
448 update_mm(mm, current);
449 return;
450 }
451
452 /* User mode accesses just cause a SIGSEGV */
453 if (user_mode(regs)) {
454 do_sigsegv(regs, SEGV_MAPERR);
455 return;
456 }
457
458no_context:
459 do_no_context(regs);
460}
461#endif
462
463int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) 426int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write)
464{ 427{
465 struct pt_regs regs; 428 struct pt_regs regs;
diff --git a/arch/s390/mm/mmap.c b/arch/s390/mm/mmap.c
index 40023290ee5b..6bcb045d2bd2 100644
--- a/arch/s390/mm/mmap.c
+++ b/arch/s390/mm/mmap.c
@@ -101,18 +101,12 @@ void arch_pick_mmap_layout(struct mm_struct *mm)
101 101
102int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) 102int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags)
103{ 103{
104 int rc;
105
106 if (is_compat_task() || (TASK_SIZE >= (1UL << 53))) 104 if (is_compat_task() || (TASK_SIZE >= (1UL << 53)))
107 return 0; 105 return 0;
108 if (!(flags & MAP_FIXED)) 106 if (!(flags & MAP_FIXED))
109 addr = 0; 107 addr = 0;
110 if ((addr + len) >= TASK_SIZE) { 108 if ((addr + len) >= TASK_SIZE)
111 rc = crst_table_upgrade(current->mm, 1UL << 53); 109 return crst_table_upgrade(current->mm, 1UL << 53);
112 if (rc)
113 return rc;
114 update_mm(current->mm, current);
115 }
116 return 0; 110 return 0;
117} 111}
118 112
@@ -132,7 +126,6 @@ s390_get_unmapped_area(struct file *filp, unsigned long addr,
132 rc = crst_table_upgrade(mm, 1UL << 53); 126 rc = crst_table_upgrade(mm, 1UL << 53);
133 if (rc) 127 if (rc)
134 return (unsigned long) rc; 128 return (unsigned long) rc;
135 update_mm(mm, current);
136 area = arch_get_unmapped_area(filp, addr, len, pgoff, flags); 129 area = arch_get_unmapped_area(filp, addr, len, pgoff, flags);
137 } 130 }
138 return area; 131 return area;
@@ -155,7 +148,6 @@ s390_get_unmapped_area_topdown(struct file *filp, const unsigned long addr,
155 rc = crst_table_upgrade(mm, 1UL << 53); 148 rc = crst_table_upgrade(mm, 1UL << 53);
156 if (rc) 149 if (rc)
157 return (unsigned long) rc; 150 return (unsigned long) rc;
158 update_mm(mm, current);
159 area = arch_get_unmapped_area_topdown(filp, addr, len, 151 area = arch_get_unmapped_area_topdown(filp, addr, len,
160 pgoff, flags); 152 pgoff, flags);
161 } 153 }
diff --git a/arch/s390/mm/pgtable.c b/arch/s390/mm/pgtable.c
index a9be08899b0c..0a2e5e086749 100644
--- a/arch/s390/mm/pgtable.c
+++ b/arch/s390/mm/pgtable.c
@@ -48,12 +48,23 @@ void crst_table_free(struct mm_struct *mm, unsigned long *table)
48} 48}
49 49
50#ifdef CONFIG_64BIT 50#ifdef CONFIG_64BIT
51static void __crst_table_upgrade(void *arg)
52{
53 struct mm_struct *mm = arg;
54
55 if (current->active_mm == mm)
56 update_mm(mm, current);
57 __tlb_flush_local();
58}
59
51int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) 60int crst_table_upgrade(struct mm_struct *mm, unsigned long limit)
52{ 61{
53 unsigned long *table, *pgd; 62 unsigned long *table, *pgd;
54 unsigned long entry; 63 unsigned long entry;
64 int flush;
55 65
56 BUG_ON(limit > (1UL << 53)); 66 BUG_ON(limit > (1UL << 53));
67 flush = 0;
57repeat: 68repeat:
58 table = crst_table_alloc(mm); 69 table = crst_table_alloc(mm);
59 if (!table) 70 if (!table)
@@ -79,12 +90,15 @@ repeat:
79 mm->pgd = (pgd_t *) table; 90 mm->pgd = (pgd_t *) table;
80 mm->task_size = mm->context.asce_limit; 91 mm->task_size = mm->context.asce_limit;
81 table = NULL; 92 table = NULL;
93 flush = 1;
82 } 94 }
83 spin_unlock_bh(&mm->page_table_lock); 95 spin_unlock_bh(&mm->page_table_lock);
84 if (table) 96 if (table)
85 crst_table_free(mm, table); 97 crst_table_free(mm, table);
86 if (mm->context.asce_limit < limit) 98 if (mm->context.asce_limit < limit)
87 goto repeat; 99 goto repeat;
100 if (flush)
101 on_each_cpu(__crst_table_upgrade, mm, 0);
88 return 0; 102 return 0;
89} 103}
90 104
@@ -92,6 +106,8 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
92{ 106{
93 pgd_t *pgd; 107 pgd_t *pgd;
94 108
109 if (current->active_mm == mm)
110 __tlb_flush_mm(mm);
95 while (mm->context.asce_limit > limit) { 111 while (mm->context.asce_limit > limit) {
96 pgd = mm->pgd; 112 pgd = mm->pgd;
97 switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) { 113 switch (pgd_val(*pgd) & _REGION_ENTRY_TYPE_MASK) {
@@ -114,6 +130,8 @@ void crst_table_downgrade(struct mm_struct *mm, unsigned long limit)
114 mm->task_size = mm->context.asce_limit; 130 mm->task_size = mm->context.asce_limit;
115 crst_table_free(mm, (unsigned long *) pgd); 131 crst_table_free(mm, (unsigned long *) pgd);
116 } 132 }
133 if (current->active_mm == mm)
134 update_mm(mm, current);
117} 135}
118#endif 136#endif
119 137