Introduce FreeBSD ARM64 support

It's 100% passing test fleet. Solid as a rock.
This commit is contained in:
Justine Tunney 2023-12-29 20:11:23 -08:00
parent 43fe5956ad
commit 83107f78ed
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
455 changed files with 778 additions and 551 deletions

View file

@ -231,60 +231,6 @@ static errno_t CloneXnu(int (*fn)(void *), char *stk, size_t stksz, int flags,
return sys_clone_xnu(fn, arg, wt, 0, PTHREAD_START_CUSTOM_XNU);
}
////////////////////////////////////////////////////////////////////////////////
// FREE BESIYATA DISHMAYA
static wontreturn void FreebsdThreadMain(void *p) {
struct CloneArgs *wt = p;
*wt->ctid = wt->tid;
wt->func(wt->arg, wt->tid);
// we no longer use the stack after this point
// void thr_exit(%rdi = long *state);
asm volatile("movl\t$0,%0\n\t" // *wt->ztid = 0
"syscall\n\t" // _umtx_op(wt->ztid, WAKE, INT_MAX)
"movl\t$431,%%eax\n\t" // thr_exit(long *nonzeroes_and_wake)
"xor\t%%edi,%%edi\n\t" // sad we can't use this free futex op
"syscall\n\t" // exit1() fails if thread is orphaned
"movl\t$1,%%eax\n\t" // exit()
"syscall" //
: "=m"(*wt->ztid)
: "a"(454), "D"(wt->ztid), "S"(UMTX_OP_WAKE), "d"(INT_MAX)
: "rcx", "r8", "r9", "r10", "r11", "memory");
__builtin_unreachable();
}
static errno_t CloneFreebsd(int (*func)(void *, int), char *stk, size_t stksz,
int flags, void *arg, void *tls, int *ptid,
int *ctid) {
int ax;
bool failed;
int64_t tid;
struct CloneArgs *wt;
wt = AllocateCloneArgs(stk, stksz);
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->tls = tls;
wt->func = func;
wt->arg = arg;
struct thr_param params = {
.start_func = FreebsdThreadMain,
.arg = wt,
.stack_base = stk,
.stack_size = (uintptr_t)wt - (uintptr_t)stk,
.tls_base = flags & CLONE_SETTLS ? tls : 0,
.tls_size = 64,
.child_tid = &wt->tid64,
.parent_tid = &tid,
};
asm volatile(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(failed), "=a"(ax)
: "1"(__NR_thr_new), "D"(&params), "S"(sizeof(params))
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory");
if (failed) return ax;
if (flags & CLONE_PARENT_SETTID) *ptid = tid;
return 0;
}
////////////////////////////////////////////////////////////////////////////////
// OPEN BESIYATA DISHMAYA
@ -441,6 +387,95 @@ static int CloneNetbsd(int (*func)(void *, int), char *stk, size_t stksz,
#endif /* __x86_64__ */
////////////////////////////////////////////////////////////////////////////////
// FREE BESIYATA DISHMAYA
void bone(struct CloneArgs *wt) {
*wt->ztid = 0;
}
static wontreturn void FreebsdThreadMain(void *p) {
struct CloneArgs *wt = p;
#ifdef __aarch64__
asm volatile("mov\tx28,%0" : /* no outputs */ : "r"(wt->tls));
#endif
*wt->ctid = wt->tid;
wt->func(wt->arg, wt->tid);
// we no longer use the stack after this point
// void thr_exit(%rdi = long *state);
#ifdef __x86_64__
asm volatile("movl\t$0,%0\n\t" // *wt->ztid = 0
"syscall\n\t" // _umtx_op(wt->ztid, WAKE, INT_MAX)
"movl\t$431,%%eax\n\t" // thr_exit(long *nonzeroes_and_wake)
"xor\t%%edi,%%edi\n\t" // sad we can't use this free futex op
"syscall\n\t" // thr_exit() fails if thread is orphaned
"movl\t$1,%%eax\n\t" // _exit()
"syscall" //
: "=m"(*wt->ztid)
: "a"(454), "D"(wt->ztid), "S"(UMTX_OP_WAKE), "d"(INT_MAX)
: "rcx", "r8", "r9", "r10", "r11", "memory");
#elif defined(__aarch64__)
register long x0 asm("x0") = (long)wt->ztid;
register long x1 asm("x1") = UMTX_OP_WAKE;
register long x2 asm("x2") = INT_MAX;
register long x8 asm("x8") = 454; // _umtx_op
asm volatile("str\twzr,%0\n\t" // *wt->ztid = 0
"svc\t0\n\t" // _umtx_op(wt->ztid, WAKE, INT_MAX)
"mov\tx0,#0\n\t" // arg0 = 0
"mov\tx8,#431\n\t" // thr_exit
"svc\t0\n\t" // thr_exit(long *nonzeroes_and_wake = 0)
"mov\tx8,#1\n\t" // _exit
"svc\t0" // _exit(long *nonzeroes_and_wake = 0)
: "=m"(*wt->ztid)
: "r"(x0), "r"(x1), "r"(x2), "r"(x8));
#else
#error "unsupported architecture"
#endif
__builtin_unreachable();
}
static errno_t CloneFreebsd(int (*func)(void *, int), char *stk, size_t stksz,
int flags, void *arg, void *tls, int *ptid,
int *ctid) {
int64_t tid;
struct CloneArgs *wt;
wt = AllocateCloneArgs(stk, stksz);
wt->ctid = flags & CLONE_CHILD_SETTID ? ctid : &wt->tid;
wt->ztid = flags & CLONE_CHILD_CLEARTID ? ctid : &wt->tid;
wt->tls = tls;
wt->func = func;
wt->arg = arg;
struct thr_param params = {
.start_func = FreebsdThreadMain,
.arg = wt,
.stack_base = stk,
.stack_size = (uintptr_t)wt - (uintptr_t)stk,
.tls_base = flags & CLONE_SETTLS ? tls : 0,
.tls_size = 64,
.child_tid = &wt->tid64,
.parent_tid = &tid,
};
#ifdef __x86_64__
int ax;
bool failed;
asm volatile(CFLAG_ASM("syscall")
: CFLAG_CONSTRAINT(failed), "=a"(ax)
: "1"(__NR_thr_new), "D"(&params), "S"(sizeof(params))
: "rcx", "rdx", "r8", "r9", "r10", "r11", "memory");
if (failed) return ax;
#elif defined(__aarch64__)
register long x0 asm("x0") = (long)&params;
register long x1 asm("x1") = sizeof(params);
register int x8 asm("x8") = 0x1c7; // thr_new
asm volatile("svc\t0" : "+r"(x0) : "r"(x1), "r"(x8) : "memory");
if (x0) return x0;
#else
#error "unsupported architecture"
#endif
if (flags & CLONE_PARENT_SETTID) *ptid = tid;
return 0;
}
#ifdef __aarch64__
////////////////////////////////////////////////////////////////////////////////
@ -675,9 +710,9 @@ errno_t clone(void *func, void *stk, size_t stksz, int flags, void *arg,
#else
#error "unsupported architecture"
#endif
#ifdef __x86_64__
} else if (IsFreebsd()) {
rc = CloneFreebsd(func, stk, stksz, flags, arg, tls, ptid, ctid);
#ifdef __x86_64__
} else if (IsNetbsd()) {
rc = CloneNetbsd(func, stk, stksz, flags, arg, tls, ptid, ctid);
} else if (IsOpenbsd()) {