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 #ifdef CONFIG_64BIT 23c6557e7fSMartin Schwidefsky mm->context.asce_bits |= _ASCE_TYPE_REGION3; 24c6557e7fSMartin Schwidefsky #endif 25250cf776SChristian Borntraeger mm->context.has_pgste = 0; 26693ffc08SDominik Dingel mm->context.use_skey = 0; 27c6557e7fSMartin Schwidefsky mm->context.asce_limit = STACK_TOP_MAX; 28c6557e7fSMartin Schwidefsky crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm)); 29c6557e7fSMartin Schwidefsky return 0; 30c6557e7fSMartin Schwidefsky } 31c6557e7fSMartin Schwidefsky 32c6557e7fSMartin Schwidefsky #define destroy_context(mm) do { } while (0) 33c6557e7fSMartin Schwidefsky 34beef560bSMartin Schwidefsky static inline void set_user_asce(struct mm_struct *mm) 35c6557e7fSMartin Schwidefsky { 36f8b13505SMartin Schwidefsky S390_lowcore.user_asce = mm->context.asce_bits | __pa(mm->pgd); 37f8b13505SMartin Schwidefsky if (current->thread.mm_segment.ar4) 38f8b13505SMartin Schwidefsky __ctl_load(S390_lowcore.user_asce, 7, 7); 39d3a73acbSMartin Schwidefsky set_cpu_flag(CIF_ASCE); 40c6557e7fSMartin Schwidefsky } 41c6557e7fSMartin Schwidefsky 42beef560bSMartin Schwidefsky static inline void clear_user_asce(void) 4302a8f3abSMartin Schwidefsky { 4402a8f3abSMartin Schwidefsky S390_lowcore.user_asce = S390_lowcore.kernel_asce; 45457f2180SHeiko Carstens 46457f2180SHeiko Carstens __ctl_load(S390_lowcore.user_asce, 1, 1); 47457f2180SHeiko Carstens __ctl_load(S390_lowcore.user_asce, 7, 7); 48457f2180SHeiko Carstens } 49457f2180SHeiko Carstens 50beef560bSMartin Schwidefsky static inline void load_kernel_asce(void) 51457f2180SHeiko Carstens { 52457f2180SHeiko Carstens unsigned long asce; 53457f2180SHeiko Carstens 54457f2180SHeiko Carstens __ctl_store(asce, 1, 1); 55457f2180SHeiko Carstens if (asce != S390_lowcore.kernel_asce) 56457f2180SHeiko Carstens __ctl_load(S390_lowcore.kernel_asce, 1, 1); 57d3a73acbSMartin Schwidefsky set_cpu_flag(CIF_ASCE); 5802a8f3abSMartin Schwidefsky } 5902a8f3abSMartin Schwidefsky 60c6557e7fSMartin Schwidefsky static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, 61c6557e7fSMartin Schwidefsky struct task_struct *tsk) 62c6557e7fSMartin Schwidefsky { 6353e857f3SMartin Schwidefsky int cpu = smp_processor_id(); 6453e857f3SMartin Schwidefsky 6553e857f3SMartin Schwidefsky if (prev == next) 6653e857f3SMartin Schwidefsky return; 671b948d6cSMartin Schwidefsky if (MACHINE_HAS_TLB_LC) 681b948d6cSMartin Schwidefsky cpumask_set_cpu(cpu, &next->context.cpu_attach_mask); 6902a8f3abSMartin Schwidefsky /* Clear old ASCE by loading the kernel ASCE. */ 70beef560bSMartin Schwidefsky __ctl_load(S390_lowcore.kernel_asce, 1, 1); 71beef560bSMartin Schwidefsky __ctl_load(S390_lowcore.kernel_asce, 7, 7); 72beef560bSMartin Schwidefsky atomic_inc(&next->context.attach_count); 73050eef36SMartin Schwidefsky atomic_dec(&prev->context.attach_count); 741b948d6cSMartin Schwidefsky if (MACHINE_HAS_TLB_LC) 751b948d6cSMartin Schwidefsky cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask); 76f8b13505SMartin Schwidefsky S390_lowcore.user_asce = next->context.asce_bits | __pa(next->pgd); 7753e857f3SMartin Schwidefsky } 7853e857f3SMartin Schwidefsky 7953e857f3SMartin Schwidefsky #define finish_arch_post_lock_switch finish_arch_post_lock_switch 8053e857f3SMartin Schwidefsky static inline void finish_arch_post_lock_switch(void) 8153e857f3SMartin Schwidefsky { 8253e857f3SMartin Schwidefsky struct task_struct *tsk = current; 8353e857f3SMartin Schwidefsky struct mm_struct *mm = tsk->mm; 8453e857f3SMartin Schwidefsky 85f8b13505SMartin Schwidefsky load_kernel_asce(); 86f8b13505SMartin Schwidefsky if (mm) { 8753e857f3SMartin Schwidefsky preempt_disable(); 8853e857f3SMartin Schwidefsky while (atomic_read(&mm->context.attach_count) >> 16) 8953e857f3SMartin Schwidefsky cpu_relax(); 9053e857f3SMartin Schwidefsky 9153e857f3SMartin Schwidefsky cpumask_set_cpu(smp_processor_id(), mm_cpumask(mm)); 9253e857f3SMartin Schwidefsky if (mm->context.flush_mm) 9353e857f3SMartin Schwidefsky __tlb_flush_mm(mm); 9453e857f3SMartin Schwidefsky preempt_enable(); 95c6557e7fSMartin Schwidefsky } 96f8b13505SMartin Schwidefsky set_fs(current->thread.mm_segment); 97f8b13505SMartin Schwidefsky } 98c6557e7fSMartin Schwidefsky 99c6557e7fSMartin Schwidefsky #define enter_lazy_tlb(mm,tsk) do { } while (0) 100c6557e7fSMartin Schwidefsky #define deactivate_mm(tsk,mm) do { } while (0) 101c6557e7fSMartin Schwidefsky 102c6557e7fSMartin Schwidefsky static inline void activate_mm(struct mm_struct *prev, 103c6557e7fSMartin Schwidefsky struct mm_struct *next) 104c6557e7fSMartin Schwidefsky { 105c6557e7fSMartin Schwidefsky switch_mm(prev, next, current); 106beef560bSMartin Schwidefsky cpumask_set_cpu(smp_processor_id(), mm_cpumask(next)); 107beef560bSMartin Schwidefsky set_user_asce(next); 108c6557e7fSMartin Schwidefsky } 109c6557e7fSMartin Schwidefsky 1100f6f281bSMartin Schwidefsky static inline void arch_dup_mmap(struct mm_struct *oldmm, 1110f6f281bSMartin Schwidefsky struct mm_struct *mm) 1120f6f281bSMartin Schwidefsky { 1130f6f281bSMartin Schwidefsky #ifdef CONFIG_64BIT 1140f6f281bSMartin Schwidefsky if (oldmm->context.asce_limit < mm->context.asce_limit) 1150f6f281bSMartin Schwidefsky crst_table_downgrade(mm, oldmm->context.asce_limit); 1160f6f281bSMartin Schwidefsky #endif 1170f6f281bSMartin Schwidefsky } 1180f6f281bSMartin Schwidefsky 1190f6f281bSMartin Schwidefsky static inline void arch_exit_mmap(struct mm_struct *mm) 1200f6f281bSMartin Schwidefsky { 1210f6f281bSMartin Schwidefsky } 1220f6f281bSMartin Schwidefsky 123*62e88b1cSDave Hansen static inline void arch_unmap(struct mm_struct *mm, 124*62e88b1cSDave Hansen struct vm_area_struct *vma, 125*62e88b1cSDave Hansen unsigned long start, unsigned long end) 126*62e88b1cSDave Hansen { 127*62e88b1cSDave Hansen } 128*62e88b1cSDave Hansen 129*62e88b1cSDave Hansen static inline void arch_bprm_mm_init(struct mm_struct *mm, 130*62e88b1cSDave Hansen struct vm_area_struct *vma) 131*62e88b1cSDave Hansen { 132*62e88b1cSDave Hansen } 133*62e88b1cSDave Hansen 134c6557e7fSMartin Schwidefsky #endif /* __S390_MMU_CONTEXT_H */ 135