ARM: user_memcpy/memset/strlcpy: fix my horrible ARM assembly
Turns out I was way to green (and tired) last year to code this properly... now they finally work and the kernel is a lot more stable for it.
This commit is contained in:
@@ -82,27 +82,32 @@ FUNCTION(arm_context_switch):
|
|||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arm_context_switch)
|
FUNCTION_END(arm_context_switch)
|
||||||
|
|
||||||
|
|
||||||
/* addr_t arm_get_fsr(void); */
|
/* addr_t arm_get_fsr(void); */
|
||||||
FUNCTION(arm_get_fsr):
|
FUNCTION(arm_get_fsr):
|
||||||
mrc p15, 0, r0, c5, c0, 0 @ get FSR
|
mrc p15, 0, r0, c5, c0, 0 @ get FSR
|
||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arm_get_fsr)
|
FUNCTION_END(arm_get_fsr)
|
||||||
|
|
||||||
|
|
||||||
/* addr_t arm_get_far(void); */
|
/* addr_t arm_get_far(void); */
|
||||||
FUNCTION(arm_get_far):
|
FUNCTION(arm_get_far):
|
||||||
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
mrc p15, 0, r0, c6, c0, 0 @ get FAR
|
||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arm_get_far)
|
FUNCTION_END(arm_get_far)
|
||||||
|
|
||||||
|
|
||||||
/* addr_t arm_get_fp(void); */
|
/* addr_t arm_get_fp(void); */
|
||||||
FUNCTION(arm_get_fp):
|
FUNCTION(arm_get_fp):
|
||||||
mov r0, fp @ get framepointer
|
mov r0, fp @ get framepointer
|
||||||
bx lr
|
bx lr
|
||||||
FUNCTION_END(arm_get_fp);
|
FUNCTION_END(arm_get_fp);
|
||||||
|
|
||||||
|
|
||||||
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
/* status_t arch_cpu_user_memcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
||||||
FUNCTION(arch_cpu_user_memcpy):
|
FUNCTION(arch_cpu_user_memcpy):
|
||||||
stmfd sp!, { r4-r6 }
|
stmfd sp!, { r4-r6, lr }
|
||||||
|
|
||||||
ldr r6, [r3]
|
ldr r6, [r3]
|
||||||
ldr r4, =.L_user_memcpy_error
|
ldr r4, =.L_user_memcpy_error
|
||||||
str r4, [r3] /* set fault handler */
|
str r4, [r3] /* set fault handler */
|
||||||
@@ -112,33 +117,35 @@ FUNCTION(arch_cpu_user_memcpy):
|
|||||||
str r5, [r0]
|
str r5, [r0]
|
||||||
add r1, #4
|
add r1, #4
|
||||||
add r0, #4
|
add r0, #4
|
||||||
sub r4, #1
|
subs r4, #1
|
||||||
bne 1b
|
bne 1b
|
||||||
|
|
||||||
|
ands r4, r2, #3 /* size % 4 */
|
||||||
|
beq 3f
|
||||||
|
|
||||||
2:
|
2:
|
||||||
and r4, r2, #3 /* size % 4 */
|
|
||||||
ldrb r5, [r1]
|
ldrb r5, [r1]
|
||||||
strb r5, [r0]
|
strb r5, [r0]
|
||||||
add r1, #1
|
add r1, #1
|
||||||
add r0, #1
|
add r0, #1
|
||||||
sub r4, #1
|
subs r4, #1
|
||||||
bne 2b
|
bne 2b
|
||||||
|
3:
|
||||||
str r6, [r3] /* restore fault handler */
|
str r6, [r3] /* restore fault handler */
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
ldmfd sp!, { r4-r6 }
|
ldmfd sp!, { r4-r6, pc }
|
||||||
bx lr
|
|
||||||
|
|
||||||
.L_user_memcpy_error:
|
.L_user_memcpy_error:
|
||||||
str r6, [r3] /* restore fault handler */
|
str r6, [r3] /* restore fault handler */
|
||||||
mov r0, #-1
|
mov r0, #-1
|
||||||
|
|
||||||
ldmfd sp!, { r4-r6 }
|
ldmfd sp!, { r4-r6, pc }
|
||||||
bx lr
|
|
||||||
FUNCTION_END(arch_cpu_user_memcpy)
|
FUNCTION_END(arch_cpu_user_memcpy)
|
||||||
|
|
||||||
/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */
|
/* status_t arch_cpu_user_memset(void *to, char c, size_t count, addr_t *faultHandler) */
|
||||||
FUNCTION(arch_cpu_user_memset):
|
FUNCTION(arch_cpu_user_memset):
|
||||||
stmfd sp!, { r4-r5 }
|
stmfd sp!, { r4-r5, lr }
|
||||||
|
|
||||||
ldr r5, [r3]
|
ldr r5, [r3]
|
||||||
ldr r4, =.L_user_memset_error
|
ldr r4, =.L_user_memset_error
|
||||||
str r4, [r3]
|
str r4, [r3]
|
||||||
@@ -152,33 +159,31 @@ FUNCTION(arch_cpu_user_memset):
|
|||||||
1:
|
1:
|
||||||
str r1, [r0]
|
str r1, [r0]
|
||||||
add r0, r0, #4
|
add r0, r0, #4
|
||||||
sub r4, r4, #1
|
subs r4, r4, #1
|
||||||
bne 1b
|
bne 1b
|
||||||
|
|
||||||
and r4, r2, #3 /* count % 4 */
|
and r4, r2, #3 /* count % 4 */
|
||||||
2:
|
2:
|
||||||
strb r1, [r0]
|
strb r1, [r0]
|
||||||
add r0, r0, #1
|
add r0, r0, #1
|
||||||
sub r4, r4, #1
|
subs r4, r4, #1
|
||||||
bne 2b
|
bne 2b
|
||||||
|
|
||||||
mov r0, #0
|
mov r0, #0
|
||||||
str r5, [r3]
|
str r5, [r3]
|
||||||
|
|
||||||
ldmfd sp!, { r4-r5 }
|
ldmfd sp!, { r4-r5, pc }
|
||||||
bx lr
|
|
||||||
|
|
||||||
.L_user_memset_error:
|
.L_user_memset_error:
|
||||||
mov r0, #-1
|
mov r0, #-1
|
||||||
str r5, [r3]
|
str r5, [r3]
|
||||||
|
|
||||||
ldmfd sp!, { r4-r5 }
|
ldmfd sp!, { r4-r5, pc }
|
||||||
bx lr
|
|
||||||
FUNCTION_END(arch_cpu_user_memset)
|
FUNCTION_END(arch_cpu_user_memset)
|
||||||
|
|
||||||
/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
/* ssize_t arch_cpu_user_strlcpy(void *to, const void *from, size_t size, addr_t *faultHandler) */
|
||||||
FUNCTION(arch_cpu_user_strlcpy):
|
FUNCTION(arch_cpu_user_strlcpy):
|
||||||
stmfd sp!, { r4-r6 }
|
stmfd sp!, { r4-r6, lr }
|
||||||
ldr r5, [r3]
|
ldr r5, [r3]
|
||||||
ldr r4, =.L_user_strlcpy_error
|
ldr r4, =.L_user_strlcpy_error
|
||||||
str r4, [r3]
|
str r4, [r3]
|
||||||
@@ -187,7 +192,7 @@ FUNCTION(arch_cpu_user_strlcpy):
|
|||||||
ldrb r4, [r1, r6]
|
ldrb r4, [r1, r6]
|
||||||
strb r4, [r0, r6]
|
strb r4, [r0, r6]
|
||||||
add r6, r6, #1
|
add r6, r6, #1
|
||||||
and r4, #0xff /* done yet? */
|
cmp r4, #0
|
||||||
beq 2f
|
beq 2f
|
||||||
cmp r6, r2 /* reached max length? */
|
cmp r6, r2 /* reached max length? */
|
||||||
blt 1b
|
blt 1b
|
||||||
@@ -195,18 +200,16 @@ FUNCTION(arch_cpu_user_strlcpy):
|
|||||||
mov r4, #0
|
mov r4, #0
|
||||||
strb r4, [r0, r6]
|
strb r4, [r0, r6]
|
||||||
|
|
||||||
mov r0, r4 /* return B_OK */
|
mov r0, r6 /* return length */
|
||||||
str r5, [r3] /* restore fault handler */
|
str r5, [r3] /* restore fault handler */
|
||||||
|
|
||||||
ldmfd sp!, { r4-r6 }
|
ldmfd sp!, { r4-r6, pc }
|
||||||
bx lr
|
|
||||||
|
|
||||||
.L_user_strlcpy_error:
|
.L_user_strlcpy_error:
|
||||||
mov r0, #-1
|
mov r0, #-1
|
||||||
str r5, [r3]
|
str r5, [r3]
|
||||||
|
|
||||||
ldmfd sp!, { r4-r6 }
|
ldmfd sp!, { r4-r6, pc }
|
||||||
bx lr
|
|
||||||
FUNCTION_END(arch_cpu_user_strlcpy)
|
FUNCTION_END(arch_cpu_user_strlcpy)
|
||||||
|
|
||||||
|
|
||||||
@@ -242,12 +245,11 @@ FUNCTION(arch_debug_call_with_fault_handler):
|
|||||||
blx r2
|
blx r2
|
||||||
|
|
||||||
// regular return
|
// regular return
|
||||||
ldmfd sp!, { r4, lr }
|
ldmfd sp!, { r4, pc }
|
||||||
bx lr
|
|
||||||
|
|
||||||
// fault -- return via longjmp(jumpBuffer, 1)
|
// fault -- return via longjmp(jumpBuffer, 1)
|
||||||
1:
|
1:
|
||||||
mov r0, r4
|
mov r0, r1
|
||||||
mov r1, #1
|
mov r1, #1
|
||||||
bl longjmp
|
bl longjmp
|
||||||
FUNCTION_END(arch_debug_call_with_fault_handler)
|
FUNCTION_END(arch_debug_call_with_fault_handler)
|
||||||
|
|||||||
Reference in New Issue
Block a user