diff options
Diffstat (limited to 'tools/regression/compat32/aarch64/swp_test_impl.S')
| -rw-r--r-- | tools/regression/compat32/aarch64/swp_test_impl.S | 410 |
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 |
