The branch main has been updated by kevans:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ccb59683b98360afaf5b5bb641a68fea22c68d0b

commit ccb59683b98360afaf5b5bb641a68fea22c68d0b
Author:     Kyle Evans <kev...@freebsd.org>
AuthorDate: 2023-05-15 15:42:16 +0000
Commit:     Kyle Evans <kev...@freebsd.org>
CommitDate: 2023-05-15 15:42:16 +0000

    arm64: add tests for swp/swpb emulation
    
    One test is suitable to be hooked up to the build, so I've done this
    here.  The other test lives in tools/regression because failure is a
    bit more subjective -- generally, one runs it for some unbounded amount
    of time and observe if it eventually exits because two threads acquired
    the same mutex.
    
    Reviewed by:    imp, mmel
    Sponsored by:   Stormshield
    Sponsored by:   Klara, Inc.
    Differential Revision:  https://reviews.freebsd.org/D39668
---
 etc/mtree/BSD.tests.dist                          |   2 +
 tests/sys/Makefile                                |   1 +
 tests/sys/compat32/Makefile                       |   6 +
 tests/sys/compat32/Makefile.inc                   |   4 +
 tests/sys/compat32/aarch64/Makefile               |  24 ++
 tests/sys/compat32/aarch64/common.sh              |   9 +
 tests/sys/compat32/aarch64/swp_cond_test.sh       |  14 +
 tests/sys/compat32/aarch64/swp_cond_test_impl.S   | 413 ++++++++++++++++++++++
 tests/sys/compat32/aarch64/swp_test.sh            |  14 +
 tests/sys/compat32/aarch64/swp_test_impl.S        | 216 +++++++++++
 tools/regression/compat32/aarch64/Makefile        |   4 +
 tools/regression/compat32/aarch64/swp_test_impl.S | 410 +++++++++++++++++++++
 12 files changed, 1117 insertions(+)

diff --git a/etc/mtree/BSD.tests.dist b/etc/mtree/BSD.tests.dist
index 5d99653100df..77c07960f938 100644
--- a/etc/mtree/BSD.tests.dist
+++ b/etc/mtree/BSD.tests.dist
@@ -750,6 +750,8 @@
                 ..
             ..
         ..
+        compat32
+        ..
         devrandom
         ..
         dtrace
diff --git a/tests/sys/Makefile b/tests/sys/Makefile
index 8f83445f9d91..3e9a30105a1d 100644
--- a/tests/sys/Makefile
+++ b/tests/sys/Makefile
@@ -10,6 +10,7 @@ TESTS_SUBDIRS+=               ${_audit}
 TESTS_SUBDIRS+=                auditpipe
 TESTS_SUBDIRS+=                capsicum
 TESTS_SUBDIRS+=                ${_cddl}
+TESTS_SUBDIRS+=                compat32
 TESTS_SUBDIRS+=                devrandom
 TESTS_SUBDIRS+=                fifo
 TESTS_SUBDIRS+=                file
diff --git a/tests/sys/compat32/Makefile b/tests/sys/compat32/Makefile
new file mode 100644
index 000000000000..31834de16246
--- /dev/null
+++ b/tests/sys/compat32/Makefile
@@ -0,0 +1,6 @@
+
+.if exists(${.CURDIR}/${MACHINE_ARCH})
+SUBDIR+=       ${MACHINE_ARCH}
+.endif
+
+.include <bsd.subdir.mk>
diff --git a/tests/sys/compat32/Makefile.inc b/tests/sys/compat32/Makefile.inc
new file mode 100644
index 000000000000..0220ac0431e9
--- /dev/null
+++ b/tests/sys/compat32/Makefile.inc
@@ -0,0 +1,4 @@
+
+TESTSDIR=              ${TESTSBASE}/sys/compat32
+
+.include "../Makefile.inc"
diff --git a/tests/sys/compat32/aarch64/Makefile 
b/tests/sys/compat32/aarch64/Makefile
new file mode 100644
index 000000000000..716182b15d9c
--- /dev/null
+++ b/tests/sys/compat32/aarch64/Makefile
@@ -0,0 +1,24 @@
+PACKAGE=       tests
+FILESGROUPS+=  asmprogs
+
+ACFLAGS= -target armv7-unknown-freebsd${OS_REVISION} -nostdlib -Wl,-e -Wl,main 
-static
+
+TAP_TESTS_SH+= swp_cond_test
+TAP_TESTS_SH+= swp_test
+${PACKAGE}FILES+=      common.sh
+
+# Each test will individually respect the compat.arm.emul_swp
+# sysctl upon entry.
+TEST_METADATA.swp_cond_test+=  is_exclusive=true
+TEST_METADATA.swp_test+=       is_exclusive=true
+
+asmprogsMODE=          0755
+asmprogs+=     swp_cond_test_impl swp_test_impl
+asmprogsDIR=   ${TESTSDIR}
+
+.for aprog in ${asmprogs}
+${aprog}: ${aprog}.S
+       ${CC} ${ACFLAGS} -o ${.TARGET} ${.ALLSRC}
+.endfor
+
+.include <bsd.test.mk>
diff --git a/tests/sys/compat32/aarch64/common.sh 
b/tests/sys/compat32/aarch64/common.sh
new file mode 100644
index 000000000000..f8b02e8ac157
--- /dev/null
+++ b/tests/sys/compat32/aarch64/common.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+if ! sysctl -n kern.features.compat_freebsd_32bit >/dev/null 2>&1; then
+       echo "1..0 # Skipped: Kernel not built with COMPAT_FREEBSD32"
+       exit 0
+elif ! sysctl -n kern.supported_archs | grep -q '\<armv7\>'; then
+       echo "1..0 # Skipped: 32-bit ARM not supported on this hardware"
+       exit 0
+fi
diff --git a/tests/sys/compat32/aarch64/swp_cond_test.sh 
b/tests/sys/compat32/aarch64/swp_cond_test.sh
new file mode 100644
index 000000000000..8edfa43b3e7e
--- /dev/null
+++ b/tests/sys/compat32/aarch64/swp_cond_test.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+scriptdir=$(dirname $(realpath "$0"))
+
+. ${scriptdir}/common.sh
+
+# Ensure emul_swp is enabled just for this test; we'll turn it back off if
+# it wasn't enabled before the test.
+emul_swpval=$(sysctl -n compat.arm.emul_swp)
+sysctl compat.arm.emul_swp=1 >/dev/null
+${scriptdir}/swp_test_impl
+if [ "$emul_swpval" -ne 1 ]; then
+       sysctl compat.arm.emul_swp="$emul_swpval" >/dev/null
+fi
diff --git a/tests/sys/compat32/aarch64/swp_cond_test_impl.S 
b/tests/sys/compat32/aarch64/swp_cond_test_impl.S
new file mode 100644
index 000000000000..d29db44832b1
--- /dev/null
+++ b/tests/sys/compat32/aarch64/swp_cond_test_impl.S
@@ -0,0 +1,413 @@
+/*
+ * 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        SWP_MAGIC       0xffc0
+#define        SWPB_MAGIC      0xc0c0
+
+       .text
+       .file "swp_test.S"
+       .syntax unified
+       .globl main
+       .p2align 2
+       .type main,%function
+       .code 32
+
+main:
+       sub sp, #0x04
+       /* r4 is our failed test counter */
+       mov r4, #0
+       /* r6 is our current teset counter */
+       mov r6, #1
+
+       movw r0, :lower16:.L.testheader
+       movt r0, :upper16:.L.testheader
+       ldr r1, =(.L.testheaderEnd - .L.testheader - 1)
+       bl print
+
+       /* eq */
+       bl reset
+       mov r1, #SWP_MAGIC
+       cmp r1, r1
+       swpeq r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 1f
+
+       /* !eq */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0
+       cmp r1, r2
+       swpeq r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+1:
+       movw r0, :lower16:.L.eq
+       movt r0, :upper16:.L.eq
+       ldr r1, =(.L.eqEnd - .L.eq - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       /* cs */
+       bl reset
+       mov r1, #SWP_MAGIC
+       movw r3, #0xffff
+       movt r3, #0xffff
+       /* Overflow */
+       adds r2, r3, r3
+       swpcs r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 2f
+
+       /* !cs */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r3, #0x00
+       adds r2, r3, #0x08
+       swpcs r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+2:
+       movw r0, :lower16:.L.cs
+       movt r0, :upper16:.L.cs
+       ldr r1, =(.L.csEnd - .L.cs - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       /* mi */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0
+       /* Underflow */
+       subs r2, r2, #0x05
+       swpmi r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 3f
+
+       /* !mi */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x10
+       subs r2, r2, #0x08
+       swpmi r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+3:
+       movw r0, :lower16:.L.mi
+       movt r0, :upper16:.L.mi
+       ldr r1, =(.L.miEnd - .L.mi - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       /* vs */
+       bl reset
+       mov r1, #SWP_MAGIC
+       movw r3, #0xffff
+       movt r3, #0x7fff
+       /* Overflow */
+       adds r2, r3, #0x10
+       swpvs r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 4f
+
+       /* !vs */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r3, #0x00
+       adds r2, r3, #0x08
+       swpvs r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+4:
+       movw r0, :lower16:.L.vs
+       movt r0, :upper16:.L.vs
+       ldr r1, =(.L.vsEnd - .L.vs - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       /* hi */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x00
+       mov r3, #0x01
+       cmp r3, r2
+       swphi r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 5f
+
+       /* !hi */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x00
+       mov r3, #0x01
+       cmp r2, r3
+       swphi r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+5:
+       movw r0, :lower16:.L.hi
+       movt r0, :upper16:.L.hi
+       ldr r1, =(.L.hiEnd - .L.hi - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       /* ge */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x01
+       cmp r2, r2
+       swpge r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 6f
+
+       /* !ge */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x00
+       mov r3, #0x01
+       cmp r2, r3
+       swpge r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+6:
+       movw r0, :lower16:.L.ge
+       movt r0, :upper16:.L.ge
+       ldr r1, =(.L.geEnd - .L.ge - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       /* gt */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x00
+       mov r3, #0x01
+       cmp r3, r2
+       swpgt r0, r1, [r0]
+       bl expect_success
+
+       /* Returned 0 (bad) or 1 (ok) */
+       cmp r0, #0
+       beq 7f
+
+       /* !ge */
+       bl reset
+       mov r1, #SWP_MAGIC
+       mov r2, #0x00
+       mov r3, #0x01
+       cmp r2, r3
+       swpgt r0, r1, [r0]
+       bl expect_fail
+
+       /* Don't care about the return of the second one, just print */
+7:
+       movw r0, :lower16:.L.gt
+       movt r0, :upper16:.L.gt
+       ldr r1, =(.L.gtEnd - .L.gt - 1)
+       bl print_result
+       add r6, r6, #1  /* Next test */
+
+       mov r0, r4      /* retval */
+       ldr r7, =SYS_exit
+       swi 0
+
+       .p2align 2
+       .type print_result,%function
+       .code 32
+print_result:
+       push {r4, r5, lr}
+       /* Save the label, size for our result */
+       mov r4, r0
+       mov r5, r1
+
+       movw r0, :lower16:.L.ok
+       movt r0, :upper16:.L.ok
+       ldr r1, =(.L.okEnd - .L.ok - 1)
+       bl print
+       mov r0, r6
+       add r0, #0x30 /* "0" + test number */
+       mov r1, #0x01
+       str r0, [sp]
+       mov r0, sp
+       bl print
+       movw r0, :lower16:.L.swp
+       movt r0, :upper16:.L.swp
+       ldr r1, =(.L.swpEnd - .L.swp - 1)
+       bl print
+       mov r0, r4
+       mov r1, r5
+       bl print
+       movw r0, :lower16:.L.term
+       movt r0, :upper16:.L.term
+       ldr r1, =(.L.termEnd - .L.term - 1)
+       bl print
+
+       pop {r4, r5, lr}
+       bx lr
+
+       .p2align 2
+       .type reset,%function
+       .code 32
+reset:
+       /* Reset sp[0] and return the address used */
+       mov r0, #0x03
+       str r0, [sp]
+       mov r0, sp
+       bx lr
+
+       .p2align 2
+       .type expect_fail,%function
+       .code 32
+expect_fail:
+       /* Just check the stack value */
+       ldr r0, [sp]
+       mov r1, #0x03
+       cmp r0,  r1
+       bne 1f
+
+       /* Success (not swapped) */
+       mov r0, #1
+       bx lr
+
+1:
+       /* Fail (swapped) */
+       /* Print the "not" part */
+       movw r0, :lower16:.L.not
+       movt r0, :upper16:.L.not
+       ldr r1, =(.L.notEnd - .L.not - 1)
+       push {lr}
+       bl print
+       pop {lr}
+
+       /* Failed */
+       add r4, r4, #1
+       mov r0, #0
+       bx lr
+
+       .p2align 2
+       .type expect_success,%function
+       .code 32
+expect_success:
+       /* Old value should be 3 */
+       cmp r0, #0x03
+       beq 1f
+       b 3f
+
+1:
+       /* Check stack value */
+       ldr r0, [sp]
+       mov r1, #SWP_MAGIC
+       cmp r0, r1
+       beq 2f
+       b 3f
+
+2:
+       mov r0, #1
+       bx lr
+
+3:
+       /* Print the "not" part */
+       movw r0, :lower16:.L.not
+       movt r0, :upper16:.L.not
+       ldr r1, =(.L.notEnd - .L.not - 1)
+       push {lr}
+       bl print
+       pop {lr}
+
+       /* Failed */
+       add r4, r4, #1
+       mov r0, #0
+       bx lr
+
+       .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.testheader:
+       .asciz "1..7\n"
+.L.testheaderEnd:
+       .size .L.testheader, .L.testheaderEnd - .L.testheader
+
+.L.not:
+       .asciz "not "
+.L.notEnd:
+       .size .L.not, .L.notEnd - .L.not
+.L.ok:
+       .asciz "ok "
+.L.okEnd:
+       .size .L.ok, .L.okEnd - .L.ok
+.L.swp:
+       .asciz " - swp"
+.L.swpEnd:
+       .size .L.swp, .L.swpEnd - .L.swp
+.L.eq:
+       .asciz "eq"
+.L.eqEnd:
+       .size .L.eq, .L.eqEnd - .L.eq
+.L.cs:
+       .asciz "cs"
+.L.csEnd:
+       .size .L.cs, .L.csEnd - .L.cs
+.L.mi:
+       .asciz "mi"
+.L.miEnd:
+       .size .L.mi, .L.miEnd - .L.mi
+.L.vs:
+       .asciz "vs"
+.L.vsEnd:
+       .size .L.vs, .L.vsEnd - .L.vs
+.L.hi:
+       .asciz "hi"
+.L.hiEnd:
+       .size .L.hi, .L.hiEnd - .L.hi
+.L.ge:
+       .asciz "ge"
+.L.geEnd:
+       .size .L.ge, .L.geEnd - .L.ge
+.L.gt:
+       .asciz "gt"
+.L.gtEnd:
+       .size .L.gt, .L.gtEnd - .L.gt
+.L.term:
+       .asciz "\n"
+.L.termEnd:
+       .size .L.term, .L.termEnd - .L.term
diff --git a/tests/sys/compat32/aarch64/swp_test.sh 
b/tests/sys/compat32/aarch64/swp_test.sh
new file mode 100644
index 000000000000..8edfa43b3e7e
--- /dev/null
+++ b/tests/sys/compat32/aarch64/swp_test.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+scriptdir=$(dirname $(realpath "$0"))
+
+. ${scriptdir}/common.sh
+
+# Ensure emul_swp is enabled just for this test; we'll turn it back off if
+# it wasn't enabled before the test.
+emul_swpval=$(sysctl -n compat.arm.emul_swp)
+sysctl compat.arm.emul_swp=1 >/dev/null
+${scriptdir}/swp_test_impl
+if [ "$emul_swpval" -ne 1 ]; then
+       sysctl compat.arm.emul_swp="$emul_swpval" >/dev/null
+fi
diff --git a/tests/sys/compat32/aarch64/swp_test_impl.S 
b/tests/sys/compat32/aarch64/swp_test_impl.S
new file mode 100644
index 000000000000..0e8047f1a6cf
--- /dev/null
+++ b/tests/sys/compat32/aarch64/swp_test_impl.S
@@ -0,0 +1,216 @@
+/*
+ * 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        SWP_MAGIC       0xffc0
+#define        SWPB_MAGIC      0xc0c0
+
+       .text
+       .file "swp_test.S"
+       .syntax unified
+       .globl main
+       .p2align 2
+       .type main,%function
+       .code 32
+
+main:
+       sub sp, #0x04
+       /* r4 is our failed test counter */
+       mov r4, #0
+
+       movw r0, :lower16:.L.testheader
+       movt r0, :upper16:.L.testheader
+       ldr r1, =(.L.testheaderEnd - .L.testheader - 1)
+       bl print
+
+       /* Target address */
+       mov r0, #0x03
+       str r0, [sp]
+       mov r0, sp
+
+       /* Load value */
+       mov r1, #SWP_MAGIC
+
+       /* swp it */
+       swp r0, r1, [r0]
+
+       /* Old value should be 3 */
+       cmp r0, #0x03
+       bne 1f
+
+       /* Check stack value */
+       ldr r0, [sp]
+       mov r1, #SWP_MAGIC
+       cmp r0, r1
+       bne 1f
+       b 2f
+
+1:
+       /* Denote the failed test */
+       add r4, #1
+       /* "No" part of the notification */
+       movw r0, :lower16:.L.boknot
+       movt r0, :upper16:.L.boknot
+       ldr r1, =(.L.boknotEnd - .L.boknot - 1)
+       bl print
+
+2:
+       /* Notify */
+       movw r0, :lower16:.L.ok1
+       movt r0, :upper16:.L.ok1
+       ldr r1, =(.L.ok1End - .L.ok1 - 1)
+       bl print
+
+       movw r5, #SWPB_MAGIC
+       movt r5, #SWPB_MAGIC
+
+       /* Using r6 as our accumulator */
+       mov r6, sp
+       /* Simplify the loop */
+       sub r6, #1
+3:
+       /* Restore our magic value every time */
+       str r5, [sp]
+       /* Move on to the next byte */
+       add r6, #1
+
+       /* swp it in */
+       mov r0, r6
+       mov r1, #3
+       swpb r0, r1, [r0]
+
+       /* Check the old value */
+       cmp r0, #0xc0
+       bne 6f
+
+       /* Check the stack value */
+       ldrb r0, [r6]
+       cmp r0, #0x03
+       bne 6f
+
+       /* Just loop over the rest of the word and check those values. */
+       mov r1, r6
+       sub r1, sp
+
+       mov r0, #0x00
+4:
+       cmp r0, r1
+       beq 5f
+
+       /* Check the next byte */
+       ldrb r3, [sp, r0]
+       cmp r3, #0xc0
+       bne 6f
+
+5:
+       add r0, #0x01
+       cmp r0, #0x04
+       /* Hit the end, this one succeeded */
+       beq 7f
+
+       /* Move on to the next byte */
+       b 4b
+
+6:
+       /* Denote the failed test */
+       add r4, #1
+       /* "No" part of the notification */
+       movw r0, :lower16:.L.boknot
+       movt r0, :upper16:.L.boknot
+       ldr r1, =(.L.boknotEnd - .L.boknot - 1)
+       bl print
+
+       /* FALLTHROUGH */
+7:
+       /* "ok" part */
+       movw r0, :lower16:.L.bok
+       movt r0, :upper16:.L.bok
+       ldr r1, =(.L.bokEnd - .L.bok - 1)
+       bl print
+
+       /* test number */
+       mov r0, r6
+       sub r0, sp
+       add r0, #0x32 /* "0" + 2 because we start at test 2. */
+       mov r1, #0x01
+       str r0, [sp]
+       mov r0, sp
+       bl print
+
+       /* boklabel */
+       movw r0, :lower16:.L.boklabel
+       movt r0, :upper16:.L.boklabel
+       ldr r1, =(.L.boklabelEnd - .L.boklabel - 1)
+       bl print
+
+       /* index */
+       mov r0, r6
+       sub r0, sp
+       add r0, #0x30 /* "0" */
+       str r0, [sp]
+       mov r0, sp
+       mov r1, #0x01
+       bl print
+
+       /* bokterm */
+       movw r0, :lower16:.L.bokterm
+       movt r0, :upper16:.L.bokterm
+       ldr r1, =(.L.boktermEnd - .L.bokterm - 1)
+       bl print
+
+       mov r0, sp
+       add r0, #0x3
+       cmp r0, r6
+       bne 3b
+
+       mov r0, r4      /* retval */
+       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.testheader:
+       .asciz "1..5\n"
+.L.testheaderEnd:
+       .size .L.testheader, .L.testheaderEnd - .L.testheader
+
+       /* Maybe not the most efficient, but meh. */
+.L.ok1:
+       .asciz "ok 1 - swp\n"
+.L.ok1End:
+       .size .L.ok1, .L.ok1End - .L.ok1
+
+.L.boknot:
+       .asciz "not "
+.L.boknotEnd:
+       .size .L.boknot, .L.boknotEnd - .L.boknot
+.L.bok:
+       .asciz "ok "
+.L.bokEnd:
+       .size .L.bok, .L.bokEnd - .L.bok
+.L.boklabel:
+       .asciz " - swpb["
+.L.boklabelEnd:
+       .size .L.boklabel, .L.boklabelEnd - .L.boklabel
+.L.bokterm:
+       .asciz "]\n"
+.L.boktermEnd:
+       .size .L.bokterm, .L.boktermEnd - .L.bokterm
diff --git a/tools/regression/compat32/aarch64/Makefile 
b/tools/regression/compat32/aarch64/Makefile
new file mode 100644
index 000000000000..34428a58caa1
--- /dev/null
+++ b/tools/regression/compat32/aarch64/Makefile
@@ -0,0 +1,4 @@
+ACFLAGS= -target armv7-unknown-freebsd${OS_REVISION} -nostdlib -Wl,-e -Wl,main 
-static -mhwdiv=arm
+
+swp_test_impl: swp_test_impl.S
+       ${CC} ${ACFLAGS} -o ${.TARGET} ${.ALLSRC}
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)
*** 249 LINES SKIPPED ***

Reply via email to