Commit 5d09f61e authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'linux_kselftest-nolibc-6.8-rc1' of...

Merge tag 'linux_kselftest-nolibc-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull nolibc updates from Shuah Khan:

 - Support for PIC mode on MIPS

 - Support for getrlimit()/setrlimit()

 - Replace some custom declarations with UAPI includes

 - A new script "run-tests.sh" to run the testsuite over different
   architectures and configurations

 - A few non-functional code cleanups

 - Minor improvements to nolibc-test, primarily to support the test
   script

* tag 'linux_kselftest-nolibc-6.8-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest: (22 commits)
  selftests/nolibc: disable coredump via setrlimit
  tools/nolibc: add support for getrlimit/setrlimit
  tools/nolibc: drop custom definition of struct rusage
  tools/nolibc: drop duplicated testcase ioctl_tiocinq
  tools/nolibc: annotate va_list printf formats
  selftests/nolibc: make result alignment more robust
  tools/nolibc: mips: add support for PIC
  selftests/nolibc: run-tests.sh: enable testing via qemu-user
  selftests/nolibc: introduce QEMU_ARCH_USER
  selftests/nolibc: fix testcase status alignment
  selftests/nolibc: add configuration for mipso32be
  selftests/nolibc: extraconfig support
  selftests/nolibc: explicitly specify ABI for MIPS
  selftests/nolibc: use XARCH for MIPS
  tools/nolibc: move MIPS ABI validation into arch-mips.h
  tools/nolibc: error out on unsupported architecture
  selftests/nolibc: add script to run testsuite
  selftests/nolibc: support out-of-tree builds
  selftests/nolibc: anchor paths in $(srcdir) if possible
  selftests/nolibc: use EFI -bios for LoongArch qemu
  ...
parents a7e4c6cf d543d9dd
......@@ -10,6 +10,10 @@
#include "compiler.h"
#include "crt.h"
#if !defined(_ABIO32)
#error Unsupported MIPS ABI
#endif
/* Syscalls for MIPS ABI O32 :
* - WARNING! there's always a delayed slot!
* - WARNING again, the syntax is different, registers take a '$' and numbers
......@@ -180,8 +184,13 @@ void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_
__asm__ volatile (
".set push\n"
".set noreorder\n"
".option pic0\n"
"bal 1f\n" /* prime $ra for .cpload */
"nop\n"
"1:\n"
".cpload $ra\n"
"move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
"addiu $sp, $sp, -4\n" /* space for .cprestore to store $gp */
".cprestore 0\n"
"li $t0, -8\n"
"and $sp, $sp, $t0\n" /* $sp must be 8-byte aligned */
"addiu $sp, $sp, -16\n" /* the callee expects to save a0..a3 there */
......
......@@ -23,7 +23,7 @@
#include "arch-arm.h"
#elif defined(__aarch64__)
#include "arch-aarch64.h"
#elif defined(__mips__) && defined(_ABIO32)
#elif defined(__mips__)
#include "arch-mips.h"
#elif defined(__powerpc__)
#include "arch-powerpc.h"
......@@ -33,6 +33,8 @@
#include "arch-s390.h"
#elif defined(__loongarch__)
#include "arch-loongarch.h"
#else
#error Unsupported Architecture
#endif
#endif /* _NOLIBC_ARCH_H */
......@@ -212,7 +212,7 @@ char *fgets(char *s, int size, FILE *stream)
* - %s
* - unknown modifiers are ignored.
*/
static __attribute__((unused))
static __attribute__((unused, format(printf, 2, 0)))
int vfprintf(FILE *stream, const char *fmt, va_list args)
{
char escape, lpref, c;
......@@ -318,7 +318,7 @@ int vfprintf(FILE *stream, const char *fmt, va_list args)
return written;
}
static __attribute__((unused))
static __attribute__((unused, format(printf, 1, 0)))
int vprintf(const char *fmt, va_list args)
{
return vfprintf(stdout, fmt, args);
......
......@@ -21,6 +21,7 @@
#include <linux/fcntl.h> /* for O_* and AT_* */
#include <linux/stat.h> /* for statx() */
#include <linux/prctl.h>
#include <linux/resource.h>
#include "arch.h"
#include "errno.h"
......@@ -898,6 +899,43 @@ int reboot(int cmd)
}
/*
* int getrlimit(int resource, struct rlimit *rlim);
* int setrlimit(int resource, const struct rlimit *rlim);
*/
static __attribute__((unused))
int sys_prlimit64(pid_t pid, int resource,
const struct rlimit64 *new_limit, struct rlimit64 *old_limit)
{
return my_syscall4(__NR_prlimit64, pid, resource, new_limit, old_limit);
}
static __attribute__((unused))
int getrlimit(int resource, struct rlimit *rlim)
{
struct rlimit64 rlim64;
int ret;
ret = __sysret(sys_prlimit64(0, resource, NULL, &rlim64));
rlim->rlim_cur = rlim64.rlim_cur;
rlim->rlim_max = rlim64.rlim_max;
return ret;
}
static __attribute__((unused))
int setrlimit(int resource, const struct rlimit *rlim)
{
struct rlimit64 rlim64 = {
.rlim_cur = rlim->rlim_cur,
.rlim_max = rlim->rlim_max,
};
return __sysret(sys_prlimit64(0, resource, &rlim64, NULL));
}
/*
* int sched_yield(void);
*/
......
......@@ -12,6 +12,8 @@
#include <linux/reboot.h> /* for LINUX_REBOOT_* */
#include <linux/stat.h>
#include <linux/time.h>
#include <linux/wait.h>
#include <linux/resource.h>
/* Only the generic macros and types may be defined here. The arch-specific
......@@ -108,9 +110,6 @@
#define WTERMSIG(status) ((status) & 0x7f)
#define WIFSIGNALED(status) ((status) - 1 < 0xff)
/* waitpid() flags */
#define WNOHANG 1
/* standard exit() codes */
#define EXIT_SUCCESS 0
#define EXIT_FAILURE 1
......@@ -180,26 +179,6 @@ struct linux_dirent64 {
char d_name[];
};
/* needed by wait4() */
struct rusage {
struct timeval ru_utime;
struct timeval ru_stime;
long ru_maxrss;
long ru_ixrss;
long ru_idrss;
long ru_isrss;
long ru_minflt;
long ru_majflt;
long ru_nswap;
long ru_inblock;
long ru_oublock;
long ru_msgsnd;
long ru_msgrcv;
long ru_nsignals;
long ru_nvcsw;
long ru_nivcsw;
};
/* The format of the struct as returned by the libc to the application, which
* significantly differs from the format returned by the stat() syscall flavours.
*/
......
......@@ -3,4 +3,5 @@
/libc-test
/nolibc-test
/run.out
/run.out.*
/sysroot/
# SPDX-License-Identifier: GPL-2.0
# Makefile for nolibc tests
include ../../../scripts/Makefile.include
include ../../../scripts/utilities.mak
# We need this for the "cc-option" macro.
include ../../../build/Build.include
ifneq ($(O),)
ifneq ($(call is-absolute,$(O)),y)
$(error Only absolute O= parameters are supported)
endif
endif
# we're in ".../tools/testing/selftests/nolibc"
ifeq ($(srctree),)
srctree := $(patsubst %/tools/testing/selftests/,%,$(dir $(CURDIR)))
......@@ -14,6 +21,8 @@ include $(srctree)/scripts/subarch.include
ARCH = $(SUBARCH)
endif
objtree ?= $(srctree)
# XARCH extends the kernel's ARCH with a few variants of the same
# architecture that only differ by the configuration, the toolchain
# and the Qemu program used. It is copied as-is into ARCH except for
......@@ -31,12 +40,15 @@ endif
# configure default variants for target kernel supported architectures
XARCH_powerpc = ppc
XARCH_mips = mips32le
XARCH = $(or $(XARCH_$(ARCH)),$(ARCH))
# map from user input variants to their kernel supported architectures
ARCH_ppc = powerpc
ARCH_ppc64 = powerpc
ARCH_ppc64le = powerpc
ARCH_mips32le = mips
ARCH_mips32be = mips
ARCH := $(or $(ARCH_$(XARCH)),$(XARCH))
# kernel image names by architecture
......@@ -45,14 +57,15 @@ IMAGE_x86_64 = arch/x86/boot/bzImage
IMAGE_x86 = arch/x86/boot/bzImage
IMAGE_arm64 = arch/arm64/boot/Image
IMAGE_arm = arch/arm/boot/zImage
IMAGE_mips = vmlinuz
IMAGE_mips32le = vmlinuz
IMAGE_mips32be = vmlinuz
IMAGE_ppc = vmlinux
IMAGE_ppc64 = vmlinux
IMAGE_ppc64le = arch/powerpc/boot/zImage
IMAGE_riscv = arch/riscv/boot/Image
IMAGE_s390 = arch/s390/boot/bzImage
IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi
IMAGE = $(IMAGE_$(XARCH))
IMAGE = $(objtree)/$(IMAGE_$(XARCH))
IMAGE_NAME = $(notdir $(IMAGE))
# default kernel configurations that appear to be usable
......@@ -61,7 +74,8 @@ DEFCONFIG_x86_64 = defconfig
DEFCONFIG_x86 = defconfig
DEFCONFIG_arm64 = defconfig
DEFCONFIG_arm = multi_v7_defconfig
DEFCONFIG_mips = malta_defconfig
DEFCONFIG_mips32le = malta_defconfig
DEFCONFIG_mips32be = malta_defconfig
DEFCONFIG_ppc = pmac32_defconfig
DEFCONFIG_ppc64 = powernv_be_defconfig
DEFCONFIG_ppc64le = powernv_defconfig
......@@ -70,6 +84,9 @@ DEFCONFIG_s390 = defconfig
DEFCONFIG_loongarch = defconfig
DEFCONFIG = $(DEFCONFIG_$(XARCH))
EXTRACONFIG_mips32be = -d CONFIG_CPU_LITTLE_ENDIAN -e CONFIG_CPU_BIG_ENDIAN
EXTRACONFIG = $(EXTRACONFIG_$(XARCH))
# optional tests to run (default = all)
TEST =
......@@ -79,7 +96,8 @@ QEMU_ARCH_x86_64 = x86_64
QEMU_ARCH_x86 = x86_64
QEMU_ARCH_arm64 = aarch64
QEMU_ARCH_arm = arm
QEMU_ARCH_mips = mipsel # works with malta_defconfig
QEMU_ARCH_mips32le = mipsel # works with malta_defconfig
QEMU_ARCH_mips32be = mips
QEMU_ARCH_ppc = ppc
QEMU_ARCH_ppc64 = ppc64
QEMU_ARCH_ppc64le = ppc64
......@@ -88,20 +106,31 @@ QEMU_ARCH_s390 = s390x
QEMU_ARCH_loongarch = loongarch64
QEMU_ARCH = $(QEMU_ARCH_$(XARCH))
QEMU_ARCH_USER_ppc64le = ppc64le
QEMU_ARCH_USER = $(or $(QEMU_ARCH_USER_$(XARCH)),$(QEMU_ARCH_$(XARCH)))
QEMU_BIOS_DIR = /usr/share/edk2/
QEMU_BIOS_loongarch = $(QEMU_BIOS_DIR)/loongarch64/OVMF_CODE.fd
ifneq ($(QEMU_BIOS_$(XARCH)),)
QEMU_ARGS_BIOS = -bios $(QEMU_BIOS_$(XARCH))
endif
# QEMU_ARGS : some arch-specific args to pass to qemu
QEMU_ARGS_i386 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_x86_64 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_x86 = -M pc -append "console=ttyS0,9600 i8042.noaux panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_arm64 = -M virt -cpu cortex-a53 -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_arm = -M virt -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_mips = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_mips32le = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_mips32be = -M malta -append "panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_ppc = -M g3beige -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_ppc64 = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_ppc64le = -M powernv -append "console=hvc0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_riscv = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_s390 = -M s390-ccw-virtio -m 1G -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
QEMU_ARGS = $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_EXTRA)
QEMU_ARGS = $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
# OUTPUT is only set when run from the main makefile, otherwise
# it defaults to this nolibc directory.
......@@ -118,7 +147,8 @@ CFLAGS_ppc = -m32 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
CFLAGS_ppc64 = -m64 -mbig-endian -mno-vsx $(call cc-option,-mmultiple)
CFLAGS_ppc64le = -m64 -mlittle-endian -mno-vsx $(call cc-option,-mabi=elfv2)
CFLAGS_s390 = -m64
CFLAGS_mips = -EL
CFLAGS_mips32le = -EL -mabi=32 -fPIC
CFLAGS_mips32be = -EB -mabi=32
CFLAGS_STACKPROTECTOR ?= $(call cc-option,-mstack-protector-guard=global $(call cc-option,-fstack-protector-all))
CFLAGS ?= -Os -fno-ident -fno-asynchronous-unwind-tables -std=c89 -W -Wall -Wextra \
$(call cc-option,-fno-stack-protector) \
......@@ -167,7 +197,8 @@ sysroot: sysroot/$(ARCH)/include
sysroot/$(ARCH)/include:
$(Q)rm -rf sysroot/$(ARCH) sysroot/sysroot
$(QUIET_MKDIR)mkdir -p sysroot
$(Q)$(MAKE) -C ../../../include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone
$(Q)$(MAKE) -C $(srctree) outputmakefile
$(Q)$(MAKE) -C $(srctree)/tools/include/nolibc ARCH=$(ARCH) OUTPUT=$(CURDIR)/sysroot/ headers_standalone
$(Q)mv sysroot/sysroot sysroot/$(ARCH)
ifneq ($(NOLIBC_SYSROOT),0)
......@@ -177,7 +208,7 @@ nolibc-test: nolibc-test.c nolibc-test-linkage.c sysroot/$(ARCH)/include
else
nolibc-test: nolibc-test.c nolibc-test-linkage.c
$(QUIET_CC)$(CC) $(CFLAGS) $(LDFLAGS) -o $@ \
-nostdlib -static -include ../../../include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c -lgcc
-nostdlib -static -include $(srctree)/tools/include/nolibc/nolibc.h nolibc-test.c nolibc-test-linkage.c -lgcc
endif
libc-test: nolibc-test.c nolibc-test-linkage.c
......@@ -195,11 +226,11 @@ run-nolibc-test: nolibc-test
# qemu user-land test
run-user: nolibc-test
$(Q)qemu-$(QEMU_ARCH) ./nolibc-test > "$(CURDIR)/run.out" || :
$(Q)qemu-$(QEMU_ARCH_USER) ./nolibc-test > "$(CURDIR)/run.out" || :
$(Q)$(REPORT) $(CURDIR)/run.out
initramfs.cpio: kernel nolibc-test
$(QUIET_GEN)echo 'file /init nolibc-test 755 0 0' | $(srctree)/usr/gen_init_cpio - > initramfs.cpio
$(QUIET_GEN)echo 'file /init nolibc-test 755 0 0' | $(objtree)/usr/gen_init_cpio - > initramfs.cpio
initramfs: nolibc-test
$(QUIET_MKDIR)mkdir -p initramfs
......@@ -208,21 +239,25 @@ initramfs: nolibc-test
defconfig:
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) mrproper $(DEFCONFIG) prepare
$(Q)if [ -n "$(EXTRACONFIG)" ]; then \
$(srctree)/scripts/config --file $(objtree)/.config $(EXTRACONFIG); \
$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) olddefconfig < /dev/null; \
fi
kernel:
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME)
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) < /dev/null
kernel-standalone: initramfs
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs
$(Q)$(MAKE) -C $(srctree) ARCH=$(ARCH) CC=$(CC) CROSS_COMPILE=$(CROSS_COMPILE) $(IMAGE_NAME) CONFIG_INITRAMFS_SOURCE=$(CURDIR)/initramfs < /dev/null
# run the tests after building the kernel
run: kernel initramfs.cpio
$(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -initrd initramfs.cpio -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
$(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(IMAGE)" -initrd initramfs.cpio -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
$(Q)$(REPORT) $(CURDIR)/run.out
# re-run the tests from an existing kernel
rerun:
$(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(srctree)/$(IMAGE)" -initrd initramfs.cpio -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
$(Q)qemu-system-$(QEMU_ARCH) -display none -no-reboot -kernel "$(IMAGE)" -initrd initramfs.cpio -serial stdio $(QEMU_ARGS) > "$(CURDIR)/run.out"
$(Q)$(REPORT) $(CURDIR)/run.out
# report with existing test log
......
......@@ -22,6 +22,7 @@
#include <sys/mount.h>
#include <sys/prctl.h>
#include <sys/reboot.h>
#include <sys/resource.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/sysmacros.h>
......@@ -130,11 +131,17 @@ static const char *errorname(int err)
}
}
static void putcharn(char c, size_t n)
static void align_result(size_t llen)
{
char buf[64];
const size_t align = 64;
char buf[align];
size_t n;
memset(buf, c, n);
if (llen >= align)
return;
n = align - llen;
memset(buf, ' ', n);
buf[n] = '\0';
fputs(buf, stdout);
}
......@@ -150,14 +157,13 @@ static void result(int llen, enum RESULT r)
const char *msg;
if (r == OK)
msg = " [OK]";
msg = " [OK]";
else if (r == SKIPPED)
msg = "[SKIPPED]";
else
msg = "[FAIL]";
msg = " [FAIL]";
if (llen < 64)
putcharn(' ', 64 - llen);
align_result(llen);
puts(msg);
}
......@@ -834,6 +840,33 @@ int test_pipe(void)
return !!memcmp(buf, msg, len);
}
int test_rlimit(void)
{
struct rlimit rlim = {
.rlim_cur = 1 << 20,
.rlim_max = 1 << 21,
};
int ret;
ret = setrlimit(RLIMIT_CORE, &rlim);
if (ret)
return -1;
rlim.rlim_cur = 0;
rlim.rlim_max = 0;
ret = getrlimit(RLIMIT_CORE, &rlim);
if (ret)
return -1;
if (rlim.rlim_cur != 1 << 20)
return -1;
if (rlim.rlim_max != 1 << 21)
return -1;
return 0;
}
/* Run syscall tests between IDs <min> and <max>.
* Return 0 on success, non-zero on failure.
......@@ -905,7 +938,6 @@ int run_syscall(int min, int max)
CASE_TEST(gettimeofday_tv_tz);EXPECT_SYSZR(1, gettimeofday(&tv, &tz)); break;
CASE_TEST(getpagesize); EXPECT_SYSZR(1, test_getpagesize()); break;
CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
CASE_TEST(ioctl_tiocinq); EXPECT_SYSZR(1, ioctl(0, TIOCINQ, &tmp)); break;
CASE_TEST(link_root1); EXPECT_SYSER(1, link("/", "/"), -1, EEXIST); break;
CASE_TEST(link_blah); EXPECT_SYSER(1, link("/proc/self/blah", "/blah"), -1, ENOENT); break;
CASE_TEST(link_dir); EXPECT_SYSER(euid0, link("/", "/blah"), -1, EPERM); break;
......@@ -924,6 +956,7 @@ int run_syscall(int min, int max)
CASE_TEST(poll_fault); EXPECT_SYSER(1, poll(NULL, 1, 0), -1, EFAULT); break;
CASE_TEST(prctl); EXPECT_SYSER(1, prctl(PR_SET_NAME, (unsigned long)NULL, 0, 0, 0), -1, EFAULT); break;
CASE_TEST(read_badf); EXPECT_SYSER(1, read(-1, &tmp, 1), -1, EBADF); break;
CASE_TEST(rlimit); EXPECT_SYSZR(1, test_rlimit()); break;
CASE_TEST(rmdir_blah); EXPECT_SYSER(1, rmdir("/blah"), -1, ENOENT); break;
CASE_TEST(sched_yield); EXPECT_SYSZR(1, sched_yield()); break;
CASE_TEST(select_null); EXPECT_SYSZR(1, ({ struct timeval tv = { 0 }; select(0, NULL, NULL, NULL, &tv); })); break;
......@@ -1133,6 +1166,7 @@ static int run_protection(int min __attribute__((unused)),
{
pid_t pid;
int llen = 0, status;
struct rlimit rlimit = { 0, 0 };
llen += printf("0 -fstackprotector ");
......@@ -1164,6 +1198,7 @@ static int run_protection(int min __attribute__((unused)),
close(STDERR_FILENO);
prctl(PR_SET_DUMPABLE, 0, 0, 0, 0);
setrlimit(RLIMIT_CORE, &rlimit);
smash_stack();
return 1;
......
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Test runner for nolibc tests
set -e
trap 'echo Aborting...' 'ERR'
crosstool_version=13.2.0
hostarch=x86_64
nproc=$(( $(nproc) + 2))
cache_dir="${XDG_CACHE_HOME:-"$HOME"/.cache}"
download_location="${cache_dir}/crosstools/"
build_location="$(realpath "${cache_dir}"/nolibc-tests/)"
perform_download=0
test_mode=system
archs="i386 x86_64 arm64 arm mips32le mips32be ppc ppc64 ppc64le riscv s390 loongarch"
TEMP=$(getopt -o 'j:d:c:b:a:m:ph' -n "$0" -- "$@")
eval set -- "$TEMP"
unset TEMP
print_usage() {
cat <<EOF
Run nolibc testsuite for multiple architectures with crosstools
Usage:
$0 [options] <architectures>
Known architectures:
${archs}
Options:
-j [N] Allow N jobs at once (default: ${nproc})
-p Allow download of toolchains
-d [DIR] Download location for toolchains (default: ${download_location})
-c [VERSION] Version of toolchains to use (default: ${crosstool_version})
-a [ARCH] Host architecture of toolchains to use (default: ${hostarch})
-b [DIR] Build location (default: ${build_location})
-m [MODE] Test mode user/system (default: ${test_mode})
EOF
}
while true; do
case "$1" in
'-j')
nproc="$2"
shift 2; continue ;;
'-p')
perform_download=1
shift; continue ;;
'-d')
download_location="$2"
shift 2; continue ;;
'-c')
crosstool_version="$2"
shift 2; continue ;;
'-a')
hostarch="$2"
shift 2; continue ;;
'-b')
build_location="$(realpath "$2")"
shift 2; continue ;;
'-m')
test_mode="$2"
shift 2; continue ;;
'-h')
print_usage
exit 0
;;
'--')
shift; break ;;
*)
echo 'Internal error!' >&2; exit 1 ;;
esac
done
if [[ -n "$*" ]]; then
archs="$*"
fi
crosstool_arch() {
case "$1" in
arm64) echo aarch64;;
ppc) echo powerpc;;
ppc64) echo powerpc64;;
ppc64le) echo powerpc64;;
riscv) echo riscv64;;
loongarch) echo loongarch64;;
mips*) echo mips;;
*) echo "$1";;
esac
}
crosstool_abi() {
case "$1" in
arm) echo linux-gnueabi;;
*) echo linux;;
esac
}
download_crosstool() {
arch="$(crosstool_arch "$1")"
abi="$(crosstool_abi "$1")"
archive_name="${hostarch}-gcc-${crosstool_version}-nolibc-${arch}-${abi}.tar.gz"
url="https://mirrors.edge.kernel.org/pub/tools/crosstool/files/bin/${hostarch}/${crosstool_version}/${archive_name}"
archive="${download_location}${archive_name}"
stamp="${archive}.stamp"
[ -f "${stamp}" ] && return
echo "Downloading crosstools ${arch} ${crosstool_version}"
mkdir -p "${download_location}"
curl -o "${archive}" --fail --continue-at - "${url}"
tar -C "${download_location}" -xf "${archive}"
touch "${stamp}"
}
# capture command output, print it on failure
# mimics chronic(1) from moreutils
function swallow_output() {
if ! OUTPUT="$("$@" 2>&1)"; then
echo "$OUTPUT"
return 1
fi
return 0
}
test_arch() {
arch=$1
ct_arch=$(crosstool_arch "$arch")
ct_abi=$(crosstool_abi "$1")
cross_compile=$(realpath "${download_location}gcc-${crosstool_version}-nolibc/${ct_arch}-${ct_abi}/bin/${ct_arch}-${ct_abi}-")
build_dir="${build_location}/${arch}"
MAKE=(make -j"${nproc}" XARCH="${arch}" CROSS_COMPILE="${cross_compile}" O="${build_dir}")
mkdir -p "$build_dir"
if [ "$test_mode" = "system" ] && [ ! -f "${build_dir}/.config" ]; then
swallow_output "${MAKE[@]}" defconfig
fi
case "$test_mode" in
'system')
test_target=run
;;
'user')
test_target=run-user
;;
*)
echo "Unknown mode $test_mode"
exit 1
esac
printf '%-15s' "$arch:"
swallow_output "${MAKE[@]}" "$test_target" V=1
cp run.out run.out."${arch}"
"${MAKE[@]}" report | grep passed
}
if [ "$perform_download" -ne 0 ]; then
for arch in $archs; do
download_crosstool "$arch"
done
fi
for arch in $archs; do
test_arch "$arch"
done
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment