aboutsummaryrefslogtreecommitdiff
path: root/tools/regression/compat32/aarch64/swp_test_impl.S
diff options
context:
space:
mode:
Diffstat (limited to 'tools/regression/compat32/aarch64/swp_test_impl.S')
-rw-r--r--tools/regression/compat32/aarch64/swp_test_impl.S410
1 files changed, 410 insertions, 0 deletions
diff --git a/tools/regression/compat32/aarch64/swp_test_impl.S b/tools/regression/compat32/aarch64/swp_test_impl.S
new file mode 100644
index 000000000000..9f28ab17748e
--- /dev/null
+++ b/tools/regression/compat32/aarch64/swp_test_impl.S
@@ -0,0 +1,410 @@
+/*
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2021 Warner Losh
+ * Copyright (c) 2023 Stormshield
+ * Copyright (c) 2023 Klara, Inc.
+ */
+
+#include <sys/syscall.h>
+
+#define STDOUT_FILENO 1
+
+#define MUTEX_LOCKED 0x01
+#define MUTEX_UNLOCKED 0x00
+
+#define STACK_SIZE 4096
+#define TLS_SIZE 4096
+
+ .text
+ .file "swp_test.S"
+ .syntax unified
+ .globl main
+ .p2align 2
+ .type main,%function
+ .code 32
+
+main:
+ /*
+ * Stack slots:
+ * 0 - Sync word
+ * 1 - Thread id
+ * 2 - Shared word
+ */
+ sub sp, sp, #12
+
+ /* Print a message */
+ movw r0, :lower16:.L.mainmsg
+ movt r0, :upper16:.L.mainmsg
+ ldr r1, =(.L.mainmsgEnd - .L.mainmsg - 1)
+ bl print
+
+ /* Create two secondary threads */
+ mov r0, #1
+ str r0, [sp, #4] /* Thread ID */
+ movw r0, :lower16:secondary_thread
+ movt r0, :upper16:secondary_thread
+ mov r1, sp
+ movw r2, :lower16:stack1
+ movt r2, :upper16:stack1
+ movw r3, :lower16:tls1
+ movt r3, :upper16:tls1
+ bl create_thr
+
+1:
+ /*
+ * Wait for the first new thread to ack its existence by
+ * incrementing the thread id.
+ */
+ ldr r0, [sp, #4]
+ cmp r0, #1
+ bne 2f
+ ldr r7, =SYS_sched_yield
+ swi 0
+ b 1b
+
+2:
+ /* Create thread #2 */
+ movw r0, :lower16:secondary_thread
+ movt r0, :upper16:secondary_thread
+ mov r1, sp
+ movw r2, :lower16:stack2
+ movt r2, :upper16:stack2
+ movw r3, :lower16:tls2
+ movt r3, :upper16:tls2
+ bl create_thr
+
+3:
+ /*
+ * Wait for the first new thread to ack its existence by
+ * incrementing the thread id.
+ */
+ ldr r0, [sp, #4]
+ cmp r0, #2
+ bne 4f
+ ldr r7, =SYS_sched_yield
+ swi 0
+ b 3b
+
+ /* Loop */
+4:
+ mov r0, sp
+ mov r1, #0 /* Thread loop */
+ add r2, sp, #8
+ bl thread_loop
+ b 4b
+
+ /* UNREACHABLE */
+ mov r0, #0
+ ldr r7, =SYS_exit
+ swi 0
+
+ .p2align 2
+ .type secondary_thread,%function
+ .code 32
+secondary_thread:
+ /*
+ * On entry, r0 is where we stashed our sync word and
+ * ack word (thread ID).
+ *
+ * Stash the sync word in r4, thread ID in r5.
+ */
+ mov r4, r0
+ ldr r5, [r0, #4]
+
+ /* Print a message */
+ movw r0, :lower16:.L.secondarymsg
+ movt r0, :upper16:.L.secondarymsg
+ ldr r1, =(.L.secondarymsgEnd - .L.secondarymsg - 1)
+ bl print
+
+ /* Acknowledge that we started */
+ add r0, r5, #1
+ str r0, [r4, #4]
+
+1:
+ mov r0, r4
+ mov r1, r5
+ add r2, r4, #8
+ bl thread_loop
+ b 1b
+
+ .p2align 2
+ .type thread_loop,%function
+ .code 32
+thread_loop:
+ push {r4, r5, r6, r7, r8, lr}
+
+ /*
+ * r0 == sync word
+ * r1 == thread ID
+ * r2 == shared word
+ */
+ mov r4, r0
+ mov r5, r1
+ mov r6, r2
+ bl lock_mutex_swp
+ str r5, [r6] /* Write the thread ID */
+ bl random_cycles
+
+ # Save off the now cycle count */
+ mov r8, r0
+
+ /* Print the thread ID and cycle count */
+ mov r0, r5
+ mov r1, #0
+ bl printnum
+
+ /* Separator */
+ movw r0, :lower16:.L.idsep
+ movt r0, :upper16:.L.idsep
+ ldr r1, =(.L.idsepEnd - .L.idsep - 1)
+ bl print
+
+ /* Cycle count */
+ mov r0, r8
+ mov r1, #1
+ bl printnum
+
+1:
+ ldr r0, [r6]
+ cmp r0, r5 /* Check against the thread ID */
+ bne 2f
+ str r5, [r6]
+
+ /*
+ * Check if the count hit 0, otherwise go again.
+ */
+ cmp r8, #0
+ beq 3f
+ sub r8, r8, #1
+ b 1b
+
+2:
+ /* exit(1) */
+ mov r0, #1
+ ldr r7, =SYS_exit
+ swi 0
+
+3:
+ mov r0, r4
+ bl unlock_mutex_swp
+
+ /*
+ * Yield to lower the chance that we end up re-acquiring, the other two
+ * threads are still actively trying to acquire the lock.
+ */
+ ldr r7, =SYS_sched_yield
+ swi 0
+
+ pop {r4, r5, r6, r7, r8, lr}
+ bx lr
+
+ .p2align 2
+ .type random_cycles,%function
+ .code 32
+random_cycles:
+ /* Return a random number < 4k */
+ sub sp, sp, #4
+ mov r0, sp
+ mov r1, #4
+ mov r2, #0
+ ldr r7, =SYS_getrandom
+ swi 0
+
+ /*
+ * Just truncate the result of getrandom(2)
+ * to put us within range. Naive, but functional.
+ */
+ ldr r0, [sp]
+ mov r1, #0xfff
+ and r0, r0, r1
+ add sp, sp, #4
+ bx lr
+
+ /*
+ * lock_mutex_swp and unlock_mutex_swp lifted from
+ * ARM documentation on SWP/SWPB.
+ */
+ .p2align 2
+ .type lock_mutex_swp,%function
+ .code 32
+lock_mutex_swp:
+ mov r2, #MUTEX_LOCKED
+ swp r1, r2, [r0] /* Swap in lock value. */
+ cmp r1, r2 /* Check if we were locked already. */
+ beq lock_mutex_swp /* Retry if so */
+ bx lr /* Return locked */
+
+ .p2align 2
+ .type unlock_mutex_swp,%function
+ .code 32
+unlock_mutex_swp:
+ mov r1, #MUTEX_UNLOCKED
+ str r1, [r0] /* Move in unlocked */
+ bx lr
+
+ .p2align 2
+ .type create_thr,%function
+ .code 32
+create_thr:
+ /*
+ * r0 == start_func
+ * r1 == arg
+ * r2 == stack_base
+ * r3 == tls_base
+ */
+ sub sp, sp, #56
+ str r0, [sp, #4] /* start_func */
+ str r1, [sp, #8] /* arg */
+ str r2, [sp, #12] /* stack_base */
+ mov r0, #STACK_SIZE
+ str r0, [sp, #16] /* stack_size */
+ str r3, [sp, #20] /* tls_base */
+ mov r0, #TLS_SIZE
+ str r0, [sp, #24] /* tls_size */
+ mov r0, #0
+ str r0, [sp, #28]
+ str r0, [sp, #32]
+ str r0, [sp, #36]
+ str r0, [sp, #40]
+
+ add r0, sp, #4 /* &thrp */
+ mov r1, #52 /* sizeof(thrp) */
+ ldr r7, =SYS_thr_new
+ swi 0
+
+ add sp, sp, #56
+ bx lr
+
+ .p2align 2
+ .type printnum,%function
+ .code 32
+printnum:
+ push {r4, r5, r6, r7, r8, r10, lr}
+ sub sp, #4
+
+ /* 1000000000 */
+ movw r6, #0xca00
+ movt r6, #0x3b9a
+
+ udiv r5, r0, r6
+ cmp r5, #9
+ bhi abort
+
+ /* r4 is our accumulator */
+ mov r4, r0
+ /* r5 to be used as our "significant bit" */
+ mov r5, #0
+ /* r10 is "output_newline" */
+ mov r10, r1
+
+1:
+ cmp r6, #0
+ beq 4f
+
+ /* Divide by current place */
+ udiv r0, r4, r6
+ /* Significant already? print anyways */
+ cmp r5, #0
+ bne 2f
+
+ /*
+ * Not significant, maybe print. If we made it all the way to 1, we
+ * need to just print the 0 anyways.
+ */
+ cmp r6, #1
+ beq 2f
+
+ cmp r0, #0
+ bne 2f
+ b 3f /* Proceed */
+
+ /* Print */
+2:
+ mov r5, #1
+ mov r8, r0
+ add r0, r0, #0x30
+ str r0, [sp]
+ mov r0, sp
+ mov r1, #1
+ bl print
+
+ /* Multiply back into place and subtract from accumulator */
+ mul r0, r8, r6
+ sub r4, r4, r0
+
+3:
+ mov r3, #10
+ udiv r6, r6, r3
+ b 1b
+
+4:
+ cmp r10, #0
+ beq 5f
+
+ /* newline */
+ mov r0, #0x0a
+ str r0, [sp]
+ mov r0, sp
+ mov r1, #1
+ bl print
+
+5:
+ add sp, sp, #4
+ pop {r4, r5, r6, r7, r8, r10, lr}
+ bx lr
+
+abort:
+ movw r0, :lower16:.L.badnum
+ movt r0, :upper16:.L.badnum
+ ldr r1, =(.L.badnumEnd - .L.badnum - 1)
+ bl print
+
+ mov r0, #1
+ ldr r7, =SYS_exit
+ swi 0
+
+ .p2align 2
+ .type print,%function
+ .code 32
+print:
+ /* r0 - string, r1 = size */
+ mov r2, r1
+ mov r1, r0
+ ldr r0, =STDOUT_FILENO
+ ldr r7, =SYS_write
+ swi 0
+
+ bx lr
+
+.L.mainmsg:
+ .asciz "Main thread\n"
+.L.mainmsgEnd:
+ .size .L.mainmsg, .L.mainmsgEnd - .L.mainmsg
+.L.secondarymsg:
+ .asciz "Secondary thread\n"
+.L.secondarymsgEnd:
+ .size .L.secondarymsg, .L.secondarymsgEnd - .L.secondarymsg
+.L.badnum:
+ .asciz "Bad number\n"
+.L.badnumEnd:
+ .size .L.badnum, .L.badnumEnd - .L.badnum
+.L.idsep:
+ .asciz " - cycles "
+.L.idsepEnd:
+ .size .L.idsep, .L.idsepEnd - .L.idsep
+
+ .type stack1,%object
+ .local stack1
+ .comm stack1,STACK_SIZE,1
+ .type tls1,%object
+ .local tls1
+ .comm tls1,TLS_SIZE,1
+
+ .type stack2,%object
+ .local stack2
+ .comm stack2,STACK_SIZE,1
+ .type tls2,%object
+ .local tls2
+ .comm tls2,TLS_SIZE,1