From f881fd5a75d0731743bad5b5f05add485c867d4b Mon Sep 17 00:00:00 2001
From: Phil Elwell <phil@raspberrypi.org>
Date: Tue, 29 Mar 2016 15:32:30 +0100
Subject: [PATCH] copy_from_user: CPU_SW_DOMAIN_PAN compatibility

The downstream copy_from_user acceleration must also play nice with
CONFIG_CPU_SW_DOMAIN_PAN.

See: https://github.com/raspberrypi/linux/issues/1381

Signed-off-by: Phil Elwell <phil@raspberrypi.org>
---
 arch/arm/lib/uaccess_with_memcpy.c | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

--- a/arch/arm/lib/uaccess_with_memcpy.c
+++ b/arch/arm/lib/uaccess_with_memcpy.c
@@ -186,6 +186,7 @@ out:
 unsigned long noinline
 __copy_from_user_memcpy(void *to, const void __user *from, unsigned long n)
 {
+	unsigned long ua_flags;
 	int atomic;
 
 	if (unlikely(segment_eq(get_fs(), KERNEL_DS))) {
@@ -217,7 +218,9 @@ __copy_from_user_memcpy(void *to, const
 		if (tocopy > n)
 			tocopy = n;
 
+		ua_flags = uaccess_save_and_enable();
 		memcpy(to, (const void *)from, tocopy);
+		uaccess_restore(ua_flags);
 		to += tocopy;
 		from += tocopy;
 		n -= tocopy;
@@ -261,9 +264,14 @@ arm_copy_from_user(void *to, const void
 	 * With frame pointer disabled, tail call optimization kicks in
 	 * as well making this test almost invisible.
 	 */
-	if (n < COPY_FROM_USER_THRESHOLD)
-		return __copy_from_user_std(to, from, n);
-	return __copy_from_user_memcpy(to, from, n);
+	if (n < COPY_TO_USER_THRESHOLD) {
+		unsigned long ua_flags = uaccess_save_and_enable();
+		n = __copy_from_user_std(to, from, n);
+		uaccess_restore(ua_flags);
+	} else {
+		n = __copy_from_user_memcpy(to, from, n);
+	}
+	return n;
 }
 	
 static unsigned long noinline
