aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/s390/include/asm/mmu_context.h16
-rw-r--r--arch/s390/include/asm/pgalloc.h24
-rw-r--r--arch/s390/kernel/head64.S2
-rw-r--r--drivers/s390/block/dasd_diag.c9
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 @@
15static inline int init_new_context(struct task_struct *tsk, 15static 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,
111static inline void arch_dup_mmap(struct mm_struct *oldmm, 119static 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
118static inline void arch_exit_mmap(struct mm_struct *mm) 124static 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
101static inline pgd_t *pgd_alloc(struct mm_struct *mm) 101static 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
117static 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
110static inline void pmd_populate(struct mm_struct *mm, 124static 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
18ENTRY(startup_continue) 18ENTRY(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. */
70static inline int dia250(void *iob, int cmd) 70static 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
93static 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