Skip to content

Commit

Permalink
Introduce FreeBSD ARM64 support
Browse files Browse the repository at this point in the history
It's 100% passing test fleet. Solid as a rock.
  • Loading branch information
jart committed Dec 30, 2023
1 parent 43fe595 commit 83107f7
Show file tree
Hide file tree
Showing 455 changed files with 778 additions and 551 deletions.
5 changes: 3 additions & 2 deletions ape/BUILD.mk
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,8 @@ APE_LOADER_FLAGS = \
$<

o/$(MODE)/ape/ape.elf: o/$(MODE)/ape/ape.elf.dbg
$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
@$(COMPILE) -AOBJCOPY -T$@ $(OBJCOPY) -g $< $@
@$(COMPILE) -AFIXUPOBJ -wT$@ $(FIXUPOBJ) $@

o/$(MODE)/ape/ape.elf.dbg: \
o/$(MODE)/ape/start.o \
Expand All @@ -88,7 +89,7 @@ o/$(MODE)/ape/ape.elf.dbg: \
@$(COMPILE) -ALINK.elf $(LD) $(APE_LOADER_LDFLAGS) -o $@ $(patsubst %.lds,-T %.lds,$^)

o/$(MODE)/ape/loader.o: ape/loader.c ape/ape.h
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=1 -g $(APE_LOADER_FLAGS)
@$(COMPILE) -AOBJECTIFY.c $(CC) -DSUPPORT_VECTOR=33 -g $(APE_LOADER_FLAGS)
o/$(MODE)/ape/start.o: ape/start.S
@$(COMPILE) -AOBJECTIFY.S $(OBJECTIFY.S) $(OUTPUT_OPTION) -c $<
o/$(MODE)/ape/launch.o: ape/launch.S
Expand Down
6 changes: 3 additions & 3 deletions ape/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@
#define MIN(X, Y) ((Y) > (X) ? (X) : (Y))
#define MAX(X, Y) ((Y) < (X) ? (X) : (Y))

#define PATH_MAX 1024 /* XXX verify */
#define PATH_MAX 1024 /* XXX verify */

#define SupportsLinux() (SUPPORT_VECTOR & LINUX)
#define SupportsXnu() (SUPPORT_VECTOR & XNU)
Expand Down Expand Up @@ -224,8 +224,8 @@ struct ApeLoader {
};

EXTERN_C long SystemCall(long, long, long, long, long, long, long, int);
EXTERN_C void
Launch(void *, long, void *, void *, int) __attribute__((__noreturn__));
EXTERN_C void Launch(void *, long, void *, void *, int)
__attribute__((__noreturn__));

extern char __executable_start[];
extern char _end[];
Expand Down
Binary file modified build/bootstrap/ape.aarch64
Binary file not shown.
Binary file modified build/bootstrap/ape.elf
Binary file not shown.
Binary file modified build/bootstrap/ape.macho
Binary file not shown.
Binary file modified build/bootstrap/fixupobj.com
Binary file not shown.
2 changes: 1 addition & 1 deletion build/definitions.mk
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ IGNORE := $(shell $(MKDIR) $(TMPDIR))

ifneq ($(findstring aarch64,$(MODE)),)
ARCH = aarch64
HOSTS ?= pi studio
HOSTS ?= pi studio freebsdarm
else
ARCH = x86_64
HOSTS ?= freebsd rhel7 xnu win10 openbsd netbsd
Expand Down
23 changes: 23 additions & 0 deletions examples/crashreport2.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#if 0
/*─────────────────────────────────────────────────────────────────╗
│ To the extent possible under law, Justine Tunney has waived │
│ all copyright and related or neighboring rights to this file, │
│ as it is written in the following disclaimers: │
│ • http://unlicense.org/ │
│ • http://creativecommons.org/publicdomain/zero/1.0/ │
╚─────────────────────────────────────────────────────────────────*/
#endif
#include "libc/math.h"
#include "libc/runtime/runtime.h"

void crash(long x0, long x1, long x2, //
double v0, double v1, double v2) {
__builtin_trap();
}

void (*pCrash)(long, long, long, double, double, double) = crash;

int main(int argc, char *argv[]) {
ShowCrashReports();
pCrash(1, 2, 3, NAN, NAN, NAN);
}
26 changes: 15 additions & 11 deletions libc/calls/seccomp.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
│ PERFORMANCE OF THIS SOFTWARE. │
╚─────────────────────────────────────────────────────────────────────────────*/
#include "libc/calls/struct/seccomp.internal.h"
#include "libc/calls/calls.h"
#include "libc/calls/struct/seccomp.internal.h"
#include "libc/calls/syscall-sysv.internal.h"
#include "libc/dce.h"
#include "libc/errno.h"
Expand Down Expand Up @@ -62,16 +62,20 @@ int seccomp(unsigned operation, unsigned flags, void *args) {
rc = -1;
}
#elif defined(__aarch64__)
register long r0 asm("x0") = (long)operation;
register long r1 asm("x1") = (long)flags;
register long r2 asm("x2") = (long)args;
register long res_x0 asm("x0");
asm volatile("mov\tx8,%1\n\t"
"svc\t0"
: "=r"(res_x0)
: "i"(211), "r"(r0), "r"(r1), "r"(r2)
: "x8", "memory");
rc = _sysret(res_x0);
if (IsLinux()) {
register long r0 asm("x0") = (long)operation;
register long r1 asm("x1") = (long)flags;
register long r2 asm("x2") = (long)args;
register long res_x0 asm("x0");
asm volatile("mov\tx8,%1\n\t"
"svc\t0"
: "=r"(res_x0)
: "i"(211), "r"(r0), "r"(r1), "r"(r2)
: "x8", "memory");
rc = _sysret(res_x0);
} else {
rc = enosys();
}
#else
#error "arch unsupported"
#endif
Expand Down
69 changes: 57 additions & 12 deletions libc/calls/sigenter-freebsd.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include "libc/calls/calls.h"
#include "libc/calls/internal.h"
#include "libc/calls/state.internal.h"
#include "libc/calls/struct/aarch64.internal.h"
#include "libc/calls/struct/sigaction.h"
#include "libc/calls/struct/siginfo-freebsd.internal.h"
#include "libc/calls/struct/siginfo-meta.internal.h"
Expand All @@ -33,31 +34,39 @@
#include "libc/str/str.h"
#include "libc/sysv/consts/sa.h"

#ifdef __x86_64__

privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
struct ucontext_freebsd *ctx) {

#pragma GCC push_options
#pragma GCC diagnostic ignored "-Wframe-larger-than="
struct Goodies {
struct {
ucontext_t uc;
siginfo_t si;
} g;
CheckLargeStackAllocation(&g, sizeof(g));
#pragma GCC pop_options

int rva, flags;
rva = __sighandrvas[sig];
if (rva >= kSigactionMinRva) {
flags = __sighandflags[sig];
if (~flags & SA_SIGINFO) {
((sigaction_f)(__executable_start + rva))(sig, 0, 0);
} else {

//
// TRANSLATE FREEBSD SIGNAL TO LINUX SIGNAL
//

__repstosb(&g, 0, sizeof(g));
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
__siginfo2cosmo(&g.si, (void *)freebsdinfo);
g.uc.uc_stack.ss_sp = ctx->uc_stack.ss_sp;
g.uc.uc_stack.ss_size = ctx->uc_stack.ss_size;
g.uc.uc_stack.ss_flags = ctx->uc_stack.ss_flags;
g.uc.uc_sigmask = ctx->uc_sigmask[0] | (uint64_t)ctx->uc_sigmask[0] << 32;

#ifdef __x86_64__
g.uc.uc_mcontext.fpregs = &g.uc.__fpustate;
g.uc.uc_mcontext.r8 = ctx->uc_mcontext.mc_r8;
g.uc.uc_mcontext.r9 = ctx->uc_mcontext.mc_r9;
g.uc.uc_mcontext.r10 = ctx->uc_mcontext.mc_r10;
Expand All @@ -81,14 +90,39 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
g.uc.uc_mcontext.err = ctx->uc_mcontext.mc_err;
g.uc.uc_mcontext.trapno = ctx->uc_mcontext.mc_trapno;
__repmovsb(&g.uc.__fpustate, &ctx->uc_mcontext.mc_fpstate, 512);
__siginfo2cosmo(&g.si, (void *)freebsdinfo);
#endif /* __x86_64__ */

#ifdef __aarch64__
__memcpy(g.uc.uc_mcontext.regs, &ctx->uc_mcontext.mc_gpregs, 34 * 8);
if (ctx->uc_mcontext.mc_flags & _MC_FP_VALID) {
struct fpsimd_context *vc =
(struct fpsimd_context *)g.uc.uc_mcontext.__reserved;
vc->head.magic = FPSIMD_MAGIC;
vc->head.size = sizeof(*vc);
vc->fpsr = ctx->uc_mcontext.mc_fpregs.fp_sr;
vc->fpcr = ctx->uc_mcontext.mc_fpregs.fp_cr;
__memcpy(vc->vregs, ctx->uc_mcontext.mc_fpregs.fp_q, 32 * 16);
}
#endif /* __aarch64__ */

//
// INVOKE SIGNAL HANDLER
//

((sigaction_f)(__executable_start + rva))(sig, &g.si, &g.uc);

//
// TRANSLATE LINUX SIGNAL TO FREEBSD SIGNAL
//

ctx->uc_stack.ss_sp = g.uc.uc_stack.ss_sp;
ctx->uc_stack.ss_size = g.uc.uc_stack.ss_size;
ctx->uc_stack.ss_flags = g.uc.uc_stack.ss_flags;
ctx->uc_flags = g.uc.uc_flags;
ctx->uc_sigmask[0] = g.uc.uc_sigmask;
ctx->uc_sigmask[1] = g.uc.uc_sigmask >> 32;

#ifdef __x86_64__
ctx->uc_mcontext.mc_rdi = g.uc.uc_mcontext.rdi;
ctx->uc_mcontext.mc_rsi = g.uc.uc_mcontext.rsi;
ctx->uc_mcontext.mc_rdx = g.uc.uc_mcontext.rdx;
Expand All @@ -112,13 +146,24 @@ privileged void __sigenter_freebsd(int sig, struct siginfo_freebsd *freebsdinfo,
ctx->uc_mcontext.mc_rip = g.uc.uc_mcontext.rip;
ctx->uc_mcontext.mc_rsp = g.uc.uc_mcontext.rsp;
__repmovsb(&ctx->uc_mcontext.mc_fpstate, &g.uc.__fpustate, 512);
#endif /* __x86_64__ */

#ifdef __aarch64__
__memcpy(&ctx->uc_mcontext.mc_gpregs, g.uc.uc_mcontext.regs, 34 * 8);
struct fpsimd_context *vc =
(struct fpsimd_context *)g.uc.uc_mcontext.__reserved;
if (vc->head.magic == FPSIMD_MAGIC) {
ctx->uc_mcontext.mc_flags |= _MC_FP_VALID;
ctx->uc_mcontext.mc_fpregs.fp_sr = vc->fpsr;
ctx->uc_mcontext.mc_fpregs.fp_cr = vc->fpcr;
__memcpy(ctx->uc_mcontext.mc_fpregs.fp_q, vc->vregs, 32 * 16);
}
#endif /* __aarch64__ */

// done
}
}
/*
* When the FreeBSD kernel invokes this signal handler it pushes a
* trampoline on the stack which does two things: 1) it calls this
* function, and 2) calls sys_sigreturn() once this returns.
*/
// When the FreeBSD kernel invokes this signal handler it pushes a
// trampoline on the stack which does two things: 1) it calls this
// function, and 2) calls sys_sigreturn() once this returns.
}

#endif /* __x86_64__ */
25 changes: 25 additions & 0 deletions libc/calls/struct/ucontext-freebsd.internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,30 @@
#define COSMOPOLITAN_LIBC_CALLS_STRUCT_UCONTEXT_FREEBSD_INTERNAL_H_
COSMOPOLITAN_C_START_

struct gpregs_freebsd_aarch64 {
int64_t gp_x[30];
int64_t gp_lr;
int64_t gp_sp;
int64_t gp_elr; /* pc */
uint64_t gp_spsr; /* pstate or cpsr */
};

struct fpregs_freebsd_aarch64 {
uint128_t fp_q[32];
uint32_t fp_sr;
uint32_t fp_cr;
int fp_flags;
int fp_pad;
};

struct stack_freebsd {
void *ss_sp;
uint64_t ss_size;
int32_t ss_flags;
};

struct mcontext_freebsd {
#ifdef __x86_64__
int64_t mc_onstack;
int64_t mc_rdi;
int64_t mc_rsi;
Expand Down Expand Up @@ -47,6 +64,14 @@ struct mcontext_freebsd {
int64_t mc_xfpustate;
int64_t mc_xfpustate_len;
int64_t mc_spare[4];
#elif defined(__aarch64__)
struct gpregs_freebsd_aarch64 mc_gpregs;
struct fpregs_freebsd_aarch64 mc_fpregs;
int mc_flags;
#define _MC_FP_VALID 0x1 /* Set when mc_fpregs has valid data */
int mc_pad; /* Padding */
uint64_t mc_spare[8]; /* Space for expansion, set to zero */
#endif
};

struct ucontext_freebsd {
Expand Down
5 changes: 5 additions & 0 deletions libc/crt/crt.S
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,11 @@ _start:
////////////////////////////////////////////////////////////////////////////////
#elif defined(__aarch64__)

#if SupportsFreebsd()
// save first arg
mov x3,x0
#endif

// save original stack pointer
// this is the first argument to cosmo() below
mov x0,sp
Expand Down
4 changes: 3 additions & 1 deletion libc/dce.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/
#define SUPPORT_VECTOR 255
#else
#define SUPPORT_VECTOR (_HOSTLINUX | _HOSTXNU)
#define SUPPORT_VECTOR (_HOSTLINUX | _HOSTXNU | _HOSTFREEBSD)
#endif
#endif

Expand Down Expand Up @@ -62,8 +62,10 @@
#endif

#ifdef __aarch64__
#define IsAarch64() 1
#define IsXnuSilicon() IsXnu()
#else
#define IsAarch64() 0
#define IsXnuSilicon() 0
#endif

Expand Down
16 changes: 8 additions & 8 deletions libc/intrin/exit.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,12 @@ wontreturn void _Exit(int exitcode) {
: "rcx", "r11", "memory");
#elif defined(__aarch64__)
register long x0 asm("x0") = exitcode;
asm volatile("mov\tx8,%0\n\t"
"mov\tx16,%1\n\t"
register long x8 asm("x8") = IsLinux() ? 94 : 1;
asm volatile("mov\tx16,%1\n\t"
"svc\t0"
: /* no outputs */
: "i"(94), "i"(1), "r"(x0)
: "x8", "x16", "memory");
: "r"(x8), "i"(1), "r"(x0)
: "x16", "memory");
#else
#error "unsupported architecture"
#endif
Expand All @@ -77,12 +77,12 @@ wontreturn void _Exit(int exitcode) {
: "rcx", "r11", "memory");
#else
register long r0 asm("x0") = exitcode;
asm volatile("mov\tx8,%0\n\t"
"mov\tx16,%1\n\t"
register long x8 asm("x8") = IsLinux() ? 93 : 431;
asm volatile("mov\tx16,%1\n\t"
"svc\t0"
: /* no outputs */
: "i"(93), "i"(0x169), "r"(r0)
: "x8", "memory");
: "r"(x8), "i"(0x169), "r"(r0)
: "memory");
#endif
} else if (IsWindows()) {
uint32_t waitstatus;
Expand Down
28 changes: 21 additions & 7 deletions libc/intrin/exit1.greg.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,27 @@ wontreturn void _Exit1(int rc) {
}
notpossible;
#elif defined(__aarch64__)
if (IsLinux()) {
register long r0 asm("x0") = rc;
asm volatile("mov\tx8,%0\n\t"
"svc\t0"
: /* no outputs */
: "i"(93), "r"(r0)
: "x8", "memory");
if (IsLinux() || IsFreebsd()) {
register int x0 asm("x0") = rc;
register int x8 asm("x8");
if (IsLinux()) {
x8 = 93; // exit
} else if (IsFreebsd()) {
x8 = 431; // thr_exit
} else {
__builtin_unreachable();
}
asm volatile("svc\t0" : "+r"(x0) : "r"(x8) : "memory");
if (SupportsFreebsd()) {
// On FreeBSD, thr_exit() fails if the current thread is orphaned.
// In that case we're really better off just calling plain _exit()
x0 = rc;
asm volatile("mov\tx8,#1\n\t"
"svc\t0"
: /* no outputs */
: "r"(x0)
: "memory");
}
} else if (IsXnu()) {
__syslib->__pthread_exit(0);
}
Expand Down
Loading

0 comments on commit 83107f7

Please sign in to comment.