diff options
| -rw-r--r-- | arch/s390/include/asm/mmu_context.h | 16 | ||||
| -rw-r--r-- | arch/s390/include/asm/pgalloc.h | 24 | ||||
| -rw-r--r-- | arch/s390/kernel/head64.S | 2 | ||||
| -rw-r--r-- | drivers/s390/block/dasd_diag.c | 9 |
4 files changed, 38 insertions, 13 deletions
diff --git a/arch/s390/include/asm/mmu_context.h b/arch/s390/include/asm/mmu_context.h index fb1b93ea3e3f..e485817f7b1a 100644 --- a/arch/s390/include/asm/mmu_context.h +++ b/arch/s390/include/asm/mmu_context.h | |||
| @@ -15,17 +15,25 @@ | |||
| 15 | static inline int init_new_context(struct task_struct *tsk, | 15 | static inline int init_new_context(struct task_struct *tsk, |
| 16 | struct mm_struct *mm) | 16 | struct mm_struct *mm) |
| 17 | { | 17 | { |
| 18 | spin_lock_init(&mm->context.list_lock); | ||
| 19 | INIT_LIST_HEAD(&mm->context.pgtable_list); | ||
| 20 | INIT_LIST_HEAD(&mm->context.gmap_list); | ||
| 18 | cpumask_clear(&mm->context.cpu_attach_mask); | 21 | cpumask_clear(&mm->context.cpu_attach_mask); |
| 19 | atomic_set(&mm->context.attach_count, 0); | 22 | atomic_set(&mm->context.attach_count, 0); |
| 20 | mm->context.flush_mm = 0; | 23 | mm->context.flush_mm = 0; |
| 21 | mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS; | ||
| 22 | mm->context.asce_bits |= _ASCE_TYPE_REGION3; | ||
| 23 | #ifdef CONFIG_PGSTE | 24 | #ifdef CONFIG_PGSTE |
| 24 | mm->context.alloc_pgste = page_table_allocate_pgste; | 25 | mm->context.alloc_pgste = page_table_allocate_pgste; |
| 25 | mm->context.has_pgste = 0; | 26 | mm->context.has_pgste = 0; |
| 26 | mm->context.use_skey = 0; | 27 | mm->context.use_skey = 0; |
| 27 | #endif | 28 | #endif |
| 28 | mm->context.asce_limit = STACK_TOP_MAX; | 29 | if (mm->context.asce_limit == 0) { |
| 30 | /* context created by exec, set asce limit to 4TB */ | ||
| 31 | mm->context.asce_bits = _ASCE_TABLE_LENGTH | | ||
| 32 | _ASCE_USER_BITS | _ASCE_TYPE_REGION3; | ||
| 33 | mm->context.asce_limit = STACK_TOP_MAX; | ||
| 34 | } else if (mm->context.asce_limit == (1UL << 31)) { | ||
| 35 | mm_inc_nr_pmds(mm); | ||
| 36 | } | ||
| 29 | crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); | 37 | crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); |
| 30 | return 0; | 38 | return 0; |
| 31 | } | 39 | } |
| @@ -111,8 +119,6 @@ static inline void activate_mm(struct mm_struct *prev, | |||
| 111 | static inline void arch_dup_mmap(struct mm_struct *oldmm, | 119 | static inline void arch_dup_mmap(struct mm_struct *oldmm, |
| 112 | struct mm_struct *mm) | 120 | struct mm_struct *mm) |
| 113 | { | 121 | { |
| 114 | if (oldmm->context.asce_limit < mm->context.asce_limit) | ||
| 115 | crst_table_downgrade(mm, oldmm->context.asce_limit); | ||
| 116 | } | 122 | } |
| 117 | 123 | ||
| 118 | static inline void arch_exit_mmap(struct mm_struct *mm) | 124 | static inline void arch_exit_mmap(struct mm_struct *mm) |
diff --git a/arch/s390/include/asm/pgalloc.h b/arch/s390/include/asm/pgalloc.h index 7b7858f158b4..d7cc79fb6191 100644 --- a/arch/s390/include/asm/pgalloc.h +++ b/arch/s390/include/asm/pgalloc.h | |||
| @@ -100,12 +100,26 @@ static inline void pud_populate(struct mm_struct *mm, pud_t *pud, pmd_t *pmd) | |||
| 100 | 100 | ||
| 101 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) | 101 | static inline pgd_t *pgd_alloc(struct mm_struct *mm) |
| 102 | { | 102 | { |
| 103 | spin_lock_init(&mm->context.list_lock); | 103 | unsigned long *table = crst_table_alloc(mm); |
| 104 | INIT_LIST_HEAD(&mm->context.pgtable_list); | 104 | |
| 105 | INIT_LIST_HEAD(&mm->context.gmap_list); | 105 | if (!table) |
| 106 | return (pgd_t *) crst_table_alloc(mm); | 106 | return NULL; |
| 107 | if (mm->context.asce_limit == (1UL << 31)) { | ||
| 108 | /* Forking a compat process with 2 page table levels */ | ||
| 109 | if (!pgtable_pmd_page_ctor(virt_to_page(table))) { | ||
| 110 | crst_table_free(mm, table); | ||
| 111 | return NULL; | ||
| 112 | } | ||
| 113 | } | ||
| 114 | return (pgd_t *) table; | ||
| 115 | } | ||
| 116 | |||
| 117 | static inline void pgd_free(struct mm_struct *mm, pgd_t *pgd) | ||
| 118 | { | ||
| 119 | if (mm->context.asce_limit == (1UL << 31)) | ||
| 120 | pgtable_pmd_page_dtor(virt_to_page(pgd)); | ||
| 121 | crst_table_free(mm, (unsigned long *) pgd); | ||
| 107 | } | 122 | } |
| 108 | #define pgd_free(mm, pgd) crst_table_free(mm, (unsigned long *) pgd) | ||
| 109 | 123 | ||
| 110 | static inline void pmd_populate(struct mm_struct *mm, | 124 | static inline void pmd_populate(struct mm_struct *mm, |
| 111 | pmd_t *pmd, pgtable_t pte) | 125 | pmd_t *pmd, pgtable_t pte) |
diff --git a/arch/s390/kernel/head64.S b/arch/s390/kernel/head64.S index c5febe84eba6..03c2b469c472 100644 --- a/arch/s390/kernel/head64.S +++ b/arch/s390/kernel/head64.S | |||
| @@ -16,7 +16,7 @@ | |||
| 16 | 16 | ||
| 17 | __HEAD | 17 | __HEAD |
| 18 | ENTRY(startup_continue) | 18 | ENTRY(startup_continue) |
| 19 | tm __LC_STFLE_FAC_LIST+6,0x80 # LPP available ? | 19 | tm __LC_STFLE_FAC_LIST+5,0x80 # LPP available ? |
| 20 | jz 0f | 20 | jz 0f |
| 21 | xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid | 21 | xc __LC_LPP+1(7,0),__LC_LPP+1 # clear lpp and current_pid |
| 22 | mvi __LC_LPP,0x80 # and set LPP_MAGIC | 22 | mvi __LC_LPP,0x80 # and set LPP_MAGIC |
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c index cb61f300f8b5..277b5c8c825c 100644 --- a/drivers/s390/block/dasd_diag.c +++ b/drivers/s390/block/dasd_diag.c | |||
| @@ -67,7 +67,7 @@ static const u8 DASD_DIAG_CMS1[] = { 0xc3, 0xd4, 0xe2, 0xf1 };/* EBCDIC CMS1 */ | |||
| 67 | * and function code cmd. | 67 | * and function code cmd. |
| 68 | * In case of an exception return 3. Otherwise return result of bitwise OR of | 68 | * In case of an exception return 3. Otherwise return result of bitwise OR of |
| 69 | * resulting condition code and DIAG return code. */ | 69 | * resulting condition code and DIAG return code. */ |
| 70 | static inline int dia250(void *iob, int cmd) | 70 | static inline int __dia250(void *iob, int cmd) |
| 71 | { | 71 | { |
| 72 | register unsigned long reg2 asm ("2") = (unsigned long) iob; | 72 | register unsigned long reg2 asm ("2") = (unsigned long) iob; |
| 73 | typedef union { | 73 | typedef union { |
| @@ -77,7 +77,6 @@ static inline int dia250(void *iob, int cmd) | |||
| 77 | int rc; | 77 | int rc; |
| 78 | 78 | ||
| 79 | rc = 3; | 79 | rc = 3; |
| 80 | diag_stat_inc(DIAG_STAT_X250); | ||
| 81 | asm volatile( | 80 | asm volatile( |
| 82 | " diag 2,%2,0x250\n" | 81 | " diag 2,%2,0x250\n" |
| 83 | "0: ipm %0\n" | 82 | "0: ipm %0\n" |
| @@ -91,6 +90,12 @@ static inline int dia250(void *iob, int cmd) | |||
| 91 | return rc; | 90 | return rc; |
| 92 | } | 91 | } |
| 93 | 92 | ||
| 93 | static inline int dia250(void *iob, int cmd) | ||
| 94 | { | ||
| 95 | diag_stat_inc(DIAG_STAT_X250); | ||
| 96 | return __dia250(iob, cmd); | ||
| 97 | } | ||
| 98 | |||
| 94 | /* Initialize block I/O to DIAG device using the specified blocksize and | 99 | /* Initialize block I/O to DIAG device using the specified blocksize and |
| 95 | * block offset. On success, return zero and set end_block to contain the | 100 | * block offset. On success, return zero and set end_block to contain the |
| 96 | * number of blocks on the device minus the specified offset. Return non-zero | 101 | * number of blocks on the device minus the specified offset. Return non-zero |
