mirror of
https://github.com/opencontainers/runc.git
synced 2026-07-10 21:53:57 +08:00
90f5da651a
Linux repo has under `tools/include/nolibc` very simple include files that we can use to generate very small binaries that don't depend on libc. To make things even better, since Linux 6.6 it supports all the architectures we support in runc, which is just beautiful. The runc-dmz binary on x86_64 before this patch (on my debian host) was taking 636K, with this patch it takes only 8K. Signed-off-by: Rodrigo Campos <rodrigoca@microsoft.com>
165 lines
8.5 KiB
C
165 lines
8.5 KiB
C
/* SPDX-License-Identifier: LGPL-2.1 OR MIT */
|
|
/*
|
|
* LoongArch specific definitions for NOLIBC
|
|
* Copyright (C) 2023 Loongson Technology Corporation Limited
|
|
*/
|
|
|
|
#ifndef _NOLIBC_ARCH_LOONGARCH_H
|
|
#define _NOLIBC_ARCH_LOONGARCH_H
|
|
|
|
#include "compiler.h"
|
|
#include "crt.h"
|
|
|
|
/* Syscalls for LoongArch :
|
|
* - stack is 16-byte aligned
|
|
* - syscall number is passed in a7
|
|
* - arguments are in a0, a1, a2, a3, a4, a5
|
|
* - the system call is performed by calling "syscall 0"
|
|
* - syscall return comes in a0
|
|
* - the arguments are cast to long and assigned into the target
|
|
* registers which are then simply passed as registers to the asm code,
|
|
* so that we don't have to experience issues with register constraints.
|
|
*
|
|
* On LoongArch, select() is not implemented so we have to use pselect6().
|
|
*/
|
|
#define __ARCH_WANT_SYS_PSELECT6
|
|
#define _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
"memory", "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
|
|
|
|
#define my_syscall0(num) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0"); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "=r"(_arg1) \
|
|
: "r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#define my_syscall1(num, arg1) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "+r"(_arg1) \
|
|
: "r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#define my_syscall2(num, arg1, arg2) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
|
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "+r"(_arg1) \
|
|
: "r"(_arg2), \
|
|
"r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#define my_syscall3(num, arg1, arg2, arg3) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
|
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
|
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "+r"(_arg1) \
|
|
: "r"(_arg2), "r"(_arg3), \
|
|
"r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#define my_syscall4(num, arg1, arg2, arg3, arg4) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
|
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
|
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
|
register long _arg4 __asm__ ("a3") = (long)(arg4); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "+r"(_arg1) \
|
|
: "r"(_arg2), "r"(_arg3), "r"(_arg4), \
|
|
"r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#define my_syscall5(num, arg1, arg2, arg3, arg4, arg5) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
|
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
|
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
|
register long _arg4 __asm__ ("a3") = (long)(arg4); \
|
|
register long _arg5 __asm__ ("a4") = (long)(arg5); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "+r"(_arg1) \
|
|
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), \
|
|
"r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#define my_syscall6(num, arg1, arg2, arg3, arg4, arg5, arg6) \
|
|
({ \
|
|
register long _num __asm__ ("a7") = (num); \
|
|
register long _arg1 __asm__ ("a0") = (long)(arg1); \
|
|
register long _arg2 __asm__ ("a1") = (long)(arg2); \
|
|
register long _arg3 __asm__ ("a2") = (long)(arg3); \
|
|
register long _arg4 __asm__ ("a3") = (long)(arg4); \
|
|
register long _arg5 __asm__ ("a4") = (long)(arg5); \
|
|
register long _arg6 __asm__ ("a5") = (long)(arg6); \
|
|
\
|
|
__asm__ volatile ( \
|
|
"syscall 0\n" \
|
|
: "+r"(_arg1) \
|
|
: "r"(_arg2), "r"(_arg3), "r"(_arg4), "r"(_arg5), "r"(_arg6), \
|
|
"r"(_num) \
|
|
: _NOLIBC_SYSCALL_CLOBBERLIST \
|
|
); \
|
|
_arg1; \
|
|
})
|
|
|
|
#if __loongarch_grlen == 32
|
|
#define LONG_BSTRINS "bstrins.w"
|
|
#else /* __loongarch_grlen == 64 */
|
|
#define LONG_BSTRINS "bstrins.d"
|
|
#endif
|
|
|
|
/* startup code */
|
|
void __attribute__((weak, noreturn, optimize("Os", "omit-frame-pointer"))) __no_stack_protector _start(void)
|
|
{
|
|
__asm__ volatile (
|
|
"move $a0, $sp\n" /* save stack pointer to $a0, as arg1 of _start_c */
|
|
LONG_BSTRINS " $sp, $zero, 3, 0\n" /* $sp must be 16-byte aligned */
|
|
"bl _start_c\n" /* transfer to c runtime */
|
|
);
|
|
__builtin_unreachable();
|
|
}
|
|
|
|
#endif /* _NOLIBC_ARCH_LOONGARCH_H */
|