diff options
| -rw-r--r-- | arch/s390/include/asm/processor.h | 2 | ||||
| -rw-r--r-- | arch/s390/kernel/entry.h | 1 | ||||
| -rw-r--r-- | arch/s390/kernel/pgm_check.S | 2 | ||||
| -rw-r--r-- | arch/s390/mm/fault.c | 37 | ||||
| -rw-r--r-- | arch/s390/mm/mmap.c | 12 | ||||
| -rw-r--r-- | arch/s390/mm/pgtable.c | 18 |
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 | ||
| 24 | void do_protection_exception(struct pt_regs *regs); | 24 | void do_protection_exception(struct pt_regs *regs); |
| 25 | void do_dat_exception(struct pt_regs *regs); | 25 | void do_dat_exception(struct pt_regs *regs); |
| 26 | void do_asce_exception(struct pt_regs *regs); | ||
| 27 | 26 | ||
| 28 | void addressing_exception(struct pt_regs *regs); | 27 | void addressing_exception(struct pt_regs *regs); |
| 29 | void data_exception(struct pt_regs *regs); | 28 | void 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 */ | |||
| 78 | PGM_CHECK_DEFAULT /* 35 */ | 78 | PGM_CHECK_DEFAULT /* 35 */ |
| 79 | PGM_CHECK_DEFAULT /* 36 */ | 79 | PGM_CHECK_DEFAULT /* 36 */ |
| 80 | PGM_CHECK_DEFAULT /* 37 */ | 80 | PGM_CHECK_DEFAULT /* 37 */ |
| 81 | PGM_CHECK_64BIT(do_asce_exception) /* 38 */ | 81 | PGM_CHECK_DEFAULT /* 38 */ |
| 82 | PGM_CHECK_64BIT(do_dat_exception) /* 39 */ | 82 | PGM_CHECK_64BIT(do_dat_exception) /* 39 */ |
| 83 | PGM_CHECK_64BIT(do_dat_exception) /* 3a */ | 83 | PGM_CHECK_64BIT(do_dat_exception) /* 3a */ |
| 84 | PGM_CHECK_64BIT(do_dat_exception) /* 3b */ | 84 | PGM_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 | ||
| 427 | void __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 | |||
| 458 | no_context: | ||
| 459 | do_no_context(regs); | ||
| 460 | } | ||
| 461 | #endif | ||
| 462 | |||
| 463 | int __handle_fault(unsigned long uaddr, unsigned long pgm_int_code, int write) | 426 | int __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 | ||
| 102 | int s390_mmap_check(unsigned long addr, unsigned long len, unsigned long flags) | 102 | int 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 |
| 51 | static 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 | |||
| 51 | int crst_table_upgrade(struct mm_struct *mm, unsigned long limit) | 60 | int 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; | ||
| 57 | repeat: | 68 | repeat: |
| 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 | ||
