Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/s390/linux
[sfrench/cifs-2.6.git] / arch / s390 / include / asm / mmu_context.h
index 43607bb12cc2b303e7e9f87d391f053ad0aae2d2..f4a07f788f78b3160f9ae312e699805b47f67ebe 100644 (file)
@@ -44,6 +44,8 @@ static inline int init_new_context(struct task_struct *tsk,
                mm->context.asce_limit = STACK_TOP_MAX;
                mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
                                   _ASCE_USER_BITS | _ASCE_TYPE_REGION3;
+               /* pgd_alloc() did not account this pud */
+               mm_inc_nr_puds(mm);
                break;
        case -PAGE_SIZE:
                /* forked 5-level task, set new asce with new_mm->pgd */
@@ -59,7 +61,7 @@ static inline int init_new_context(struct task_struct *tsk,
                /* forked 2-level compat task, set new asce with new mm->pgd */
                mm->context.asce = __pa(mm->pgd) | _ASCE_TABLE_LENGTH |
                                   _ASCE_USER_BITS | _ASCE_TYPE_SEGMENT;
-               /* pgd_alloc() did not increase mm->nr_pmds */
+               /* pgd_alloc() did not account this pmd */
                mm_inc_nr_pmds(mm);
        }
        crst_table_init((unsigned long *) mm->pgd, pgd_entry_type(mm));
@@ -71,41 +73,38 @@ static inline int init_new_context(struct task_struct *tsk,
 static inline void set_user_asce(struct mm_struct *mm)
 {
        S390_lowcore.user_asce = mm->context.asce;
-       if (current->thread.mm_segment.ar4)
-               __ctl_load(S390_lowcore.user_asce, 7, 7);
-       set_cpu_flag(CIF_ASCE_PRIMARY);
+       __ctl_load(S390_lowcore.user_asce, 1, 1);
+       clear_cpu_flag(CIF_ASCE_PRIMARY);
 }
 
 static inline void clear_user_asce(void)
 {
        S390_lowcore.user_asce = S390_lowcore.kernel_asce;
-
-       __ctl_load(S390_lowcore.user_asce, 1, 1);
-       __ctl_load(S390_lowcore.user_asce, 7, 7);
-}
-
-static inline void load_kernel_asce(void)
-{
-       unsigned long asce;
-
-       __ctl_store(asce, 1, 1);
-       if (asce != S390_lowcore.kernel_asce)
-               __ctl_load(S390_lowcore.kernel_asce, 1, 1);
+       __ctl_load(S390_lowcore.kernel_asce, 1, 1);
        set_cpu_flag(CIF_ASCE_PRIMARY);
 }
 
+mm_segment_t enable_sacf_uaccess(void);
+void disable_sacf_uaccess(mm_segment_t old_fs);
+
 static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                             struct task_struct *tsk)
 {
        int cpu = smp_processor_id();
 
-       S390_lowcore.user_asce = next->context.asce;
        if (prev == next)
                return;
+       S390_lowcore.user_asce = next->context.asce;
        cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
-       /* Clear old ASCE by loading the kernel ASCE. */
-       __ctl_load(S390_lowcore.kernel_asce, 1, 1);
-       __ctl_load(S390_lowcore.kernel_asce, 7, 7);
+       /* Clear previous user-ASCE from CR1 and CR7 */
+       if (!test_cpu_flag(CIF_ASCE_PRIMARY)) {
+               __ctl_load(S390_lowcore.kernel_asce, 1, 1);
+               set_cpu_flag(CIF_ASCE_PRIMARY);
+       }
+       if (test_cpu_flag(CIF_ASCE_SECONDARY)) {
+               __ctl_load(S390_lowcore.vdso_asce, 7, 7);
+               clear_cpu_flag(CIF_ASCE_SECONDARY);
+       }
        cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
 }
 
@@ -115,7 +114,6 @@ static inline void finish_arch_post_lock_switch(void)
        struct task_struct *tsk = current;
        struct mm_struct *mm = tsk->mm;
 
-       load_kernel_asce();
        if (mm) {
                preempt_disable();
                while (atomic_read(&mm->context.flush_count))