mirror of
https://github.com/torvalds/linux.git
synced 2026-09-22 20:54:03 +02:00
tools/nolibc: Add support for SPARC
Add support for 32bit and 64bit SPARC to nolibc. Signed-off-by: Thomas Weißschuh <linux@weissschuh.net> Acked-by: Willy Tarreau <w@1wt.eu> Tested-by: Sebastian Andrzej Siewior <sebastian@breakpoint.cc> # UltraSparc T4 (Niagara4) Link: https://lore.kernel.org/lkml/20250322-nolibc-sparc-v2-1-89af018c6296@weissschuh.net/
This commit is contained in:
parent
fd293cb81a
commit
8e1930296f
191
tools/include/nolibc/arch-sparc.h
Normal file
191
tools/include/nolibc/arch-sparc.h
Normal file
|
|
@ -0,0 +1,191 @@
|
||||||
|
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
||||||
|
/*
|
||||||
|
* SPARC (32bit and 64bit) specific definitions for NOLIBC
|
||||||
|
* Copyright (C) 2025 Thomas Weißschuh <linux@weissschuh.net>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef _NOLIBC_ARCH_SPARC_H
|
||||||
|
#define _NOLIBC_ARCH_SPARC_H
|
||||||
|
|
||||||
|
#include <linux/unistd.h>
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "crt.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Syscalls for SPARC:
|
||||||
|
* - registers are native word size
|
||||||
|
* - syscall number is passed in g1
|
||||||
|
* - arguments are in o0-o5
|
||||||
|
* - the system call is performed by calling a trap instruction
|
||||||
|
* - syscall return value is in o0
|
||||||
|
* - syscall error flag is in the carry bit of the processor status register
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __arch64__
|
||||||
|
|
||||||
|
#define _NOLIBC_SYSCALL "t 0x6d\n" \
|
||||||
|
"bcs,a %%xcc, 1f\n" \
|
||||||
|
"sub %%g0, %%o0, %%o0\n" \
|
||||||
|
"1:\n"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
#define _NOLIBC_SYSCALL "t 0x10\n" \
|
||||||
|
"bcs,a 1f\n" \
|
||||||
|
"sub %%g0, %%o0, %%o0\n" \
|
||||||
|
"1:\n"
|
||||||
|
|
||||||
|
#endif /* __arch64__ */
|
||||||
|
|
||||||
|
#define my_syscall0(num) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0"); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define my_syscall1(num, arg1) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define my_syscall2(num, arg1, arg2) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||||
|
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_arg2), "r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define my_syscall3(num, arg1, arg2, arg3) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||||
|
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||||
|
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_arg2), "r"(_arg3), "r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||||
|
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||||
|
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||||
|
register long _arg4 __asm__ ("o3") = (long)(arg4); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||||
|
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||||
|
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||||
|
register long _arg4 __asm__ ("o3") = (long)(arg4); \
|
||||||
|
register long _arg5 __asm__ ("o4") = (long)(arg5); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
|
||||||
|
({ \
|
||||||
|
register long _num __asm__ ("g1") = (num); \
|
||||||
|
register long _arg1 __asm__ ("o0") = (long)(arg1); \
|
||||||
|
register long _arg2 __asm__ ("o1") = (long)(arg2); \
|
||||||
|
register long _arg3 __asm__ ("o2") = (long)(arg3); \
|
||||||
|
register long _arg4 __asm__ ("o3") = (long)(arg4); \
|
||||||
|
register long _arg5 __asm__ ("o4") = (long)(arg5); \
|
||||||
|
register long _arg6 __asm__ ("o5") = (long)(arg6); \
|
||||||
|
\
|
||||||
|
__asm__ volatile ( \
|
||||||
|
_NOLIBC_SYSCALL \
|
||||||
|
: "+r"(_arg1) \
|
||||||
|
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
|
||||||
|
"r"(_num) \
|
||||||
|
: "memory", "cc" \
|
||||||
|
); \
|
||||||
|
_arg1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
/* startup code */
|
||||||
|
void __attribute__((weak, noreturn)) __nolibc_entrypoint __no_stack_protector _start(void)
|
||||||
|
{
|
||||||
|
__asm__ volatile (
|
||||||
|
/*
|
||||||
|
* Save argc pointer to o0, as arg1 of _start_c.
|
||||||
|
* Account for the window save area, which is 16 registers wide.
|
||||||
|
*/
|
||||||
|
#ifdef __arch64__
|
||||||
|
"add %sp, 128 + 2047, %o0\n" /* on sparc64 / v9 the stack is offset by 2047 */
|
||||||
|
#else
|
||||||
|
"add %sp, 64, %o0\n"
|
||||||
|
#endif
|
||||||
|
"b,a _start_c\n" /* transfer to c runtime */
|
||||||
|
);
|
||||||
|
__nolibc_entrypoint_epilogue();
|
||||||
|
}
|
||||||
|
|
||||||
|
static pid_t getpid(void);
|
||||||
|
|
||||||
|
static __attribute__((unused))
|
||||||
|
pid_t sys_fork(void)
|
||||||
|
{
|
||||||
|
pid_t parent, ret;
|
||||||
|
|
||||||
|
parent = getpid();
|
||||||
|
ret = my_syscall0(__NR_fork);
|
||||||
|
|
||||||
|
/* The syscall returns the parent pid in the child instead of 0 */
|
||||||
|
if (ret == parent)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#define sys_fork sys_fork
|
||||||
|
|
||||||
|
#endif /* _NOLIBC_ARCH_SPARC_H */
|
||||||
|
|
@ -33,6 +33,8 @@
|
||||||
#include "arch-s390.h"
|
#include "arch-s390.h"
|
||||||
#elif defined(__loongarch__)
|
#elif defined(__loongarch__)
|
||||||
#include "arch-loongarch.h"
|
#include "arch-loongarch.h"
|
||||||
|
#elif defined(__sparc__)
|
||||||
|
#include "arch-sparc.h"
|
||||||
#else
|
#else
|
||||||
#error Unsupported Architecture
|
#error Unsupported Architecture
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,8 @@ ARCH_mips32be = mips
|
||||||
ARCH_riscv32 = riscv
|
ARCH_riscv32 = riscv
|
||||||
ARCH_riscv64 = riscv
|
ARCH_riscv64 = riscv
|
||||||
ARCH_s390x = s390
|
ARCH_s390x = s390
|
||||||
|
ARCH_sparc32 = sparc
|
||||||
|
ARCH_sparc64 = sparc
|
||||||
ARCH := $(or $(ARCH_$(XARCH)),$(XARCH))
|
ARCH := $(or $(ARCH_$(XARCH)),$(XARCH))
|
||||||
|
|
||||||
# kernel image names by architecture
|
# kernel image names by architecture
|
||||||
|
|
@ -76,6 +78,8 @@ IMAGE_riscv64 = arch/riscv/boot/Image
|
||||||
IMAGE_s390x = arch/s390/boot/bzImage
|
IMAGE_s390x = arch/s390/boot/bzImage
|
||||||
IMAGE_s390 = arch/s390/boot/bzImage
|
IMAGE_s390 = arch/s390/boot/bzImage
|
||||||
IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi
|
IMAGE_loongarch = arch/loongarch/boot/vmlinuz.efi
|
||||||
|
IMAGE_sparc32 = arch/sparc/boot/image
|
||||||
|
IMAGE_sparc64 = arch/sparc/boot/image
|
||||||
IMAGE = $(objtree)/$(IMAGE_$(XARCH))
|
IMAGE = $(objtree)/$(IMAGE_$(XARCH))
|
||||||
IMAGE_NAME = $(notdir $(IMAGE))
|
IMAGE_NAME = $(notdir $(IMAGE))
|
||||||
|
|
||||||
|
|
@ -97,6 +101,8 @@ DEFCONFIG_riscv64 = defconfig
|
||||||
DEFCONFIG_s390x = defconfig
|
DEFCONFIG_s390x = defconfig
|
||||||
DEFCONFIG_s390 = defconfig compat.config
|
DEFCONFIG_s390 = defconfig compat.config
|
||||||
DEFCONFIG_loongarch = defconfig
|
DEFCONFIG_loongarch = defconfig
|
||||||
|
DEFCONFIG_sparc32 = sparc32_defconfig
|
||||||
|
DEFCONFIG_sparc64 = sparc64_defconfig
|
||||||
DEFCONFIG = $(DEFCONFIG_$(XARCH))
|
DEFCONFIG = $(DEFCONFIG_$(XARCH))
|
||||||
|
|
||||||
EXTRACONFIG = $(EXTRACONFIG_$(XARCH))
|
EXTRACONFIG = $(EXTRACONFIG_$(XARCH))
|
||||||
|
|
@ -122,6 +128,8 @@ QEMU_ARCH_riscv64 = riscv64
|
||||||
QEMU_ARCH_s390x = s390x
|
QEMU_ARCH_s390x = s390x
|
||||||
QEMU_ARCH_s390 = s390x
|
QEMU_ARCH_s390 = s390x
|
||||||
QEMU_ARCH_loongarch = loongarch64
|
QEMU_ARCH_loongarch = loongarch64
|
||||||
|
QEMU_ARCH_sparc32 = sparc
|
||||||
|
QEMU_ARCH_sparc64 = sparc64
|
||||||
QEMU_ARCH = $(QEMU_ARCH_$(XARCH))
|
QEMU_ARCH = $(QEMU_ARCH_$(XARCH))
|
||||||
|
|
||||||
QEMU_ARCH_USER_ppc64le = ppc64le
|
QEMU_ARCH_USER_ppc64le = ppc64le
|
||||||
|
|
@ -152,6 +160,8 @@ QEMU_ARGS_riscv64 = -M virt -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_T
|
||||||
QEMU_ARGS_s390x = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
QEMU_ARGS_s390x = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||||
QEMU_ARGS_s390 = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
QEMU_ARGS_s390 = -M s390-ccw-virtio -append "console=ttyS0 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||||
QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
QEMU_ARGS_loongarch = -M virt -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||||
|
QEMU_ARGS_sparc32 = -M SS-5 -m 256M -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||||
|
QEMU_ARGS_sparc64 = -M sun4u -append "console=ttyS0,115200 panic=-1 $(TEST:%=NOLIBC_TEST=%)"
|
||||||
QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
|
QEMU_ARGS = -m 1G $(QEMU_ARGS_$(XARCH)) $(QEMU_ARGS_BIOS) $(QEMU_ARGS_EXTRA)
|
||||||
|
|
||||||
# OUTPUT is only set when run from the main makefile, otherwise
|
# OUTPUT is only set when run from the main makefile, otherwise
|
||||||
|
|
@ -174,6 +184,7 @@ CFLAGS_s390x = -m64
|
||||||
CFLAGS_s390 = -m31
|
CFLAGS_s390 = -m31
|
||||||
CFLAGS_mips32le = -EL -mabi=32 -fPIC
|
CFLAGS_mips32le = -EL -mabi=32 -fPIC
|
||||||
CFLAGS_mips32be = -EB -mabi=32
|
CFLAGS_mips32be = -EB -mabi=32
|
||||||
|
CFLAGS_sparc32 = $(call cc-option,-m32)
|
||||||
ifeq ($(origin XARCH),command line)
|
ifeq ($(origin XARCH),command line)
|
||||||
CFLAGS_XARCH = $(CFLAGS_$(XARCH))
|
CFLAGS_XARCH = $(CFLAGS_$(XARCH))
|
||||||
endif
|
endif
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,7 @@ all_archs=(
|
||||||
riscv32 riscv64
|
riscv32 riscv64
|
||||||
s390x s390
|
s390x s390
|
||||||
loongarch
|
loongarch
|
||||||
|
sparc32 sparc64
|
||||||
)
|
)
|
||||||
archs="${all_archs[@]}"
|
archs="${all_archs[@]}"
|
||||||
|
|
||||||
|
|
@ -111,6 +112,7 @@ crosstool_arch() {
|
||||||
loongarch) echo loongarch64;;
|
loongarch) echo loongarch64;;
|
||||||
mips*) echo mips;;
|
mips*) echo mips;;
|
||||||
s390*) echo s390;;
|
s390*) echo s390;;
|
||||||
|
sparc*) echo sparc64;;
|
||||||
*) echo "$1";;
|
*) echo "$1";;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user