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 @@ -1,1174 +1,1176 @@ # $FreeBSD$ # # Please see the file src/etc/mtree/README before making changes to this file. # /set type=dir uname=root gname=wheel mode=0755 tags=package=tests . bin cat .. chflags .. chmod .. cp .. date .. dd .. echo .. expr .. ln .. ls .. mkdir .. mv .. pax .. pkill .. pwait .. rm .. rmdir .. sh builtins .. errors .. execution .. expansion .. invocation .. parameters .. parser .. set-e .. .. sleep .. test .. timeout .. .. cddl lib .. sbin .. usr.bin ctfconvert .. ztest .. .. usr.sbin dtrace common aggs .. arithmetic .. arrays .. assocs .. begin .. bitfields .. buffering .. builtinvar .. cg .. clauses .. cpc .. decls .. drops .. dtraceUtil .. end .. env .. enum .. error .. exit .. fbtprovider .. funcs .. grammar .. include .. inline .. io .. ip .. java_api .. json .. lexer .. llquantize .. mdb .. mib .. misc .. multiaggs .. offsetof .. operators .. pid .. plockstat .. pointers .. pragma .. predicates .. preprocessor .. print .. printa .. printf .. privs .. probes .. proc .. profile-n .. providers .. raise .. rates .. safety .. scalars .. sched .. scripting .. sdt .. sizeof .. speculation .. stability .. stack .. stackdepth .. stop .. strlen .. strtoll .. struct .. sugar .. syscall .. sysevent .. tick-n .. trace .. tracemem .. translators .. typedef .. types .. uctf .. union .. usdt .. ustack .. vars .. version .. .. i386 arrays .. funcs .. pid .. ustack .. .. amd64 arrays .. kinst .. .. .. zfsd .. .. .. etc rc.d .. .. examples .. games .. gnu lib .. usr.bin diff .. .. .. lib atf libatf-c detail .. .. libatf-c++ detail .. .. test-programs .. .. csu dynamic .. dynamiclib .. static .. .. googletest gmock .. gmock_main .. gtest .. gtest_main .. .. libarchive .. libbe .. libc c063 .. db .. gen execve .. posix_spawn .. .. hash data .. .. iconv .. inet .. locale .. net getaddrinfo data .. .. .. nss .. regex data .. .. resolv .. rpc .. ssp .. setjmp .. stdio .. stdlib .. string .. sys .. time .. tls dso .. .. termios .. ttyio .. .. libcam .. libcasper services cap_dns .. cap_grp .. cap_pwd .. cap_sysctl .. .. .. libcrypt .. libdevdctl .. libexecinfo .. libkvm .. libmp .. libnv .. libproc .. libregex data .. .. librt .. libsbuf .. libsysdecode .. libthr dlopen .. .. libutil .. libxo .. msun .. .. libexec atf atf-check .. atf-pytest-wrapper .. atf-sh .. .. rc .. rtld-elf .. tftpd .. .. sbin bectl .. dhclient .. devd .. growfs .. ifconfig .. md5 .. mdconfig .. newfs_msdos .. nvmecontrol .. pfctl files .. .. ping .. route .. sysctl .. .. secure lib .. libexec .. usr.bin .. usr.sbin .. .. share examples tests atf .. googletest .. plain .. tap .. .. .. zoneinfo .. .. sys acl .. aio .. audit .. auditpipe .. capsicum .. cddl zfs bin .. include .. tests acl cifs .. nontrivial .. trivial .. .. atime .. bootfs .. cache .. cachefile .. clean_mirror .. cli_root zfs_upgrade .. zfs_promote .. zfs_clone .. zfs_property .. zfs_destroy .. zpool_create .. zpool_history .. zpool_expand .. zpool_remove .. zfs_mount .. zfs_unshare .. zdb .. zpool_online .. zpool_get .. zpool_export .. zfs_copies .. zfs_get .. zfs .. zpool_clear .. zpool_import blockfiles .. .. zpool .. zpool_offline .. zpool_replace .. zfs_rollback .. zpool_set .. zfs_send .. zfs_set .. zpool_detach .. zfs_diff .. zpool_scrub .. zfs_inherit .. zfs_snapshot .. zfs_share .. zpool_destroy .. zpool_status .. zfs_unmount .. zfs_receive .. zfs_create .. zpool_upgrade blockfiles .. .. zpool_add .. zfs_rename .. zpool_attach .. zfs_reservation .. .. cli_user misc .. zfs_list .. zpool_iostat .. zpool_list .. .. compression .. ctime .. delegate .. devices .. exec .. grow_pool .. grow_replicas .. history .. hotplug .. hotspare .. inheritance .. interop .. inuse .. iscsi .. large_files .. largest_pool .. link_count .. migration .. mmap .. mount .. mv_files .. nestedfs .. no_space .. online_offline .. pool_names .. poolversion .. quota .. redundancy .. refquota .. refreserv .. rename_dirs .. replacement .. reservation .. rootpool .. rsend .. scrub_mirror .. slog .. snapshot .. snapused .. sparse .. threadsappend .. truncate .. txg_integrity .. userquota .. utils_test .. write_dirs .. xattr .. zfsd .. zil .. zinject .. zones .. zvol zvol_ENOSPC .. zvol_cli .. zvol_misc .. zvol_swap .. .. zvol_thrash .. .. .. .. + compat32 + .. devrandom .. dtrace .. fifo .. file .. fs fusefs .. tarfs .. tmpfs .. .. geom class concat .. eli .. gate .. gpt .. mirror .. multipath .. nop .. part .. raid3 .. shsec .. stripe .. uzip etalon .. .. .. .. kern acct .. execve .. pipe .. .. kqueue libkqueue .. .. mac bsdextended .. portacl .. .. mqueue .. net if_ovpn .. routing .. .. netgraph .. netinet .. netinet6 frag6 .. .. netipsec tunnel .. .. netlink .. netmap .. netpfil common .. ipfw .. pf ioctl .. .. .. opencrypto .. pjdfstest chflags .. chmod .. chown .. ftruncate .. granular .. link .. mkdir .. mkfifo .. mknod .. open .. rename .. rmdir .. symlink .. truncate .. unlink .. utimensat .. .. posixshm .. sys .. vfs .. vm .. vmm .. .. usr.bin apply .. awk bugs-fixed .. netbsd .. .. basename .. bintrans .. bmake archives fmt_44bsd .. fmt_44bsd_mod .. fmt_oldbsd .. .. basic t0 .. t1 .. t2 .. t3 .. .. execution ellipsis .. empty .. joberr .. plus .. .. shell builtin .. meta .. path .. path_select .. replace .. select .. .. suffixes basic .. src_wild1 .. src_wild2 .. .. syntax directive-t0 .. enl .. funny-targets .. semi .. .. sysmk t0 2 1 .. .. mk .. .. t1 2 1 .. .. mk .. .. t2 2 1 .. .. mk .. .. .. variables modifier_M .. modifier_t .. opt_V .. t0 .. .. .. bsdcat .. calendar .. cmp .. compress .. cpio .. col .. comm .. csplit .. cut .. dc .. diff .. diff3 .. dirname .. du .. file2c .. file .. find .. fold .. getconf .. gh-bc .. grep .. gzip .. head .. hexdump .. ident .. indent .. join .. jot .. lastcomm .. limits .. locale .. m4 .. mkimg .. mktemp .. ncal .. opensm .. patch .. pr .. printf .. procstat .. renice .. rs .. sdiff .. sed regress.multitest.out .. .. seq .. soelim .. sort .. split .. stat .. tail .. tar .. tftp .. tr .. truncate .. tsort .. units .. unifdef .. uniq .. vmstat .. wc .. xargs .. xinstall .. xo .. yacc yacc .. .. .. usr.sbin chown .. daemon .. etcupdate .. extattr .. fstyp .. jail .. makefs .. mixer .. newsyslog .. nmtree .. praudit .. pw .. rpcbind .. sa .. .. .. # vim: set expandtab ts=4 sw=4: diff --git a/tests/sys/Makefile b/tests/sys/Makefile index 8f83445f9d91..3e9a30105a1d 100644 --- a/tests/sys/Makefile +++ b/tests/sys/Makefile @@ -1,55 +1,56 @@ # $FreeBSD$ .include TESTSDIR= ${TESTSBASE}/sys TESTS_SUBDIRS+= acl TESTS_SUBDIRS+= aio TESTS_SUBDIRS+= ${_audit} TESTS_SUBDIRS+= auditpipe TESTS_SUBDIRS+= capsicum TESTS_SUBDIRS+= ${_cddl} +TESTS_SUBDIRS+= compat32 TESTS_SUBDIRS+= devrandom TESTS_SUBDIRS+= fifo TESTS_SUBDIRS+= file TESTS_SUBDIRS+= fs TESTS_SUBDIRS+= geom TESTS_SUBDIRS+= kern TESTS_SUBDIRS+= kqueue TESTS_SUBDIRS+= mac TESTS_SUBDIRS+= mqueue TESTS_SUBDIRS+= net TESTS_SUBDIRS+= ${_netgraph} TESTS_SUBDIRS+= netinet TESTS_SUBDIRS+= netinet6 TESTS_SUBDIRS+= netipsec TESTS_SUBDIRS+= netlink TESTS_SUBDIRS+= netmap TESTS_SUBDIRS+= netpfil TESTS_SUBDIRS+= opencrypto TESTS_SUBDIRS+= posixshm TESTS_SUBDIRS+= ses TESTS_SUBDIRS+= sys TESTS_SUBDIRS+= vfs TESTS_SUBDIRS+= vm TESTS_SUBDIRS+= vmm .if ${MK_AUDIT} != "no" _audit= audit .endif .if ${MK_CDDL} != "no" _cddl= cddl .endif .if ${MK_NETGRAPH} != "no" _netgraph= netgraph .endif # Items not integrated into kyua runs by default SUBDIR+= pjdfstest SUBDIR+= common .include 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 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 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 '\'; 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 + +#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 + +#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 + +#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