Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rmk/linux
[linux-block.git] / arch / arm / include / asm / uaccess.h
index 9556d04387f7c2048fcf60a1a9263650b9c307cc..6c9c16d767cfd5df81e5d45c2df23b1454070673 100644 (file)
@@ -14,6 +14,8 @@
 #include <asm/domain.h>
 #include <asm/unaligned.h>
 #include <asm/unified.h>
+#include <asm/pgtable.h>
+#include <asm/proc-fns.h>
 #include <asm/compiler.h>
 
 #include <asm/extable.h>
  * perform such accesses (eg, via list poison values) which could then
  * be exploited for priviledge escalation.
  */
+#if defined(CONFIG_CPU_SW_DOMAIN_PAN)
+
 static __always_inline unsigned int uaccess_save_and_enable(void)
 {
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
        unsigned int old_domain = get_domain();
 
        /* Set the current domain access to permit user accesses */
@@ -34,19 +37,49 @@ static __always_inline unsigned int uaccess_save_and_enable(void)
                   domain_val(DOMAIN_USER, DOMAIN_CLIENT));
 
        return old_domain;
-#else
-       return 0;
-#endif
 }
 
 static __always_inline void uaccess_restore(unsigned int flags)
 {
-#ifdef CONFIG_CPU_SW_DOMAIN_PAN
        /* Restore the user access mask */
        set_domain(flags);
-#endif
 }
 
+#elif defined(CONFIG_CPU_TTBR0_PAN)
+
+static __always_inline unsigned int uaccess_save_and_enable(void)
+{
+       unsigned int old_ttbcr = cpu_get_ttbcr();
+
+       /*
+        * Enable TTBR0 page table walks (T0SZ = 0, EDP0 = 0) and ASID from
+        * TTBR0 (A1 = 0).
+        */
+       cpu_set_ttbcr(old_ttbcr & ~(TTBCR_A1 | TTBCR_EPD0 | TTBCR_T0SZ_MASK));
+       isb();
+
+       return old_ttbcr;
+}
+
+static inline void uaccess_restore(unsigned int flags)
+{
+       cpu_set_ttbcr(flags);
+       isb();
+}
+
+#else
+
+static inline unsigned int uaccess_save_and_enable(void)
+{
+       return 0;
+}
+
+static inline void uaccess_restore(unsigned int flags)
+{
+}
+
+#endif
+
 /*
  * These two are intentionally not defined anywhere - if the kernel
  * code generates any references to them, that's a bug.