ARMv8.1 introduced PAN (Priviliged Access Never) which prevents the
kernel from accessing userland data.  This can be bypassed by using
special instructions which we already use in copyin(9) and friends.
So we can simply turn this feature on if the CPU supports it.

Tested on an Odroid-C4 which has Cortex-A55 cores that have PAN
support.

ok?


Index: arch/arm64/arm64/cpu.c
===================================================================
RCS file: /cvs/src/sys/arch/arm64/arm64/cpu.c,v
retrieving revision 1.38
diff -u -p -r1.38 cpu.c
--- arch/arm64/arm64/cpu.c      4 Jun 2020 21:18:16 -0000       1.38
+++ arch/arm64/arm64/cpu.c      13 Aug 2020 19:12:30 -0000
@@ -321,6 +321,7 @@ cpu_attach(struct device *parent, struct
        struct fdt_attach_args *faa = aux;
        struct cpu_info *ci;
        uint64_t mpidr = READ_SPECIALREG(mpidr_el1);
+       uint64_t id_aa64mmfr1, sctlr;
        uint32_t opp;
 
        KASSERT(faa->fa_nreg > 0);
@@ -393,6 +394,14 @@ cpu_attach(struct device *parent, struct
                        cpu_cpuspeed = cpu_clockspeed;
                }
 
+               /* Enable PAN. */
+               id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
+               if (ID_AA64MMFR1_PAN(id_aa64mmfr1) != ID_AA64MMFR1_PAN_NONE) {
+                       sctlr = READ_SPECIALREG(sctlr_el1);
+                       sctlr &= ~SCTLR_SPAN;
+                       WRITE_SPECIALREG(sctlr_el1, sctlr);
+               }
+
                /* Initialize debug registers. */
                WRITE_SPECIALREG(mdscr_el1, DBG_MDSCR_TDCC);
                WRITE_SPECIALREG(oslar_el1, 0);
@@ -522,6 +531,7 @@ cpu_boot_secondary(struct cpu_info *ci)
 void
 cpu_start_secondary(struct cpu_info *ci)
 {
+       uint64_t id_aa64mmfr1, sctlr;
        uint64_t tcr;
        int s;
 
@@ -543,6 +553,14 @@ cpu_start_secondary(struct cpu_info *ci)
        tcr |= TCR_T0SZ(64 - USER_SPACE_BITS);
        tcr |= TCR_A1;
        WRITE_SPECIALREG(tcr_el1, tcr);
+
+       /* Enable PAN. */
+       id_aa64mmfr1 = READ_SPECIALREG(id_aa64mmfr1_el1);
+       if (ID_AA64MMFR1_PAN(id_aa64mmfr1) != ID_AA64MMFR1_PAN_NONE) {
+               sctlr = READ_SPECIALREG(sctlr_el1);
+               sctlr &= ~SCTLR_SPAN;
+               WRITE_SPECIALREG(sctlr_el1, sctlr);
+       }
 
        /* Initialize debug registers. */
        WRITE_SPECIALREG(mdscr_el1, DBG_MDSCR_TDCC);
Index: arch/arm64/include/armreg.h
===================================================================
RCS file: /cvs/src/sys/arch/arm64/include/armreg.h,v
retrieving revision 1.11
diff -u -p -r1.11 armreg.h
--- arch/arm64/include/armreg.h 5 Jun 2020 22:14:25 -0000       1.11
+++ arch/arm64/include/armreg.h 13 Aug 2020 19:12:30 -0000
@@ -451,6 +451,7 @@
 #define        SCTLR_nTWI      0x00010000
 #define        SCTLR_nTWE      0x00040000
 #define        SCTLR_WXN       0x00080000
+#define        SCTLR_SPAN      0x00800000
 #define        SCTLR_EOE       0x01000000
 #define        SCTLR_EE        0x02000000
 #define        SCTLR_UCI       0x04000000
@@ -478,6 +479,7 @@
 #define        PSR_D           0x00000200
 #define        PSR_IL          0x00100000
 #define        PSR_SS          0x00200000
+#define        PSR_PAN         0x00400000
 #define        PSR_V           0x10000000
 #define        PSR_C           0x20000000
 #define        PSR_Z           0x40000000

Reply via email to