1c6557e7fSMartin Schwidefsky /* 2c6557e7fSMartin Schwidefsky * S390 version 3c6557e7fSMartin Schwidefsky * 4c6557e7fSMartin Schwidefsky * Derived from "include/asm-i386/mmu_context.h" 5c6557e7fSMartin Schwidefsky */ 6c6557e7fSMartin Schwidefsky 7c6557e7fSMartin Schwidefsky #ifndef __S390_MMU_CONTEXT_H 8c6557e7fSMartin Schwidefsky #define __S390_MMU_CONTEXT_H 9c6557e7fSMartin Schwidefsky 10c6557e7fSMartin Schwidefsky #include <asm/pgalloc.h> 11c6557e7fSMartin Schwidefsky #include <asm/uaccess.h> 12050eef36SMartin Schwidefsky #include <asm/tlbflush.h> 13a0616cdeSDavid Howells #include <asm/ctl_reg.h> 14c6557e7fSMartin Schwidefsky 15c6557e7fSMartin Schwidefsky static inline int init_new_context(struct task_struct *tsk, 16c6557e7fSMartin Schwidefsky struct mm_struct *mm) 17c6557e7fSMartin Schwidefsky { 181b948d6cSMartin Schwidefsky cpumask_clear(&mm->context.cpu_attach_mask); 19050eef36SMartin Schwidefsky atomic_set(&mm->context.attach_count, 0); 20050eef36SMartin Schwidefsky mm->context.flush_mm = 0; 21c6557e7fSMartin Schwidefsky mm->context.asce_bits = _ASCE_TABLE_LENGTH | _ASCE_USER_BITS; 22c6557e7fSMartin Schwidefsky mm->context.asce_bits |= _ASCE_TYPE_REGION3; 23*0b46e0a3SMartin Schwidefsky #ifdef CONFIG_PGSTE 24*0b46e0a3SMartin Schwidefsky mm->context.alloc_pgste = page_table_allocate_pgste; 25250cf776SChristian Borntraeger mm->context.has_pgste = 0; 26693ffc08SDominik Dingel mm->context.use_skey = 0; 27*0b46e0a3SMartin Schwidefsky #endif 28c6557e7fSMartin Schwidefsky mm->context.asce_limit = STACK_TOP_MAX; 29c6557e7fSMartin Schwidefsky crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); 30c6557e7fSMartin Schwidefsky return 0; 31c6557e7fSMartin Schwidefsky } 32c6557e7fSMartin Schwidefsky 33c6557e7fSMartin Schwidefsky #define destroy_context(mm) do { } while (0) 34c6557e7fSMartin Schwidefsky 35beef560bSMartin Schwidefsky static inline void set_user_asce(struct mm_struct *mm) 36c6557e7fSMartin Schwidefsky { 37f8b13505SMartin Schwidefsky S390_lowcore.user_asce = mm->context.asce_bits | __pa(mm->pgd); 38f8b13505SMartin Schwidefsky if (current->thread.mm_segment.ar4) 39f8b13505SMartin Schwidefsky __ctl_load(S390_lowcore.user_asce, 7, 7); 40d3a73acbSMartin Schwidefsky set_cpu_flag(CIF_ASCE); 41c6557e7fSMartin Schwidefsky } 42c6557e7fSMartin Schwidefsky 43beef560bSMartin Schwidefsky static inline void clear_user_asce(void) 4402a8f3abSMartin Schwidefsky { 4502a8f3abSMartin Schwidefsky S390_lowcore.user_asce = S390_lowcore.kernel_asce; 46457f2180SHeiko Carstens 47457f2180SHeiko Carstens __ctl_load(S390_lowcore.user_asce, 1, 1); 48457f2180SHeiko Carstens __ctl_load(S390_lowcore.user_asce, 7, 7); 49457f2180SHeiko Carstens } 50457f2180SHeiko Carstens 51beef560bSMartin Schwidefsky static inline void load_kernel_asce(void) 52457f2180SHeiko Carstens { 53457f2180SHeiko Carstens unsigned long asce; 54457f2180SHeiko Carstens 55457f2180SHeiko Carstens __ctl_store(asce, 1, 1); 56457f2180SHeiko Carstens if (asce != S390_lowcore.kernel_asce) 57457f2180SHeiko Carstens __ctl_load(S390_lowcore.kernel_asce, 1, 1); 58d3a73acbSMartin Schwidefsky set_cpu_flag(CIF_ASCE); 5902a8f3abSMartin Schwidefsky } 6002a8f3abSMartin Schwidefsky 61c6557e7fSMartin Schwidefsky static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 62c6557e7fSMartin Schwidefsky struct task_struct *tsk) 63c6557e7fSMartin Schwidefsky { 6453e857f3SMartin Schwidefsky int cpu = smp_processor_id(); 6553e857f3SMartin Schwidefsky 66691d5264SMartin Schwidefsky S390_lowcore.user_asce = next->context.asce_bits | __pa(next->pgd); 6753e857f3SMartin Schwidefsky if (prev == next) 6853e857f3SMartin Schwidefsky return; 691b948d6cSMartin Schwidefsky if (MACHINE_HAS_TLB_LC) 701b948d6cSMartin Schwidefsky cpumask_set_cpu(cpu, &next->context.cpu_attach_mask); 7102a8f3abSMartin Schwidefsky /* Clear old ASCE by loading the kernel ASCE. */ 72beef560bSMartin Schwidefsky __ctl_load(S390_lowcore.kernel_asce, 1, 1); 73beef560bSMartin Schwidefsky __ctl_load(S390_lowcore.kernel_asce, 7, 7); 74beef560bSMartin Schwidefsky atomic_inc(&next->context.attach_count); 75050eef36SMartin Schwidefsky atomic_dec(&prev->context.attach_count); 761b948d6cSMartin Schwidefsky if (MACHINE_HAS_TLB_LC) 771b948d6cSMartin Schwidefsky cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask); 7853e857f3SMartin Schwidefsky } 7953e857f3SMartin Schwidefsky 8053e857f3SMartin Schwidefsky #define finish_arch_post_lock_switch finish_arch_post_lock_switch 8153e857f3SMartin Schwidefsky static inline void finish_arch_post_lock_switch(void) 8253e857f3SMartin Schwidefsky { 8353e857f3SMartin Schwidefsky struct task_struct *tsk = current; 8453e857f3SMartin Schwidefsky struct mm_struct *mm = tsk->mm; 8553e857f3SMartin Schwidefsky 86f8b13505SMartin Schwidefsky load_kernel_asce(); 87f8b13505SMartin Schwidefsky if (mm) { 8853e857f3SMartin Schwidefsky preempt_disable(); 8953e857f3SMartin Schwidefsky while (atomic_read(&mm->context.attach_count) >> 16) 9053e857f3SMartin Schwidefsky cpu_relax(); 9153e857f3SMartin Schwidefsky 9253e857f3SMartin Schwidefsky cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); 9353e857f3SMartin Schwidefsky if (mm->context.flush_mm) 9453e857f3SMartin Schwidefsky __tlb_flush_mm(mm); 9553e857f3SMartin Schwidefsky preempt_enable(); 96c6557e7fSMartin Schwidefsky } 97f8b13505SMartin Schwidefsky set_fs(current->thread.mm_segment); 98f8b13505SMartin Schwidefsky } 99c6557e7fSMartin Schwidefsky 100c6557e7fSMartin Schwidefsky #define enter_lazy_tlb(mm,tsk) do { } while (0) 101c6557e7fSMartin Schwidefsky #define deactivate_mm(tsk,mm) do { } while (0) 102c6557e7fSMartin Schwidefsky 103c6557e7fSMartin Schwidefsky static inline void activate_mm(struct mm_struct *prev, 104c6557e7fSMartin Schwidefsky struct mm_struct *next) 105c6557e7fSMartin Schwidefsky { 106c6557e7fSMartin Schwidefsky switch_mm(prev, next, current); 107beef560bSMartin Schwidefsky cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); 108beef560bSMartin Schwidefsky set_user_asce(next); 109c6557e7fSMartin Schwidefsky } 110c6557e7fSMartin Schwidefsky 1110f6f281bSMartin Schwidefsky static inline void arch_dup_mmap(struct mm_struct *oldmm, 1120f6f281bSMartin Schwidefsky struct mm_struct *mm) 1130f6f281bSMartin Schwidefsky { 1140f6f281bSMartin Schwidefsky if (oldmm->context.asce_limit < mm->context.asce_limit) 1150f6f281bSMartin Schwidefsky crst_table_downgrade(mm, oldmm->context.asce_limit); 1160f6f281bSMartin Schwidefsky } 1170f6f281bSMartin Schwidefsky 1180f6f281bSMartin Schwidefsky static inline void arch_exit_mmap(struct mm_struct *mm) 1190f6f281bSMartin Schwidefsky { 1200f6f281bSMartin Schwidefsky } 1210f6f281bSMartin Schwidefsky 12262e88b1cSDave Hansen static inline void arch_unmap(struct mm_struct *mm, 12362e88b1cSDave Hansen struct vm_area_struct *vma, 12462e88b1cSDave Hansen unsigned long start, unsigned long end) 12562e88b1cSDave Hansen { 12662e88b1cSDave Hansen } 12762e88b1cSDave Hansen 12862e88b1cSDave Hansen static inline void arch_bprm_mm_init(struct mm_struct *mm, 12962e88b1cSDave Hansen struct vm_area_struct *vma) 13062e88b1cSDave Hansen { 13162e88b1cSDave Hansen } 13262e88b1cSDave Hansen 133c6557e7fSMartin Schwidefsky #endif /* __S390_MMU_CONTEXT_H */ 134