*/
 #define valid_user_address(x) ((__force long)(x) >= 0)
 
+/*
+ * Masking the user address is an alternative to a conditional
+ * user_access_begin that can avoid the fencing. This only works
+ * for dense accesses starting at the address.
+ */
+#define mask_user_address(x) ((typeof(x))((long)(x)|((long)(x)>>63)))
+#define masked_user_access_begin(x) ({ __uaccess_begin(); mask_user_address(x); })
+
 /*
  * User pointers can have tag bits on x86-64.  This scheme tolerates
  * arbitrary values in those bits rather then masking them off.
 
 {
        // the path is hot enough for overhead of copy_from_user() to matter
        if (from) {
-               if (!user_read_access_begin(from, sizeof(*from)))
+               if (can_do_masked_user_access())
+                       from = masked_user_access_begin(from);
+               else if (!user_read_access_begin(from, sizeof(*from)))
                        return -EFAULT;
                unsafe_get_user(to->p, &from->p, Efault);
                unsafe_get_user(to->size, &from->size, Efault);
 
 })
 #endif
 
+#ifdef masked_user_access_begin
+ #define can_do_masked_user_access() 1
+#else
+ #define can_do_masked_user_access() 0
+ #define masked_user_access_begin(src) NULL
+#endif
+
 /*
  * Architectures should provide two primitives (raw_copy_{to,from}_user())
  * and get rid of their private instances of copy_{to,from}_user() and
 
        if (unlikely(count <= 0))
                return 0;
 
+       if (can_do_masked_user_access()) {
+               long retval;
+
+               src = masked_user_access_begin(src);
+               retval = do_strncpy_from_user(dst, src, count, count);
+               user_read_access_end();
+               return retval;
+       }
+
        max_addr = TASK_SIZE_MAX;
        src_addr = (unsigned long)untagged_addr(src);
        if (likely(src_addr < max_addr)) {
 
        if (unlikely(count <= 0))
                return 0;
 
+       if (can_do_masked_user_access()) {
+               long retval;
+
+               str = masked_user_access_begin(str);
+               retval = do_strnlen_user(str, count, count);
+               user_read_access_end();
+               return retval;
+       }
+
        max_addr = TASK_SIZE_MAX;
        src_addr = (unsigned long)untagged_addr(str);
        if (likely(src_addr < max_addr)) {