SchOS/ports/musl/patches/0001-schunix-tls.patch
Nexoniarz d0f7acf9eb Initial commit: Schunix as it stands before the SchOS rename
An x86-64 operating system built from xv6, now largely rewritten: SMP,
a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF
rasteriser, and a Linux-numbered syscall ABI.

No history before this point -- the tree was never under version control.
This commit exists so the rename that follows has something to undo to.
2026-08-09 13:47:01 +02:00

133 lines
4.9 KiB
Diff

From: Schunix Project <kernel@schunix.org>
Subject: [PATCH] schunix: TLS via global, mallocng decls, optional malloc tracing
Three local changes to musl 1.2.5, kept in one patch because they are all
"make musl work on Schunix" and share a lifetime.
1. arch/x86_64/pthread_arch.h, src/env/__init_tls.c - TLS.
Schunix's kernel saves/restores FS_BASE at the syscall boundary, so
arch_prctl(ARCH_SET_FS) is safe from userspace. __get_tp() is redirected
through a global uintptr_t (__schunix_tp) set at the START of __init_tp(),
before __set_thread_area() is called. The rest of __init_tp() runs
normally so td->locale and the other pthread fields still initialise.
2. src/malloc/mallocng/glue.h - build fix, NOT optional.
mallocng #defines mmap/madvise/mremap to the __-prefixed internals but
does not declare them in this configuration; without these prototypes the
freestanding build gets implicit declarations and the wrong ABI. This had
been applied by hand to the build tree and was MISSING from this patch
file, so any 'make distclean' would have silently lost it.
3. src/malloc/mallocng/meta.h, malloc.c - diagnostics, inert by default.
get_meta()/alloc_group() tracing that dumps group/meta pointers to fd 2,
entirely inside #ifdef SCHUNIX_MALLOC_DEBUG, which nothing defines. Kept
because this is the instrumentation that resolved the boot-crash
investigation in docs/architecture/kernel-history.md section 1; build
with -DSCHUNIX_MALLOC_DEBUG to re-enable.
--- a/arch/x86_64/pthread_arch.h 2024-03-01 03:07:33.000000000 +0100
+++ b/arch/x86_64/pthread_arch.h 2026-08-01 19:11:51.533102649 +0200
@@ -1,8 +1,13 @@
+#ifdef __SCHUNIX__
+extern uintptr_t __schunix_tp;
+static inline uintptr_t __get_tp() { return __schunix_tp; }
+#else
static inline uintptr_t __get_tp()
{
uintptr_t tp;
__asm__ ("mov %%fs:0,%0" : "=r" (tp) );
return tp;
}
+#endif
#define MC_PC gregs[REG_RIP]
--- a/src/env/__init_tls.c 2024-03-01 03:07:33.000000000 +0100
+++ b/src/env/__init_tls.c 2026-08-01 19:11:54.666345585 +0200
@@ -11,10 +11,19 @@
volatile int __thread_list_lock;
+#ifdef __SCHUNIX__
+uintptr_t __schunix_tp;
+#endif
+
int __init_tp(void *p)
{
pthread_t td = p;
td->self = td;
+ // Set __schunix_tp for __get_tp() before calling __set_thread_area.
+ // The kernel now correctly saves/restores FS_BASE at the syscall boundary.
+#ifdef __SCHUNIX__
+ __schunix_tp = (uintptr_t)TP_ADJ(p);
+#endif
int r = __set_thread_area(TP_ADJ(p));
if (r < 0) return -1;
if (!r) libc.can_do_threads = 1;
--- a/src/malloc/mallocng/glue.h 2024-03-01 03:07:33.000000000 +0100
+++ b/src/malloc/mallocng/glue.h 2026-08-01 19:11:57.018230131 +0200
@@ -35,6 +35,10 @@
#define brk(p) ((uintptr_t)__syscall(SYS_brk, p))
+void *__mmap(void *, size_t, int, int, int, off_t);
+int __madvise(void *, size_t, int);
+void *__mremap(void *, size_t, size_t, int, ...);
+
#define mmap __mmap
#define madvise __madvise
#define mremap __mremap
--- a/src/malloc/mallocng/meta.h 2024-03-01 03:07:33.000000000 +0100
+++ b/src/malloc/mallocng/meta.h 2026-08-01 19:11:57.041611644 +0200
@@ -6,6 +6,24 @@
#include <limits.h>
#include "glue.h"
+#ifdef SCHUNIX_MALLOC_DEBUG
+static void schunix_hex(char *out, uint64_t v) {
+ static const char digits[] = "0123456789abcdef";
+ for (int i = 15; i >= 0; i--) { out[i] = digits[v & 0xf]; v >>= 4; }
+}
+static void schunix_dbg(const char *tag, uint64_t a, uint64_t b, uint64_t c) {
+ char buf[128];
+ int n = 0;
+ buf[n++]='['; buf[n++]='D'; buf[n++]='B'; buf[n++]='G'; buf[n++]=']'; buf[n++]=' ';
+ for (const char *p = tag; *p; p++) buf[n++] = *p;
+ buf[n++]=' ';
+ schunix_hex(buf+n, a); n += 16; buf[n++]=' ';
+ schunix_hex(buf+n, b); n += 16; buf[n++]=' ';
+ schunix_hex(buf+n, c); n += 16; buf[n++]='\n';
+ __syscall(SYS_write, 2, buf, n);
+}
+#endif
+
__attribute__((__visibility__("hidden")))
extern const uint16_t size_classes[];
@@ -138,6 +156,14 @@
}
const struct group *base = (const void *)(p - UNIT*offset - UNIT);
const struct meta *meta = base->meta;
+#ifdef SCHUNIX_MALLOC_DEBUG
+ schunix_dbg("get_meta p", (uint64_t)p, (uint64_t)offset, (uint64_t)index);
+ {
+ volatile uint64_t *rawbase = (volatile uint64_t *)base;
+ schunix_dbg("get_meta RAW reread base[0..2]", rawbase[0], rawbase[1], rawbase[2]);
+ }
+ schunix_dbg("get_meta base/meta/meta->mem", (uint64_t)base, (uint64_t)meta, (uint64_t)meta->mem);
+#endif
assert(meta->mem == base);
assert(index <= meta->last_idx);
assert(!(meta->avail_mask & (1u<<index)));
--- a/src/malloc/mallocng/malloc.c 2024-03-01 03:07:33.000000000 +0100
+++ b/src/malloc/mallocng/malloc.c 2026-08-01 19:11:57.026224498 +0200
@@ -280,6 +280,10 @@
m->last_idx = cnt-1;
m->freeable = 1;
m->sizeclass = sc;
+#ifdef SCHUNIX_MALLOC_DEBUG
+ schunix_dbg("alloc_group p/m/cnt", (uint64_t)p, (uint64_t)m, (uint64_t)cnt);
+ schunix_dbg("alloc_group readback mem->meta", (uint64_t)m->mem, (uint64_t)m->mem->meta, (uint64_t)sc);
+#endif
return m;
}