Improve aarch64 native support some more

This change introduces partial support for automating remote testing of
aarch64 binaries on Raspberry Pi and Apple Silicon.
This commit is contained in:
Justine Tunney 2023-06-04 08:19:45 -07:00
parent fc34ba2596
commit 4aa1d09b9e
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
20 changed files with 185 additions and 82 deletions

View file

@ -60,7 +60,6 @@
# build/config.mk
SHELL = build/bootstrap/cocmd.com
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10
MAKEFLAGS += --no-builtin-rules
.SUFFIXES:

View file

@ -82,8 +82,10 @@ endif
ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
VM = o/third_party/qemu/qemu-aarch64
HOSTS ?= pi silicon
else
ARCH = x86_64
HOSTS ?= freebsd openbsd netbsd rhel7 rhel5 xnu win10
endif
ifneq ("$(wildcard o/third_party/gcc/bin/x86_64-pc-linux-gnu-*)","")

View file

@ -23,9 +23,9 @@
# - tool/build/runitd.c
.PRECIOUS: o/$(MODE)/%.com.ok
o/$(MODE)/%.com.ok: .PLEDGE = stdio rpath wpath cpath proc fattr inet
o/$(MODE)/%.com.ok: private .PLEDGE = stdio rpath wpath cpath proc fattr inet
o/$(MODE)/%.com.ok: \
o/$(MODE)/tool/build/runit.com \
o/$(MODE)/tool/build/runitd.com \
o//tool/build/runit.com \
o//tool/build/runitd.com \
o/$(MODE)/%.com
@$(COMPILE) -wATEST -tT$@ $^ $(HOSTS)

View file

@ -9,6 +9,7 @@
#endif
#include "libc/intrin/kprintf.h"
#include "libc/log/log.h"
#include "libc/math.h"
#include "libc/runtime/symbols.internal.h"
/**
@ -25,13 +26,17 @@
*/
noubsan int main(int argc, char *argv[]) {
kprintf("----------------\n");
kprintf(" THIS IS A TEST \n");
kprintf("SIMULATING CRASH\n");
kprintf("----------------\n");
volatile int64_t x;
ShowCrashReports();
volatile double a = 0;
volatile double b = 23;
volatile double c = exp(b) / a;
volatile int64_t x;
return 1 / (x = 0);
}

View file

@ -0,0 +1,43 @@
#ifndef COSMOPOLITAN_LIBC_CALLS_STRUCT_AARCH64_H_
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_AARCH64_H_
#if !(__ASSEMBLER__ + __LINKER__ + 0)
COSMOPOLITAN_C_START_
#define FPSIMD_MAGIC 0x46508001
#define ESR_MAGIC 0x45535201
#define EXTRA_MAGIC 0x45585401
#define SVE_MAGIC 0x53564501
struct _aarch64_ctx {
uint32_t magic;
uint32_t size;
};
struct fpsimd_context {
struct _aarch64_ctx head;
uint32_t fpsr;
uint32_t fpcr;
uint128_t vregs[32];
};
struct esr_context {
struct _aarch64_ctx head;
uint64_t esr;
};
struct extra_context {
struct _aarch64_ctx head;
uint64_t datap;
uint32_t size;
uint32_t __reserved[3];
};
struct sve_context {
struct _aarch64_ctx head;
uint16_t vl;
uint16_t __reserved[3];
};
COSMOPOLITAN_C_END_
#endif /* !(__ASSEMBLER__ + __LINKER__ + 0) */
#endif /* COSMOPOLITAN_LIBC_CALLS_STRUCT_AARCH64_H_ */

View file

@ -49,8 +49,6 @@ static textwindows dontinline void SetupWinStd(struct Fds *fds, int i, int x) {
textstartup void InitializeFileDescriptors(void) {
struct Fds *fds;
__fds_lock_obj._type = PTHREAD_MUTEX_RECURSIVE;
pthread_atfork(_weaken(__fds_lock), _weaken(__fds_unlock),
_weaken(__fds_funlock));
fds = VEIL("r", &g_fds);
fds->n = 4;
atomic_store_explicit(&fds->f, 3, memory_order_relaxed);

View file

@ -19,6 +19,7 @@
#include "ape/sections.internal.h"
#include "libc/assert.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/aarch64.h"
#include "libc/calls/struct/rusage.internal.h"
#include "libc/calls/struct/siginfo.h"
#include "libc/calls/struct/sigset.h"
@ -44,6 +45,7 @@ STATIC_YOINK("strerror_wr"); // for kprintf %m
STATIC_YOINK("strsignal_r"); // for kprintf %G
#define RESET "\e[0m"
#define BOLD "\e[1m"
#define STRONG "\e[30;101m"
#define RED "\e[31;1m"
#define GREEN "\e[32;1m"
@ -203,6 +205,7 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) {
const char *addr2line;
struct StackFrame *fp;
struct SymbolTable *st;
struct fpsimd_context *vc;
st = GetSymbolTable();
debugbin = FindDebugBinary();
addr2line = GetAddr2linePath();
@ -217,13 +220,30 @@ relegated void __oncrash_arm64(int sig, struct siginfo *si, void *arg) {
for (j = 0; j < 4; ++j) {
int r = 8 * j + i;
if (j) Append(b, " ");
Append(b, "%s%016lx%s %d%s", ColorRegister(r),
Append(b, "%s%016lx%s x%d%s", ColorRegister(r),
ctx->uc_mcontext.regs[r], reset, r,
r == 8 || r == 9 ? " " : "");
}
Append(b, "\n");
}
// PRINT VECTORS
vc = (struct fpsimd_context *)ctx->uc_mcontext.__reserved;
if (vc->head.magic == FPSIMD_MAGIC) {
int n = 16;
while (n && !vc->vregs[n - 1] && !vc->vregs[n - 2]) n -= 2;
for (i = 0; i * 2 < n; ++i) {
Append(b, " ");
for (j = 0; j < 2; ++j) {
int r = j + 2 * i;
if (j) Append(b, " ");
Append(b, "%016lx ..%s %016lx v%d%s", (long)(vc->vregs[r] >> 64),
!j ? "" : ".", (long)vc->vregs[r], r, r < 10 ? " " : "");
}
Append(b, "\n");
}
}
// PRINT CURRENT LOCATION
//
// We can get the address of the currently executing function by

View file

@ -26,22 +26,20 @@ CheckStackIsAligned:
push %rbp
mov %rsp,%rbp
// allocate sixteen bytes
push %rax
push %rax
// put a value in it
xorps %xmm0,%xmm0
movaps %xmm0,-16(%rbp)
leave
test $15,%rsp
jz 1f
int3 // misaligned stack trap
1: pop %rbp
ret
#elif defined(__aarch64__)
// TODO: support me
mov x0,#1
stp x29,x30,[sp,#-16]!
mov x29,sp
and x0,x29,#15
cbz x0,1f
brk #666 // misaligned stack trap
1: ldp x29,x30,[sp],#16
ret
#else

View file

@ -313,7 +313,7 @@ static errno_t CloneOpenbsd(int (*func)(void *, int), char *stk, size_t stksz,
sp &= -alignof(struct __tfork);
tf = (struct __tfork *)sp;
sp -= sizeof(struct CloneArgs);
sp &= -MAX(16, alignof(struct CloneArgs));
sp &= -alignof(struct CloneArgs);
wt = (struct CloneArgs *)sp;
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
@ -442,10 +442,10 @@ static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,
static void *SiliconThreadMain(void *arg) {
register struct CloneArgs *wt asm("x21") = arg;
asm volatile("ldr\tx28,%0" : /* no outputs */ : "m"(wt->tls));
*wt->ctid = wt->this;
register long x0 asm("x0") = (long)wt->arg;
register long x1 asm("x1") = (long)wt->tid;
register void *x0 asm("x0") = wt->arg;
register int x1 asm("w1") = wt->this;
register void *x28 asm("x28") = wt->tls;
asm volatile("mov\tx19,x29\n\t" // save frame pointer
"mov\tx20,sp\n\t" // save stack pointer
"mov\tx29,#0\n\t" // reset backtrace
@ -454,7 +454,7 @@ static void *SiliconThreadMain(void *arg) {
"mov\tx29,x19\n\t" // restore frame pointer
"mov\tsp,x20" // restore stack pointer
: "+r"(x0)
: "r"(x1), "r"(wt->func), "r"(wt)
: "r"(x1), "r"(wt->func), "r"(wt), "r"(x28)
: "x19", "x20", "memory");
*wt->ztid = 0;
return 0;

View file

@ -19,6 +19,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/intrin/kprintf.h"
#include "libc/intrin/strace.internal.h"
#include "libc/macros.internal.h"
#include "libc/nexgen32e/rdtsc.h"
@ -44,12 +45,12 @@ typedef int init_f(int argc, char **argv, char **envp, unsigned long *auxv);
extern long syscon_start[];
extern long syscon_end[];
extern long syscon_linux[];
extern long syscon_xnu[];
extern long syscon_freebsd[];
extern long syscon_openbsd[];
extern long syscon_netbsd[];
extern long syscon_windows[];
extern char syscon_linux[];
extern char syscon_xnu[];
extern char syscon_freebsd[];
extern char syscon_openbsd[];
extern char syscon_netbsd[];
extern char syscon_windows[];
extern init_f __strace_init;
extern init_f *__preinit_array_start[] __attribute__((__weak__));
extern init_f *__preinit_array_end[] __attribute__((__weak__));
@ -61,13 +62,24 @@ extern char ape_stack_prot[] __attribute__((__weak__));
extern pthread_mutex_t __mmi_lock_obj;
extern int hostos asm("__hostos");
static const char *DecodeMagnum(const char *p, long *r) {
int k = 0;
unsigned long c, x = 0;
do {
c = *p++;
x |= (c & 127) << k;
k += 7;
} while (c & 128);
return *r = x, p;
}
textstartup void cosmo(long *sp, struct Syslib *m1) {
int argc;
long *mp;
init_f **fp;
uintptr_t *pp;
long *mp, *magnums;
char **argv, **envp;
unsigned long *auxv;
char **argv, **envp, *magnums;
// get startup timestamp as early as possible
// its used by --strace and also kprintf() %T
@ -93,7 +105,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
// setup system magic numbers
for (mp = syscon_start; mp < syscon_end; ++mp) {
*mp = *magnums++;
magnums = DecodeMagnum(magnums, mp);
}
// check system call abi compatibility
@ -131,6 +143,7 @@ textstartup void cosmo(long *sp, struct Syslib *m1) {
#endif
#endif
// initialize file system
InitializeFileDescriptors();
// set helpful globals

View file

@ -61,9 +61,7 @@ textstartup void __set_tls(struct CosmoTib *tib) {
"d"((uint32_t)(val >> 32)));
}
#else
asm volatile("mov\tx28,%0" : /* no outputs */ : "r"(tib));
if (!IsXnu()) {
asm volatile("msr\ttpidr_el0,%0" : /* no outputs */ : "r"(tib));
}
register long x28 asm("x28") = (long)tib;
asm volatile("" : "+r"(x28));
#endif
}

View file

@ -67,13 +67,13 @@ vfork:
#endif
pop %rbp
#endif
mov %fs:0,%r9 # get thread information block
mov %fs:0,%r9 // get thread information block
#if SupportsWindows()
testb IsWindows()
jnz 6f # and we're lucky to have that
jnz 6f // and we're lucky to have that
#endif
#ifdef __SANITIZE_ADDRESS__
jmp 5f # TODO: asan and vfork don't mix?
jmp 5f // TODO: asan and vfork don't mix?
#endif
#if SupportsXnu()
testb IsXnu()
@ -81,10 +81,10 @@ vfork:
#endif
#if SupportsOpenbsd()
testb IsOpenbsd()
jnz 5f # fake vfork plus msyscall issues
jnz 5f // fake vfork plus msyscall issues
#endif
mov 0x3c(%r9),%r8d # avoid question of @vforksafe errno
pop %rsi # saves return address in a register
mov 0x3c(%r9),%r8d // avoid question of @vforksafe errno
pop %rsi // saves return address in a register
mov __NR_vfork(%rip),%eax
#if SupportsBsd()
clc
@ -95,10 +95,10 @@ vfork:
neg %rax
0:
#endif
push %rsi # note it happens twice in same page
push %rsi // note it happens twice in same page
cmp $-4095,%eax
jae systemfive_error
mov %r8d,0x3c(%r9) # restore errno
mov %r8d,0x3c(%r9) // restore errno
1: test %eax,%eax
jnz .Lpar
.Lchi: orb $TIB_FLAG_VFORKED,0x40(%r9)
@ -121,7 +121,7 @@ vfork:
mov %rsp,%rbp
push %r9
push %r9
xor %edi,%edi # dwCreationFlags
xor %edi,%edi // dwCreationFlags
call sys_fork_nt
pop %r9
pop %r9
@ -131,11 +131,31 @@ vfork:
#elif defined(__aarch64__)
mov x8,#220 // __NR_clone
adrp x0,__hostos
ldr w0,[x0,#:lo12:__hostos]
tbz x0,3,1f // bit 3 is xnu
b fork // which doesn't support vfork()
1: mov x8,#220 // __NR_clone
mov x0,#0x4111 // SIGCHLD | CLONE_VM | CLONE_VFORK
mov x1,#0
svc 0
.hidden _sysret
// if (!rc) {
// __get_tls()->tib_flags |= TIB_FLAG_VFORKED;
// } else {
// __get_tls()->tib_flags &= ~TIB_FLAG_VFORKED;
// }
sub x1,x28,#1152
ldr x2,[x1,0x40]
cbnz x0,2f
orr x2,x2,#TIB_FLAG_VFORKED
1: str x2,[x1,0x40]
b 3f
2: and x2,x2,#~TIB_FLAG_VFORKED
b 1b
// if (rc < 0) errno = -rc, rc = -1;
3: .hidden _sysret
b _sysret
#else

View file

@ -601,8 +601,8 @@ syscon clock CLOCK_MONOTONIC_PRECISE 1 1 1 6 11 3 3 1 #
syscon clock CLOCK_MONOTONIC_FAST 1 1 1 6 12 3 3 1 #
syscon clock CLOCK_MONOTONIC_COARSE 6 6 1 6 12 3 3 1 # Linux 2.6.32+; bsd consensus; not available on RHEL5
syscon clock CLOCK_MONOTONIC_RAW 4 4 127 4 127 127 127 127 # actually monotonic; not subject to NTP adjustments; Linux 2.6.28+; XNU/NT/FreeBSD/OpenBSD faked; not available on RHEL5
syscon clock CLOCK_PROCESS_CPUTIME_ID 2 2 127 127 15 2 0x40000000 127 #
syscon clock CLOCK_THREAD_CPUTIME_ID 3 3 127 127 14 4 0x20000000 127 #
syscon clock CLOCK_PROCESS_CPUTIME_ID 2 2 127 12 15 2 0x40000000 127 #
syscon clock CLOCK_THREAD_CPUTIME_ID 3 3 127 16 14 4 0x20000000 127 #
syscon clock CLOCK_PROF 127 127 127 127 2 127 2 127 #
syscon clock CLOCK_BOOTTIME 7 7 127 127 127 6 127 127 #
syscon clock CLOCK_REALTIME_ALARM 8 8 127 127 127 127 127 127 #

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon clock,CLOCK_PROCESS_CPUTIME_ID,2,2,127,127,15,2,0x40000000,127
.syscon clock,CLOCK_PROCESS_CPUTIME_ID,2,2,127,12,15,2,0x40000000,127

View file

@ -1,2 +1,2 @@
#include "libc/sysv/consts/syscon.internal.h"
.syscon clock,CLOCK_THREAD_CPUTIME_ID,3,3,127,127,14,4,0x20000000,127
.syscon clock,CLOCK_THREAD_CPUTIME_ID,3,3,127,16,14,4,0x20000000,127

View file

@ -21,10 +21,7 @@
// clang-format off
#ifdef __x86_64__
#define ENCODE .uleb128
.yoink _init_systemfive
#else
#define ENCODE .balign 8 ; .quad
#endif
.macro .syscon group:req name:req linux:req linux_aarch64:req xnu:req xnu_aarch64:req freebsd:req openbsd:req netbsd:req windows:req
@ -38,9 +35,9 @@
#if SupportsLinux() || SupportsMetal()
.section .sort.rodata.syscon.linux.2.\group\().\name,"a",@progbits
#ifdef __aarch64__
ENCODE \linux_aarch64
.uleb128 \linux_aarch64
#else
ENCODE \linux
.uleb128 \linux
#endif
.previous
#endif
@ -48,34 +45,34 @@
#if SupportsXnu()
.section .sort.rodata.syscon.xnu.2.\group\().\name,"a",@progbits
#ifdef __aarch64__
ENCODE \xnu_aarch64
.uleb128 \xnu_aarch64
#else
ENCODE \xnu
.uleb128 \xnu
#endif
.previous
#endif
#if SupportsFreebsd()
.section .sort.rodata.syscon.freebsd.2.\group\().\name,"a",@progbits
ENCODE \freebsd
.uleb128 \freebsd
.previous
#endif
#if SupportsOpenbsd()
.section .sort.rodata.syscon.openbsd.2.\group\().\name,"a",@progbits
ENCODE \openbsd
.uleb128 \openbsd
.previous
#endif
#if SupportsNetbsd()
.section .sort.rodata.syscon.netbsd.2.\group\().\name,"a",@progbits
ENCODE \netbsd
.uleb128 \netbsd
.previous
#endif
#if SupportsWindows()
.section .sort.rodata.syscon.windows.2.\group\().\name,"a",@progbits
ENCODE \windows
.uleb128 \windows
.previous
#endif

View file

@ -19,12 +19,6 @@
#include "libc/dce.h"
#include "libc/macros.internal.h"
#ifdef __x86_64__
#define ROALIGN 1
#else
#define ROALIGN 8
#endif
// Sections for varint encoded magic numbers.
//
// These sections are all ordered by (group_name, constant_name).
@ -46,7 +40,6 @@ syscon_end:
.globl syscon_end
#if SupportsLinux() || SupportsMetal()
.section .sort.rodata.syscon.linux.1,"a",@progbits
.balign ROALIGN
syscon_linux:/*
...decentralized leb128...
*/.previous
@ -55,7 +48,6 @@ syscon_linux:/*
#endif
#if SupportsXnu()
.section .sort.rodata.syscon.xnu.1,"a",@progbits
.balign ROALIGN
syscon_xnu:/*
...decentralized leb128...
*/.previous
@ -64,7 +56,6 @@ syscon_xnu:/*
#endif
#if SupportsFreebsd()
.section .sort.rodata.syscon.freebsd.1,"a",@progbits
.balign ROALIGN
syscon_freebsd:/*
...decentralized leb128...
*/.previous
@ -73,7 +64,6 @@ syscon_freebsd:/*
#endif
#if SupportsOpenbsd()
.section .sort.rodata.syscon.openbsd.1,"a",@progbits
.balign ROALIGN
syscon_openbsd:/*
...decentralized leb128...
*/.previous
@ -82,7 +72,6 @@ syscon_openbsd:/*
#endif
#if SupportsNetbsd()
.section .sort.rodata.syscon.netbsd.1,"a",@progbits
.balign ROALIGN
syscon_netbsd:/*
...decentralized leb128...
*/.previous
@ -91,7 +80,6 @@ syscon_netbsd:/*
#endif
#if SupportsWindows()
.section .sort.rodata.syscon.windows.1,"a",@progbits
.balign ROALIGN
syscon_windows:/*
...decentralized leb128...
*/.previous

View file

@ -17,6 +17,7 @@
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/assert.h"
#include "libc/calls/state.internal.h"
#include "libc/errno.h"
#include "libc/intrin/atomic.h"
#include "libc/intrin/kmalloc.h"
@ -58,13 +59,15 @@ static void _pthread_onfork(int i) {
void _pthread_onfork_prepare(void) {
_pthread_onfork(0);
pthread_spin_lock(&_pthread_lock);
__kmalloc_lock();
__fds_lock();
__mmi_lock();
__kmalloc_lock();
}
void _pthread_onfork_parent(void) {
__mmi_unlock();
__kmalloc_unlock();
__mmi_unlock();
__fds_unlock();
pthread_spin_unlock(&_pthread_lock);
_pthread_onfork(1);
}
@ -82,11 +85,12 @@ void _pthread_onfork_child(void) {
atomic_store_explicit(&pt->cancelled, false, memory_order_relaxed);
// wipe core runtime locks
__kmalloc_unlock();
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&__mmi_lock_obj, &attr);
pthread_mutex_init(&__fds_lock_obj, &attr);
pthread_spin_init(&_pthread_lock, 0);
__kmalloc_unlock();
// call user-supplied forked child callbacks
_pthread_onfork(2);

View file

@ -18,7 +18,9 @@
*/
#include "libc/calls/calls.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/dce.h"
#include "libc/errno.h"
#include "libc/stdio/stdio.h"
#include "libc/sysv/consts/sig.h"
#include "libc/testlib/testlib.h"
#include "libc/thread/thread.h"
@ -26,6 +28,13 @@
int fds[2];
_Thread_local sig_atomic_t gotsig;
void SetUp(void) {
if (IsXnuSilicon()) {
fprintf(stderr, "TODO(jart): Get pthread_kill() working on XNU silicon\n");
exit(0);
}
}
void OnSig(int sig) {
gotsig = 1;
}

View file

@ -432,11 +432,20 @@ void HandleClient(void) {
sigaction(SIGQUIT, &(struct sigaction){0}, 0);
sigprocmask(SIG_SETMASK, &savemask, 0);
int i = 0;
char *args[4] = {0};
const char *exe;
char *args[8] = {0};
if (!IsXnuSilicon()) {
exe = g_exepath;
} else {
exe = "ape-m1.com";
args[i++] = exe;
args[i++] = "-";
args[i++] = g_exepath;
}
args[i++] = g_exepath;
if (use_strace) args[i++] = "--strace";
if (use_ftrace) args[i++] = "--ftrace";
execv(g_exepath, args);
execvp(exe, args);
_Exit(127);
}
close(pipefds[1]);