--- /dev/null
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_POWERPC_BOOK3S_32_KUP_H
+#define _ASM_POWERPC_BOOK3S_32_KUP_H
+
+#include <asm/book3s/32/mmu-hash.h>
+
+#ifdef __ASSEMBLY__
+
+.macro kuep_update_sr  gpr1, gpr2              /* NEVER use r0 as gpr2 due to addis */
+101:   mtsrin  \gpr1, \gpr2
+       addi    \gpr1, \gpr1, 0x111             /* next VSID */
+       rlwinm  \gpr1, \gpr1, 0, 0xf0ffffff     /* clear VSID overflow */
+       addis   \gpr2, \gpr2, 0x1000            /* address of next segment */
+       bdnz    101b
+       isync
+.endm
+
+.macro kuep_lock       gpr1, gpr2
+#ifdef CONFIG_PPC_KUEP
+       li      \gpr1, NUM_USER_SEGMENTS
+       li      \gpr2, 0
+       mtctr   \gpr1
+       mfsrin  \gpr1, \gpr2
+       oris    \gpr1, \gpr1, SR_NX@h           /* set Nx */
+       kuep_update_sr \gpr1, \gpr2
+#endif
+.endm
+
+.macro kuep_unlock     gpr1, gpr2
+#ifdef CONFIG_PPC_KUEP
+       li      \gpr1, NUM_USER_SEGMENTS
+       li      \gpr2, 0
+       mtctr   \gpr1
+       mfsrin  \gpr1, \gpr2
+       rlwinm  \gpr1, \gpr1, 0, ~SR_NX         /* Clear Nx */
+       kuep_update_sr \gpr1, \gpr2
+#endif
+.endm
+
+#endif /* __ASSEMBLY__ */
+
+#endif /* _ASM_POWERPC_BOOK3S_32_KUP_H */
 
 #define PP_RWRW 2      /* Supervisor read/write, User read/write */
 #define PP_RXRX 3      /* Supervisor read,       User read */
 
+/* Values for Segment Registers */
+#define SR_NX  0x10000000      /* No Execute */
+
 #ifndef __ASSEMBLY__
 
 /*
 
 #ifdef CONFIG_PPC_8xx
 #include <asm/nohash/32/kup-8xx.h>
 #endif
+#ifdef CONFIG_PPC_BOOK3S_32
+#include <asm/book3s/32/kup.h>
+#endif
 
 #ifdef __ASSEMBLY__
 #ifndef CONFIG_PPC_KUAP
 
        andis.  r12,r12,DBCR0_IDM@h
 #endif
        ACCOUNT_CPU_USER_ENTRY(r2, r11, r12)
+#ifdef CONFIG_PPC_BOOK3S_32
+       kuep_lock r11, r12
+#endif
 #if defined(CONFIG_40x) || defined(CONFIG_BOOKE)
        beq+    3f
        /* From user and task is ptraced - load up global dbcr0 */
 END_FTR_SECTION_IFSET(CPU_FTR_NEED_PAIRED_STWCX)
        stwcx.  r0,0,r1                 /* to clear the reservation */
        ACCOUNT_CPU_USER_EXIT(r2, r5, r7)
+#ifdef CONFIG_PPC_BOOK3S_32
+       kuep_unlock r5, r7
+#endif
        kuap_check r2, r4
        lwz     r4,_LINK(r1)
        lwz     r5,_CCR(r1)
        bnel-   load_dbcr0
 #endif
        ACCOUNT_CPU_USER_EXIT(r2, r10, r11)
+#ifdef CONFIG_PPC_BOOK3S_32
+       kuep_unlock     r10, r11
+#endif
 
        b       restore
 
 
        tophys(r6,r6)
        lwz     r6,_SDR1@l(r6)
        mtspr   SPRN_SDR1,r6
-       li      r0,16           /* load up segment register values */
+       li      r0, NUM_USER_SEGMENTS   /* load up segment register values */
        mtctr   r0              /* for context 0 */
        lis     r3,0x2000       /* Ku = 1, VSID = 0 */
+#ifdef CONFIG_PPC_KUEP
+       oris    r3, r3, SR_NX@h /* Set Nx */
+#endif
        li      r4,0
 3:     mtsrin  r3,r4
        addi    r3,r3,0x111     /* increment VSID */
        addis   r4,r4,0x1000    /* address of next segment */
        bdnz    3b
+       li      r0, 16 - NUM_USER_SEGMENTS /* load up kernel segment registers */
+       mtctr   r0                      /* for context 0 */
+       rlwinm  r3, r3, 0, ~SR_NX       /* Nx = 0 */
+3:     mtsrin  r3, r4
+       addi    r3, r3, 0x111   /* increment VSID */
+       addis   r4, r4, 0x1000  /* address of next segment */
+       bdnz    3b
 
 /* Load the BAT registers with the values set up by MMU_init.
    MMU_init takes care of whether we're on a 601 or not. */
        mulli   r3,r3,897       /* multiply context by skew factor */
        rlwinm  r3,r3,4,8,27    /* VSID = (context & 0xfffff) << 4 */
        addis   r3,r3,0x6000    /* Set Ks, Ku bits */
+#ifdef CONFIG_PPC_KUEP
+       oris    r3, r3, SR_NX@h /* Set Nx */
+#endif
        li      r0,NUM_USER_SEGMENTS
        mtctr   r0
 
 
        else /* Anything else has 256M mapped */
                memblock_set_current_limit(min_t(u64, first_memblock_size, 0x10000000));
 }
+
+#ifdef CONFIG_PPC_KUEP
+void __init setup_kuep(bool disabled)
+{
+       pr_info("Activating Kernel Userspace Execution Prevention\n");
+
+       if (cpu_has_feature(CPU_FTR_601))
+               pr_warn("KUEP is not working on powerpc 601 (No NX bit in Seg Regs)\n");
+
+       if (disabled)
+               pr_warn("KUEP cannot be disabled yet on 6xx when compiled in\n");
+}
+#endif
 
        bool "512x/52xx/6xx/7xx/74xx/82xx/83xx/86xx"
        select PPC_FPU
        select PPC_HAVE_PMU_SUPPORT
+       select PPC_HAVE_KUEP
 
 config PPC_85xx
        bool "Freescale 85xx"