OFFSET(PACA_CANARY, paca_struct, canary);
 #endif
 #endif
-       OFFSET(MMCONTEXTID, mm_struct, context.id);
 #ifdef CONFIG_PPC32
 #ifdef CONFIG_PPC_RTAS
        OFFSET(RTAS_SP, thread_struct, rtas_sp);
 #endif
 #endif
 
-#ifndef CONFIG_PPC64
-       OFFSET(MM_PGD, mm_struct, pgd);
-#endif /* ! CONFIG_PPC64 */
-
        /* About the CPU features table */
        OFFSET(CPU_SPEC_FEATURES, cpu_spec, cpu_features);
        OFFSET(CPU_SPEC_SETUP, cpu_spec, cpu_setup);
 
        mtspr   SPRN_SRR1,r4
        rfi
 
-/*
- * void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next);
- *
- * Set up the segment registers for a new context.
- */
-_ENTRY(switch_mmu_context)
-       lwz     r3,MMCONTEXTID(r4)
-       cmpwi   cr0,r3,0
-       blt-    4f
-       mulli   r3,r3,897       /* multiply context by skew factor */
-       rlwinm  r3,r3,4,8,27    /* VSID = (context & 0xfffff) << 4 */
-#ifdef CONFIG_PPC_KUEP
-       oris    r3, r3, SR_NX@h /* Set Nx */
-#endif
-#ifdef CONFIG_PPC_KUAP
-       oris    r3, r3, SR_KS@h /* Set Ks */
-#endif
-       li      r0,NUM_USER_SEGMENTS
-       mtctr   r0
-
-#ifdef CONFIG_BDI_SWITCH
-       /* Context switch the PTE pointer for the Abatron BDI2000.
-        * The PGDIR is passed as second argument.
-        */
-       lwz     r4, MM_PGD(r4)
-       lis     r5, abatron_pteptrs@ha
-       stw     r4, abatron_pteptrs@l + 0x4(r5)
-#endif
-BEGIN_MMU_FTR_SECTION
-#ifndef CONFIG_BDI_SWITCH
-       lwz     r4, MM_PGD(r4)
-#endif
-       tophys(r4, r4)
-       rlwinm  r4, r4, 4, 0xffff01ff
-       mtspr   SPRN_SDR1, r4
-END_MMU_FTR_SECTION_IFCLR(MMU_FTR_HPTE_TABLE)
-       li      r4,0
-       isync
-3:
-       mtsrin  r3,r4
-       addi    r3,r3,0x111     /* next VSID */
-       rlwinm  r3,r3,0,8,3     /* clear out any overflow from VSID field */
-       addis   r4,r4,0x1000    /* address of next segment */
-       bdnz    3b
-       sync
-       isync
-       blr
-4:     trap
-       EMIT_BUG_ENTRY 4b,__FILE__,__LINE__,0
-       blr
-EXPORT_SYMBOL(switch_mmu_context)
-
 /*
  * An undocumented "feature" of 604e requires that the v bit
  * be cleared before changing BAT values.
        .globl  swapper_pg_dir
 swapper_pg_dir:
        .space  PGD_TABLE_SIZE
-
-/* Room for two PTE pointers, usually the kernel and current user pointers
- * to their respective root page table.
- */
-abatron_pteptrs:
-       .space  8
 
 
 #include <asm/mmu_context.h>
 
+/*
+ * Room for two PTE pointers, usually the kernel and current user pointers
+ * to their respective root page table.
+ */
+void *abatron_pteptrs[2];
+
 /*
  * On 32-bit PowerPC 6xx/7xx/7xxx CPUs, we use a set of 16 VSIDs
  * (virtual segment identifiers) for each context.  Although the
        context_map[0] = (1 << FIRST_CONTEXT) - 1;
        next_mmu_context = FIRST_CONTEXT;
 }
+
+void switch_mmu_context(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk)
+{
+       long id = next->context.id;
+       unsigned long val;
+
+       if (id < 0)
+               panic("mm_struct %p has no context ID", next);
+
+       isync();
+
+       val = CTX_TO_VSID(id, 0);
+       if (!kuep_is_disabled())
+               val |= SR_NX;
+       if (!kuap_is_disabled())
+               val |= SR_KS;
+
+       update_user_segments(val);
+
+       if (IS_ENABLED(CONFIG_BDI_SWITCH))
+               abatron_pteptrs[1] = next->pgd;
+
+       if (!mmu_has_feature(MMU_FTR_HPTE_TABLE))
+               mtspr(SPRN_SDR1, rol32(__pa(next->pgd), 4) & 0xffff01ff);
+
+       mb();   /* sync */
+       isync();
+}
+EXPORT_SYMBOL(switch_mmu_context);