This preserves the initial arguments of the user copy calls so that
they can be restored by the fixup routines.
The values in the relevant three registers (x0/dstin, x1/src,
x2/count) may be modified by the optimized memcpy algorithm for large
copy sizes, and this stores them before it begins executing.
The stack is used instead of other general-purpose registers due to
resource constraints: the algorithm is optimized with respect to the
Procedure Call Standard in the Arm ABI, which assumes that x0-x17
can be used as scratch registers and utilizes all of them during
copying, but leaves alone the rest that have specific uses in the
broader system. As there are no more temporary registers, the stack
can be used to preserve the initial arguments to provide fixup
routines with more information to use in the calculation of the
number of bytes that failed to copy.
The stack pointer is restored to its initial position, either from
the fixup code in the case of a fault, or at the end of the copy
algorithm otherwise (uaccess_finish is extended to restore the sp,
and this code is also moved to copy_template_user.S as it is common
to all of the copy routines that access userspace memory).
Signed-off-by: Oliver Swede <[email protected]>
---
arch/arm64/lib/copy_from_user.S | 3 ---
arch/arm64/lib/copy_in_user.S | 3 ---
arch/arm64/lib/copy_template_user.S | 6 ++++++
arch/arm64/lib/copy_to_user.S | 3 ---
arch/arm64/lib/copy_user_fixup.S | 1 +
5 files changed, 7 insertions(+), 9 deletions(-)
diff --git a/arch/arm64/lib/copy_from_user.S b/arch/arm64/lib/copy_from_user.S
index fa319f27a42b..cd3042e98394 100644
--- a/arch/arm64/lib/copy_from_user.S
+++ b/arch/arm64/lib/copy_from_user.S
@@ -110,9 +110,6 @@
SYM_FUNC_START(__arch_copy_from_user)
#include "copy_template_user.S"
-.Luaccess_finish:
- mov x0, #0
- ret
SYM_FUNC_END(__arch_copy_from_user)
EXPORT_SYMBOL(__arch_copy_from_user)
#include "copy_user_fixup.S"
diff --git a/arch/arm64/lib/copy_in_user.S b/arch/arm64/lib/copy_in_user.S
index 6b9bb6091dd8..fe035e513b34 100644
--- a/arch/arm64/lib/copy_in_user.S
+++ b/arch/arm64/lib/copy_in_user.S
@@ -117,9 +117,6 @@
SYM_FUNC_START(__arch_copy_in_user)
#include "copy_template_user.S"
-.Luaccess_finish:
- mov x0, #0
- ret
SYM_FUNC_END(__arch_copy_in_user)
EXPORT_SYMBOL(__arch_copy_in_user)
#include "copy_user_fixup.S"
diff --git a/arch/arm64/lib/copy_template_user.S b/arch/arm64/lib/copy_template_user.S
index 3db24dcdab05..1d13daf314b0 100644
--- a/arch/arm64/lib/copy_template_user.S
+++ b/arch/arm64/lib/copy_template_user.S
@@ -21,4 +21,10 @@
L(copy_non_uao):
#undef L
#define L(l) .Lnuao ## l
+ str x2, [sp, #-16]! // count
+ stp x0, x1, [sp, #-16]! // dstin, src
#include "copy_template.S"
+.Luaccess_finish:
+ add sp, sp, 32
+ mov x0, #0
+ ret
diff --git a/arch/arm64/lib/copy_to_user.S b/arch/arm64/lib/copy_to_user.S
index 23af6af254da..de0af211b3ba 100644
--- a/arch/arm64/lib/copy_to_user.S
+++ b/arch/arm64/lib/copy_to_user.S
@@ -110,9 +110,6 @@
SYM_FUNC_START(__arch_copy_to_user)
#include "copy_template_user.S"
-.Luaccess_finish:
- mov x0, #0
- ret
SYM_FUNC_END(__arch_copy_to_user)
EXPORT_SYMBOL(__arch_copy_to_user)
#include "copy_user_fixup.S"
diff --git a/arch/arm64/lib/copy_user_fixup.S b/arch/arm64/lib/copy_user_fixup.S
index 117c37598691..fe9f5ac19605 100644
--- a/arch/arm64/lib/copy_user_fixup.S
+++ b/arch/arm64/lib/copy_user_fixup.S
@@ -5,5 +5,6 @@ addr .req x15
.align 2
9998:
// TODO: add accurate fixup
+ add sp, sp, 32
ret
--
2.17.1