aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile20
-rwxr-xr-xbin/status4
-rwxr-xr-xbin/updatedirs3
-rw-r--r--include/rt.h15
-rw-r--r--include/u.h5
-rw-r--r--rules.mk22
-rw-r--r--share/dynamic.mk8
-rw-r--r--src/base/coro/rules.mk6
-rw-r--r--src/base/flate/internal.h2
-rw-r--r--src/base/gz/internal.h3
-rw-r--r--src/libfmt/do.c10
-rw-r--r--src/libutf/vendor/mkrunetype.c2
-rw-r--r--sys.mk14
-rwxr-xr-xsys/gen.py48
-rw-r--r--sys/linux/amd64/arch/atomic.h123
-rw-r--r--sys/linux/arm/arch/atomic.h107
-rw-r--r--sys/linux/arm64/arch/atomic.h82
-rw-r--r--sys/linux/i386/arch/atomic.h108
-rw-r--r--sys/linux/riscv64/arch/atomic.h38
-rw-r--r--sys/rt/amd64/crt1.s21
-rw-r--r--sys/rt/amd64/crti.s17
-rw-r--r--sys/rt/amd64/crtn.s9
-rw-r--r--sys/rt/amd64/rt1.s9
-rw-r--r--sys/rt/amd64/rti.s9
-rw-r--r--sys/rt/amd64/rtn.s7
-rw-r--r--sys/rt/arm/rt1.s11
-rw-r--r--sys/rt/arm/rti.s13
-rw-r--r--sys/rt/arm/rtn.s9
-rw-r--r--sys/rt/arm64/rt1.s10
-rw-r--r--sys/rt/arm64/rti.s13
-rw-r--r--sys/rt/arm64/rtn.s7
-rw-r--r--sys/rt/boot.c57
-rw-r--r--sys/rt/context.c4
-rw-r--r--sys/rt/dummy.c6
-rw-r--r--sys/rt/env.c3
-rw-r--r--sys/rt/exit.c22
-rw-r--r--sys/rt/i386/rt1.s14
-rw-r--r--sys/rt/i386/rti.s9
-rw-r--r--sys/rt/i386/rtn.s7
-rw-r--r--sys/rt/include/rt.h12
-rw-r--r--sys/rt/riscv64/rt1.s0
-rw-r--r--sys/rt/riscv64/rti.s0
-rw-r--r--sys/rt/riscv64/rtn.s0
-rw-r--r--sys/rt/stack.c17
-rw-r--r--sys/rt/thunk.c17
-rw-r--r--sys/rules.mk55
46 files changed, 834 insertions, 144 deletions
diff --git a/Makefile b/Makefile
index 1a48db3..793d888 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@ MAKEFLAGS += --no-builtin-variables
# Compiler, Linker, and Assembler
CC := gcc
AR := ar
-AS := nasm
+AS := gcc
PKG := PKG_CONFIG_PATH=lib/pkgconfig pkg-config
OS := linux
@@ -22,26 +22,26 @@ SRC_DIR := src
OBJ_DIR := obj
TST_DIR := test
-# C runtime library
-CINIT := $(LIB_DIR)/crt/crt1.o $(LIB_DIR)/crt/x86_64/crti.o `gcc --print-file-name=crtbeginS.o`
-CFINI := `gcc --print-file-name=crtendS.o` $(LIB_DIR)/crt/x86_64/crtn.o
+# runtime library
+INIT = $(RT1) $(RTI) `gcc --print-file-name=crtbeginT.o`
+FINI = `gcc --print-file-name=crtend.o` $(RTN) $(RT3)
# Flags, Libraries and Includes
CFLAGS := -g -march=native -fno-strict-aliasing -fwrapv -fms-extensions -Wno-microsoft-anon-tag
-STATIC := -nodefaultlibs -nostartfiles -nostdinc -static
-AFLAGS := -f elf64
+STATIC := -ffreestanding -nodefaultlibs -nostartfiles -nostdinc -static
+AFLAGS := -g
INCS := -I $(SYS_DIR)/$(OS)/$(ARCH) -I $(SYS_DIR)/$(OS)/port -I $(INC_DIR) -isystem $(INC_DIR)/vendor/libc
ELIBS := -L$(LIB_DIR) -lc
# Named generic rules (must be evaluated lazily)
COMPILE = @echo "CC "$(@:$(OBJ_DIR)/%=%);\
- $(CC) -MD $(CFLAGS) $(TCFLAGS) $(INCS) $(TINCS) -o $@ -c $<
+ $(CC) -MD $(CFLAGS) $(STATIC) $(TCFLAGS) $(INCS) $(TINCS) -o $@ -c $<
LINK = @echo "LD "$(@:$(OBJ_DIR)/%=%);\
- $(CC) -MD $(CFLAGS) $(STATIC) $(TCFLAGS) -o $@ $(CINIT) $< $(CFINI) $(TLIBS) $(ELIBS)
+ $(CC) -MD $(CFLAGS) $(STATIC) $(TCFLAGS) -o $@ $(INIT) $< $(TLIBS) $(ELIBS) $(FINI)
COMPLINK = @echo "CC "$(@:$(OBJ_DIR)/%=%);\
- $(CC) -MD $(CFLAGS) $(STATIC) $(TCFLAGS) $(INCS) $(TINCS) -o $@ $(CINIT) $^ $(CFINI) $(TLIBS) $(ELIBS)
+ $(CC) -MD $(CFLAGS) $(STATIC) $(TCFLAGS) $(INCS) $(TINCS) -o $@ $(INIT) $^ $(TLIBS) $(ELIBS) $(FINI)
ASSEMBLE = @echo "AS "$(@:$(OBJ_DIR)/%=%);\
- $(AS) $(AFLAGS) $(TCFLAGS) -o $@ $<
+ $(AS) $(AFLAGS) -o $@ -c $<
ARCHIVE = @echo "AR "$(@:$(OBJ_DIR)/%=%);\
$(AR) crs $@ $^
diff --git a/bin/status b/bin/status
index 7e406d1..9643e39 100755
--- a/bin/status
+++ b/bin/status
@@ -7,7 +7,7 @@ cpu() {
}
mail() {
- NEWMAIL=$(expr $(ls -1 ~/mail/*/INBOX/new | wc -l) - 5)
+ NEWMAIL=$(expr $(ls -1 ~/mail/*/INBOX/new | wc -l) - 7)
if [ "${NEWMAIL%% *}" -eq 0 ]; then
printf " (%s)" "${NEWMAIL%% *}"
@@ -71,7 +71,7 @@ ipaddr() {
}
dostatus() {
- exec xsetroot -name "$VOL│$BAT│$MEM│$IP│$CPU│$NML│$WTR│$TIM"
+ exec xsetroot -name "$VOL│$MEM│$IP│$CPU│$NML│$WTR│$TIM" &
}
# signal handlers
diff --git a/bin/updatedirs b/bin/updatedirs
index 2b90ee4..663c51a 100755
--- a/bin/updatedirs
+++ b/bin/updatedirs
@@ -14,6 +14,9 @@ if __name__ == "__main__":
if not os.path.exists(f"{BUILD}/sys"):
os.mkdir(f"{BUILD}/sys")
+ if not os.path.exists(f"{BUILD}/rt"):
+ os.mkdir(f"{BUILD}/rt")
+
if not os.path.exists(TEST):
os.mkdir(TEST)
diff --git a/include/rt.h b/include/rt.h
new file mode 100644
index 0000000..43357cd
--- /dev/null
+++ b/include/rt.h
@@ -0,0 +1,15 @@
+#pragma once
+
+extern struct rt·Context
+{
+ void (*fini)(void);
+ void (*exit)(void);
+
+ uintptr *auxv;
+ uintptr pagesize;
+ uintptr sysinfo;
+} rt·context;
+
+extern char **rt·environ;
+
+void noreturn rt·exit(int code);
diff --git a/include/u.h b/include/u.h
index 333d6b2..d415d82 100644
--- a/include/u.h
+++ b/include/u.h
@@ -108,6 +108,11 @@ typedef __builtin_va_list va_list;
// ------------------------------------------------------------------
// global macros
+/* weak aliasing */
+#define noreturn _Noreturn
+#define hidden __attribute__((__visibility__("hidden")))
+#define weakalias(old, new) extern __typeof(old) new __attribute__((weak, alias(#old)))
+
/* offsets */
#define offsetof(t, d) __builtin_offsetof(t, d)
diff --git a/rules.mk b/rules.mk
index e03a1c4..8c7bb2c 100644
--- a/rules.mk
+++ b/rules.mk
@@ -1,5 +1,5 @@
# Standard housekeeping
-.PHONY: all debug release clean target install
+.PHONY: all debug release system bins libs tests clean target install
.SUFFIXES:
all: targets
@@ -27,10 +27,6 @@ TEST :=
GENS :=
-# iterate through source directory tree
-DIR := src
-include $(DIR)/rules.mk
-
# generic rules
%.a: %.o
$(ARCHIVE)
@@ -39,9 +35,10 @@ include $(DIR)/rules.mk
$(LINK)
# explicit system layer
-include sys.mk
+DIR := sys
+include $(DIR)/rules.mk
-# rules for userland
+# userland rules
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
$(COMPILE)
@@ -51,11 +48,18 @@ $(OBJ_DIR)/%.o: $(SRC_DIR)/%.s
$(OBJ_DIR)/%: $(SRC_DIR)/%.c
$(COMPLINK)
-targets: $(SYS) $(LIBS) $(BINS) $(TEST)
+# iterate through source directory tree
+DIR := src
+include $(DIR)/rules.mk
+
+system: $(RUNTIME)
+bins: system $(BINS)
+tests: system $(TEST)
+targets: libs bins tests
clean:
@echo removing system layer
- @rm -f $(SYS_OBJS) $(OBJ_DIR)/sys/sys.a
+ @rm -f $(SYS_OBJS) $(SYS) $(RT) $(RT_OBJS) $(RT1) $(RTI) $(RTN)
@echo removing object files
@rm -f $(OBJS)
@echo removing dependency files
diff --git a/share/dynamic.mk b/share/dynamic.mk
index 66065a5..b7ec24d 100644
--- a/share/dynamic.mk
+++ b/share/dynamic.mk
@@ -1,11 +1,11 @@
$(BINS_$(d)): STATIC =
-$(BINS_$(d)): CINIT =
-$(BINS_$(d)): CFINI =
+$(BINS_$(d)): INIT =
+$(BINS_$(d)): FINI =
$(BINS_$(d)): ELIBS =
$(BINS_$(d)): INCS = -I $(SYS_DIR)/$(OS)/$(ARCH) -I $(SYS_DIR)/$(OS)/port -I $(INC_DIR)
$(TEST_$(d)): STATIC =
-$(TEST_$(d)): CINIT =
-$(TEST_$(d)): CFINI =
+$(TEST_$(d)): INIT =
+$(TEST_$(d)): FINI =
$(TEST_$(d)): ELIBS =
$(TEST_$(d)): INCS = -I $(SYS_DIR)/$(OS)/$(ARCH) -I $(SYS_DIR)/$(OS)/port -I $(INC_DIR)
diff --git a/src/base/coro/rules.mk b/src/base/coro/rules.mk
index c2ee89f..d23bfd0 100644
--- a/src/base/coro/rules.mk
+++ b/src/base/coro/rules.mk
@@ -1,3 +1,3 @@
-SRCS_$(d)+=\
- $(d)/coro/coro.c\
- $(d)/coro/unix_x64.s\
+# SRCS_$(d)+=\
+# $(d)/coro/coro.c\
+# $(d)/coro/unix_x64.s\
diff --git a/src/base/flate/internal.h b/src/base/flate/internal.h
index 794c7c2..a926ed7 100644
--- a/src/base/flate/internal.h
+++ b/src/base/flate/internal.h
@@ -3,7 +3,7 @@
#include <u.h>
#include <base.h>
-#include <zlib.h>
+#include <vendor/zlib.h>
typedef struct buffer
{
diff --git a/src/base/gz/internal.h b/src/base/gz/internal.h
index 6a268c4..0e71db0 100644
--- a/src/base/gz/internal.h
+++ b/src/base/gz/internal.h
@@ -2,5 +2,4 @@
#include <u.h>
#include <base.h>
-
-#include <zlib.h>
+#include <vendor/zlib.h>
diff --git a/src/libfmt/do.c b/src/libfmt/do.c
index eaac0a3..bd2e65c 100644
--- a/src/libfmt/do.c
+++ b/src/libfmt/do.c
@@ -1,10 +1,8 @@
#include "internal.h"
-#include <stdatomic.h>
+#include <arch/atomic.h>
-#define atomic _Atomic
#define MaxFmt 128
-#define atomic·load atomic_load
-#define atomic·store atomic_store
+#define atomic·load(p) (*(p))
// -----------------------------------------------------------------------
// globals
@@ -25,11 +23,11 @@ static int badfmt(fmt·State *);
static struct
{
- atomic int len;
+ volatile int len;
Verb verb[MaxFmt];
} formatter =
{
- ATOMIC_VAR_INIT(30),
+ 30,
{
{' ', fmtflag},
{'#', fmtflag},
diff --git a/src/libutf/vendor/mkrunetype.c b/src/libutf/vendor/mkrunetype.c
index 9f939f4..b33df32 100644
--- a/src/libutf/vendor/mkrunetype.c
+++ b/src/libutf/vendor/mkrunetype.c
@@ -385,4 +385,6 @@ main(int argc, char *argv[])
mkto("upper", table.toupper, 1, 0);
mkto("lower", table.tolower, 1, 0);
mkto("title", table.totitle, 1, 0);
+
+ return 0;
}
diff --git a/sys.mk b/sys.mk
deleted file mode 100644
index b4f0bf6..0000000
--- a/sys.mk
+++ /dev/null
@@ -1,14 +0,0 @@
-SYS := $(OBJ_DIR)/sys/sys.a
-
-SYS_SRCS := $(sort $(wildcard $(SYS_DIR)/src/*.c))
-
-SYS_OBJS := $(filter %.o, $(SYS_SRCS:.c=.o))
-SYS_OBJS := $(patsubst $(SYS_DIR)/src/%, $(OBJ_DIR)/$(SYS_DIR)/%, $(SYS_OBJS))
-
-# rules for kernel interface
-$(OBJ_DIR)/$(SYS_DIR)/%.o: TINCS = -I $(SYS_DIR)/$(OS)/$(ARCH)
-$(OBJ_DIR)/$(SYS_DIR)/%.o: $(SYS_DIR)/src/%.c
- $(COMPILE)
-
-$(SYS): $(SYS_OBJS)
- $(ARCHIVE)
diff --git a/sys/gen.py b/sys/gen.py
index 02ff952..4dcbc4d 100755
--- a/sys/gen.py
+++ b/sys/gen.py
@@ -289,6 +289,44 @@ def fmtsyscallold(writer, musl):
print(f"# {word[0][1:]:<8}{name[0]:<10} {name[1]}", file=writer)
# ------------------------------------------------------------------------
+# atomic
+
+def snaketolower(name):
+ return "".join(w for w in name.split("_"))
+
+def modifytype(line):
+ return line.replace("uint64_t", "uint64").replace("uint32_t", "uint32").replace("uintptr_t","uintptr")
+
+def fmtatomic(writer, reader):
+ def fmt(name):
+ prefix = ""
+ index = name.find("a_")
+ if index > 0:
+ prefix = name[:index]
+
+ name = name[index:]
+ name = name.replace("a_", "")
+ return prefix + "atomic·" + snaketolower(name)
+
+ for line in reader:
+ word = [modifytype(w) for w in line.split(" ")]
+ if len(word) == 3:
+ if word[0].strip() == "#define" and word[1].strip() == word[2].strip():
+ continue
+ if len(word) == 2:
+ if word[0].strip() == "#define" and "libc.h" in word[1]:
+ continue
+
+ ours = [ fmt(w) if "a_" in w else w for w in word ]
+ line = " ".join(ours)
+ line = line.replace("static inline void ", "static inline void\n")\
+ .replace("static inline int ", "static inline int\n")\
+ .replace("if (", "if(").replace("for (", "for(").replace("while (", "while(")\
+ .replace("do {", "do{").replace("} while", "}while").replace(") {", "){")
+
+ print(line, file=writer, end="")
+
+# ------------------------------------------------------------------------
# types
stdintdefs=[
@@ -384,6 +422,10 @@ if __name__ == "__main__":
with open(f"{libnarch}/bits.h", "w") as io:
fmtbits(io, musl, source)
+ print("--> emitting atomics", file=stderr)
+ with open(f"{musl}/atomic_arch.h") as reader, open(f"{libnarch}/atomic.h", "w") as writer:
+ fmtatomic(writer,reader)
+
print("--> emitting syscalls", file=stderr)
with open(f"{libn}/syscall.h", "w") as io:
fmtsyscall(io,musl)
@@ -394,17 +436,17 @@ if __name__ == "__main__":
source, target = "generic", "port"
musl = f"{muslroot}/arch/{source}"
- libn = f"linux/{target}/arch"
+ libn = f"linux/{target}/os"
mkpath(libnarch, exist_ok=True)
with open(f"{libn}/errno.h","w") as io:
fmterrno(io, musl)
musl = f"{muslroot}/src/errno"
- libn = "src/errno.inc.h"
+ libn = "linux/src/errno.inc.h"
with open(libn,"w") as io:
fmtstrerror(io, musl)
- libn = "src/internal.h"
+ libn = "linux/src/internal.h"
musl = f"{muslroot}/src/internal/syscall.h"
needfix = False
diff --git a/sys/linux/amd64/arch/atomic.h b/sys/linux/amd64/arch/atomic.h
new file mode 100644
index 0000000..b3aeed1
--- /dev/null
+++ b/sys/linux/amd64/arch/atomic.h
@@ -0,0 +1,123 @@
+static inline int
+atomic·cas(volatile int *p, int t, int s)
+{
+ __asm__ __volatile__ (
+ "lock ; cmpxchg %3, %1"
+ : "=a"(t), "=m"(*p) : "a"(t), "r"(s) : "memory" );
+ return t;
+}
+
+static inline void
+*atomic·casp(volatile void *p, void *t, void *s)
+{
+ __asm__( "lock ; cmpxchg %3, %1"
+ : "=a"(t), "=m"(*(void *volatile *)p)
+ : "a"(t), "r"(s) : "memory" );
+ return t;
+}
+
+static inline int
+atomic·swap(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "xchg %0, %1"
+ : "=r"(v), "=m"(*p) : "0"(v) : "memory" );
+ return v;
+}
+
+static inline int
+atomic·fetchadd(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "lock ; xadd %0, %1"
+ : "=r"(v), "=m"(*p) : "0"(v) : "memory" );
+ return v;
+}
+
+static inline void
+atomic·and(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "lock ; and %1, %0"
+ : "=m"(*p) : "r"(v) : "memory" );
+}
+
+static inline void
+atomic·or(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "lock ; or %1, %0"
+ : "=m"(*p) : "r"(v) : "memory" );
+}
+
+static inline void
+atomic·and64(volatile uint64 *p, uint64 v)
+{
+ __asm__ __volatile(
+ "lock ; and %1, %0"
+ : "=m"(*p) : "r"(v) : "memory" );
+}
+
+static inline void
+atomic·or64(volatile uint64 *p, uint64 v)
+{
+ __asm__ __volatile__(
+ "lock ; or %1, %0"
+ : "=m"(*p) : "r"(v) : "memory" );
+}
+
+static inline void
+atomic·inc(volatile int *p)
+{
+ __asm__ __volatile__(
+ "lock ; incl %0"
+ : "=m"(*p) : "m"(*p) : "memory" );
+}
+
+static inline void
+atomic·dec(volatile int *p)
+{
+ __asm__ __volatile__(
+ "lock ; decl %0"
+ : "=m"(*p) : "m"(*p) : "memory" );
+}
+
+static inline void
+atomic·store(volatile int *p, int x)
+{
+ __asm__ __volatile__(
+ "mov %1, %0 ; lock ; orl $0,(%%rsp)"
+ : "=m"(*p) : "r"(x) : "memory" );
+}
+
+static inline void
+atomic·barrier()
+{
+ __asm__ __volatile__( "" : : : "memory" );
+}
+
+static inline void
+atomic·spin()
+{
+ __asm__ __volatile__( "pause" : : : "memory" );
+}
+
+static inline void
+atomic·crash()
+{
+ __asm__ __volatile__( "hlt" : : : "memory" );
+}
+
+static inline int
+atomic·ctz64(uint64 x)
+{
+ __asm__( "bsf %1,%0" : "=r"(x) : "r"(x) );
+ return x;
+}
+
+static inline int
+atomic·clz64(uint64 x)
+{
+ __asm__( "bsr %1,%0 ; xor $63,%0" : "=r"(x) : "r"(x) );
+ return x;
+}
diff --git a/sys/linux/arm/arch/atomic.h b/sys/linux/arm/arch/atomic.h
new file mode 100644
index 0000000..abb8a7b
--- /dev/null
+++ b/sys/linux/arm/arch/atomic.h
@@ -0,0 +1,107 @@
+#include "libc.h"
+
+#if __ARM_ARCH_4__ || __ARM_ARCH_4T__ || __ARM_ARCH == 4
+#define BLX "mov lr,pc\n\tbx"
+#else
+#define BLX "blx"
+#endif
+
+extern hidden uintptr __atomic·casptr, __atomic·barrierptr;
+
+#if((__ARM_ARCH_6__ || __ARM_ARCH_6K__ || __ARM_ARCH_6KZ__ || __ARM_ARCH_6ZK__) && !__thumb__) \
+ || __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+static inline int
+atomic·ll(volatile int *p)
+{
+ int v;
+ __asm__ __volatile__ ("ldrex %0, %1" : "=r"(v) : "Q"(*p));
+ return v;
+}
+
+static inline int
+atomic·sc(volatile int *p, int v)
+{
+ int r;
+ __asm__ __volatile__ ("strex %0,%2,%1" : "=&r"(r), "=Q"(*p) : "r"(v) : "memory");
+ return !r;
+}
+
+#if __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+static inline void
+atomic·barrier()
+{
+ __asm__ __volatile__ ("dmb ish" : : : "memory");
+}
+
+#endif
+
+#define atomic·prellsc atomic·barrier
+#define atomic·postllsc atomic·barrier
+
+#else
+
+static inline int
+atomic·cas(volatile int *p, int t, int s)
+{
+ for(;;){
+ register int r0 __asm__("r0") = t;
+ register int r1 __asm__("r1") = s;
+ register volatile int *r2 __asm__("r2") = p;
+ register uintptr r3 __asm__("r3") = __atomic·casptr;
+ int old;
+ __asm__ __volatile__ (
+ BLX " r3"
+ : "+r"(r0), "+r"(r3) : "r"(r1), "r"(r2)
+ : "memory", "lr", "ip", "cc" );
+ if(!r0) return t;
+ if((old=*p)!=t) return old;
+ }
+}
+
+#endif
+
+#ifndef atomic·barrier
+static inline void
+atomic·barrier()
+{
+ register uintptr ip __asm__("ip") = __atomic·barrierptr;
+ __asm__ __volatile__( BLX " ip" : "+r"(ip) : : "memory", "cc", "lr" );
+}
+#endif
+
+static inline void
+atomic·crash()
+{
+ __asm__ __volatile__(
+#ifndef __thumb__
+ ".word 0xe7f000f0"
+#else
+ ".short 0xdeff"
+#endif
+ : : : "memory");
+}
+
+#if __ARM_ARCH >= 5 && (!__thumb__ || __thumb2__)
+
+static inline int
+atomic·clz32(uint32 x)
+{
+ __asm__ ("clz %0, %1" : "=r"(x) : "r"(x));
+ return x;
+}
+
+#if __ARM_ARCH_6T2__ || __ARM_ARCH_7A__ || __ARM_ARCH_7R__ || __ARM_ARCH >= 7
+
+static inline int
+atomic·ctz32(uint32 x)
+{
+ uint32 xr;
+ __asm__ ("rbit %0, %1" : "=r"(xr) : "r"(x));
+ return atomic·clz32(xr);
+}
+
+#endif
+
+#endif
diff --git a/sys/linux/arm64/arch/atomic.h b/sys/linux/arm64/arch/atomic.h
new file mode 100644
index 0000000..2fa4b04
--- /dev/null
+++ b/sys/linux/arm64/arch/atomic.h
@@ -0,0 +1,82 @@
+static inline int
+atomic·ll(volatile int *p)
+{
+ int v;
+ __asm__ __volatile__ ("ldaxr %w0,%1" : "=r"(v) : "Q"(*p));
+ return v;
+}
+
+static inline int
+atomic·sc(volatile int *p, int v)
+{
+ int r;
+ __asm__ __volatile__ ("stlxr %w0,%w2,%1" : "=&r"(r), "=Q"(*p) : "r"(v) : "memory");
+ return !r;
+}
+
+static inline void
+atomic·barrier()
+{
+ __asm__ __volatile__ ("dmb ish" : : : "memory");
+}
+
+static inline int
+atomic·cas(volatile int *p, int t, int s)
+{
+ int old;
+ do{
+ old = atomic·ll(p);
+ if(old != t){
+ atomic·barrier();
+ break;
+ }
+ }while(!atomic·sc(p, s));
+ return old;
+}
+
+static inline void
+*atomic·llp(volatile void *p)
+{
+ void *v;
+ __asm__ __volatile__ ("ldaxr %0, %1" : "=r"(v) : "Q"(*(void *volatile *)p));
+ return v;
+}
+
+static inline int
+atomic·scp(volatile int *p, void *v)
+{
+ int r;
+ __asm__ __volatile__ ("stlxr %w0,%2,%1" : "=&r"(r), "=Q"(*(void *volatile *)p) : "r"(v) : "memory");
+ return !r;
+}
+
+static inline void
+*atomic·casp(volatile void *p, void *t, void *s)
+{
+ void *old;
+ do{
+ old = atomic·llp(p);
+ if(old != t){
+ atomic·barrier();
+ break;
+ }
+ }while(!atomic·scp(p, s));
+ return old;
+}
+
+static inline int
+atomic·ctz64(uint64 x)
+{
+ __asm__(
+ " rbit %0, %1\n"
+ " clz %0, %0\n"
+ : "=r"(x) : "r"(x));
+ return x;
+}
+
+static inline int
+atomic·clz64(uint64 x)
+{
+ __asm__("clz %0, %1" : "=r"(x) : "r"(x));
+ return x;
+}
diff --git a/sys/linux/i386/arch/atomic.h b/sys/linux/i386/arch/atomic.h
new file mode 100644
index 0000000..eab161d
--- /dev/null
+++ b/sys/linux/i386/arch/atomic.h
@@ -0,0 +1,108 @@
+static inline int
+atomic·cas(volatile int *p, int t, int s)
+{
+ __asm__ __volatile__ (
+ "lock ; cmpxchg %3, %1"
+ : "=a"(t), "=m"(*p) : "a"(t), "r"(s) : "memory" );
+ return t;
+}
+
+static inline int
+atomic·swap(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "xchg %0, %1"
+ : "=r"(v), "=m"(*p) : "0"(v) : "memory" );
+ return v;
+}
+
+static inline int
+atomic·fetchadd(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "lock ; xadd %0, %1"
+ : "=r"(v), "=m"(*p) : "0"(v) : "memory" );
+ return v;
+}
+
+static inline void
+atomic·and(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "lock ; and %1, %0"
+ : "=m"(*p) : "r"(v) : "memory" );
+}
+
+static inline void
+atomic·or(volatile int *p, int v)
+{
+ __asm__ __volatile__(
+ "lock ; or %1, %0"
+ : "=m"(*p) : "r"(v) : "memory" );
+}
+
+static inline void
+atomic·inc(volatile int *p)
+{
+ __asm__ __volatile__(
+ "lock ; incl %0"
+ : "=m"(*p) : "m"(*p) : "memory" );
+}
+
+static inline void
+atomic·dec(volatile int *p)
+{
+ __asm__ __volatile__(
+ "lock ; decl %0"
+ : "=m"(*p) : "m"(*p) : "memory" );
+}
+
+static inline void
+atomic·store(volatile int *p, int x)
+{
+ __asm__ __volatile__(
+ "mov %1, %0 ; lock ; orl $0,(%%esp)"
+ : "=m"(*p) : "r"(x) : "memory" );
+}
+
+static inline void
+atomic·barrier()
+{
+ __asm__ __volatile__( "" : : : "memory" );
+}
+
+static inline void
+atomic·spin()
+{
+ __asm__ __volatile__( "pause" : : : "memory" );
+}
+
+static inline void
+atomic·crash()
+{
+ __asm__ __volatile__( "hlt" : : : "memory" );
+}
+
+static inline int
+atomic·ctz64(uint64 x)
+{
+ int r;
+ __asm__( "bsf %1,%0 ; jnz 1f ; bsf %2,%0 ; add $32,%0\n1:"
+ : "=&r"(r) : "r"((unsigned)x), "r"((unsigned)(x>>32)) );
+ return r;
+}
+
+static inline int
+atomic·ctz32(uint32 x)
+{
+ int r;
+ __asm__( "bsf %1,%0" : "=r"(r) : "r"(x) );
+ return r;
+}
+
+static inline int
+atomic·clz32(uint32 x)
+{
+ __asm__( "bsr %1,%0 ; xor $31,%0" : "=r"(x) : "r"(x) );
+ return x;
+}
diff --git a/sys/linux/riscv64/arch/atomic.h b/sys/linux/riscv64/arch/atomic.h
new file mode 100644
index 0000000..95db16d
--- /dev/null
+++ b/sys/linux/riscv64/arch/atomic.h
@@ -0,0 +1,38 @@
+static inline void
+atomic·barrier()
+{
+ __asm__ __volatile__ ("fence rw,rw" : : : "memory");
+}
+
+static inline int
+atomic·cas(volatile int *p, int t, int s)
+{
+ int old, tmp;
+ __asm__ __volatile__ (
+ "\n1: lr.w.aqrl %0, (%2)\n"
+ " bne %0, %3, 1f\n"
+ " sc.w.aqrl %1, %4, (%2)\n"
+ " bnez %1, 1b\n"
+ "1:"
+ : "=&r"(old), "=&r"(tmp)
+ : "r"(p), "r"((long)t), "r"((long)s)
+ : "memory");
+ return old;
+}
+
+static inline void
+*atomic·casp(volatile void *p, void *t, void *s)
+{
+ void *old;
+ int tmp;
+ __asm__ __volatile__ (
+ "\n1: lr.d.aqrl %0, (%2)\n"
+ " bne %0, %3, 1f\n"
+ " sc.d.aqrl %1, %4, (%2)\n"
+ " bnez %1, 1b\n"
+ "1:"
+ : "=&r"(old), "=&r"(tmp)
+ : "r"(p), "r"(t), "r"(s)
+ : "memory");
+ return old;
+}
diff --git a/sys/rt/amd64/crt1.s b/sys/rt/amd64/crt1.s
deleted file mode 100644
index aaad0ba..0000000
--- a/sys/rt/amd64/crt1.s
+++ /dev/null
@@ -1,21 +0,0 @@
-global _start
-
-; NOTE: assumes program loader has put argc, argv, envc, envp on stack
-section .text
-_start:
- xor rbp,rbp ; base pointer undefined: set to 0
- mov r9,rdx ; 6th arg: function to register with atexit()
- pop rsi ; 2nd arg: argc
- mov rdx,rsp ; 3rd arg: argv
- and rsp,$-16 ; align stack pointer to 16 bytes
- mov $_fini,r8 ; 5th arg: fini
- mov $_init,rcx ; 4th arg: init
- mov $main,rdi ; 1st arg: main
-
- call rt·boot ; int boot(
- ; int(*main)(int,char*[],char*[]),
- ; int argc,
- ; char *argv[],
- ; init, fini, atexit);
-
-.loop: jmp .loop ; should never reach...
diff --git a/sys/rt/amd64/crti.s b/sys/rt/amd64/crti.s
deleted file mode 100644
index eeba8b1..0000000
--- a/sys/rt/amd64/crti.s
+++ /dev/null
@@ -1,17 +0,0 @@
-global _init
-global _fini
-
-section .init
-_init:
- ; call pushes an 8 byte return address on the stack
- ; 64 bit ABI requires stack to be aligned to 16 bytes
- ; we realign with another 8 byte address
- push rbp
- mov rbp, rsp
- ;; compiler inserts the rest here
-
-section .fini
-_fini:
- push rbp ; see above
- mov rbp, rsp
- ;; compiler inserts the rest here
diff --git a/sys/rt/amd64/crtn.s b/sys/rt/amd64/crtn.s
deleted file mode 100644
index 45d1a29..0000000
--- a/sys/rt/amd64/crtn.s
+++ /dev/null
@@ -1,9 +0,0 @@
-section .init
- ;; compiler inserts here
- pop rbp ;; undo our push
- ret
-
-section .fini
- ;; compiler inserts here
- pop rbp ;; undo our push
- ret
diff --git a/sys/rt/amd64/rt1.s b/sys/rt/amd64/rt1.s
new file mode 100644
index 0000000..afb5c32
--- /dev/null
+++ b/sys/rt/amd64/rt1.s
@@ -0,0 +1,9 @@
+.extern rt·thunk
+
+.text
+.global _start
+_start:
+ xor %rbp,%rbp
+ mov %rsp,%rdi
+ andq $-16,%rsp
+ call rt·thunk
diff --git a/sys/rt/amd64/rti.s b/sys/rt/amd64/rti.s
new file mode 100644
index 0000000..4788968
--- /dev/null
+++ b/sys/rt/amd64/rti.s
@@ -0,0 +1,9 @@
+.section .init
+.global _init
+_init:
+ push %rax
+
+.section .fini
+.global _fini
+_fini:
+ push %rax
diff --git a/sys/rt/amd64/rtn.s b/sys/rt/amd64/rtn.s
new file mode 100644
index 0000000..29198b7
--- /dev/null
+++ b/sys/rt/amd64/rtn.s
@@ -0,0 +1,7 @@
+.section .init
+ pop %rax
+ ret
+
+.section .fini
+ pop %rax
+ ret
diff --git a/sys/rt/arm/rt1.s b/sys/rt/arm/rt1.s
new file mode 100644
index 0000000..2adfee8
--- /dev/null
+++ b/sys/rt/arm/rt1.s
@@ -0,0 +1,11 @@
+.extern rt·thunk
+
+.text
+.global _start
+.type _start, %function
+_start:
+ mov fp, #0
+ mov lr, #0
+ mov a1, sp
+ and sp, sp, #-16
+ bl rt·thunk
diff --git a/sys/rt/arm/rti.s b/sys/rt/arm/rti.s
new file mode 100644
index 0000000..18dc1e4
--- /dev/null
+++ b/sys/rt/arm/rti.s
@@ -0,0 +1,13 @@
+.syntax unified
+
+.section .init
+.global _init
+.type _init,%function
+_init:
+ push {r0,lr}
+
+.section .fini
+.global _fini
+.type _fini,%function
+_fini:
+ push {r0,lr}
diff --git a/sys/rt/arm/rtn.s b/sys/rt/arm/rtn.s
new file mode 100644
index 0000000..dc020f9
--- /dev/null
+++ b/sys/rt/arm/rtn.s
@@ -0,0 +1,9 @@
+.syntax unified
+
+.section .init
+ pop {r0,lr}
+ bx lr
+
+.section .fini
+ pop {r0,lr}
+ bx lr
diff --git a/sys/rt/arm64/rt1.s b/sys/rt/arm64/rt1.s
new file mode 100644
index 0000000..d0f76da
--- /dev/null
+++ b/sys/rt/arm64/rt1.s
@@ -0,0 +1,10 @@
+ .extern rt·thunk
+
+.global _start
+.type _start, %function
+_start:
+ mov x29, #0
+ mov x30, #0
+ mov x0, sp
+ and sp, x0, #-16
+ b rt·thunk
diff --git a/sys/rt/arm64/rti.s b/sys/rt/arm64/rti.s
new file mode 100644
index 0000000..775df0a
--- /dev/null
+++ b/sys/rt/arm64/rti.s
@@ -0,0 +1,13 @@
+.section .init
+.global _init
+.type _init,%function
+_init:
+ stp x29,x30,[sp,-16]!
+ mov x29,sp
+
+.section .fini
+.global _fini
+.type _fini,%function
+_fini:
+ stp x29,x30,[sp,-16]!
+ mov x29,sp
diff --git a/sys/rt/arm64/rtn.s b/sys/rt/arm64/rtn.s
new file mode 100644
index 0000000..73cab69
--- /dev/null
+++ b/sys/rt/arm64/rtn.s
@@ -0,0 +1,7 @@
+.section .init
+ ldp x29,x30,[sp],#16
+ ret
+
+.section .fini
+ ldp x29,x30,[sp],#16
+ ret
diff --git a/sys/rt/boot.c b/sys/rt/boot.c
index 197e861..76f5599 100644
--- a/sys/rt/boot.c
+++ b/sys/rt/boot.c
@@ -1,34 +1,41 @@
+#include <u.h>
#include <rt.h>
+#include <elf.h>
-int
-rt·boot(
- int (*main)(int,char **,char **), int argc, char **argv,
- int (*init)(int, char **, char **), void (*fini)(void),
- void (*exit)(void)
-)
+/* tell linker to go find */
+int __libc_start_main(int (*main)(int,char **,char **), int argc, char **argv);
+
+#define NAUX 38
+static void
+rt·init(char **env, char *program)
{
- char **envp = argv+argc+1;
- rt·environ = envp;
+ uintptr i, *auxv, aux[NAUX];
+ for(i=0; env[i]; i++)
+ ;
+ rt·context.auxv = auxv = (void *)(env+i+1);
+ for(i=0; auxv[i]; i+=2)
+ if(auxv[i]<NAUX)
+ aux[auxv[i]] = auxv[i+1];
- if(exit)
- rt·context.exit = exit;
+ rt·context.sysinfo = aux[AT_SYSINFO];
+ rt·context.pagesize = aux[AT_PAGESZ];
+}
- if(fini)
- rt·context.fini = fini;
+int
+rt·boot(int (*main)(), int argc, char **argv, void (*init)(), void (*fini)(), void (*exit)())
+{
+ char **env = argv+argc+1;
+ rt·init(env, argv[0]);
- if(init){
- rt·context.init = init;
- init(argc, argv, envp);
- }
+ /* ring libc, anyone home? */
+ __libc_start_main(main, argc, argv);
- /* XXX:
- * we could call __libc_start_main of musl here:
- * this would give us the normal C runtime along with ours
- * which would allow seamless linking to other libraries
- * or we can implement a compatibility layer
- */
- rt·exit(main(argc, argv, envp));
+ /* no? ok we continue on if there is no libc linked */
+ init();
+ if(fini)
+ rt·context.fini = fini;
+ if(exit)
+ rt·context.exit = exit;
- /* should never get here */
- return 0;
+ rt·exit(main(argc, argv, env));
}
diff --git a/sys/rt/context.c b/sys/rt/context.c
new file mode 100644
index 0000000..fb383e3
--- /dev/null
+++ b/sys/rt/context.c
@@ -0,0 +1,4 @@
+#include <u.h>
+#include <rt.h>
+
+struct rt·Context rt·context;
diff --git a/sys/rt/dummy.c b/sys/rt/dummy.c
new file mode 100644
index 0000000..f123d16
--- /dev/null
+++ b/sys/rt/dummy.c
@@ -0,0 +1,6 @@
+#include <u.h>
+#include <rt.h>
+
+/* provide a dummy implementation if libc is not linked */
+static int noop(int (*main)(), int argc, char **argv) { return 0; }
+weakalias(noop, __libc_start_main);
diff --git a/sys/rt/env.c b/sys/rt/env.c
index ddd559d..be710ae 100644
--- a/sys/rt/env.c
+++ b/sys/rt/env.c
@@ -1,3 +1,4 @@
+#include <u.h>
#include <rt.h>
-char *rt·environ = 0;
+char **rt·environ = 0;
diff --git a/sys/rt/exit.c b/sys/rt/exit.c
index 55a684a..e6027b7 100644
--- a/sys/rt/exit.c
+++ b/sys/rt/exit.c
@@ -1,15 +1,27 @@
+#include <u.h>
#include <rt.h>
-#include <sys.h>
+#include <syscall.h>
-void
-rt·exit(int code)
+/* XXX:
+ * if we are here, we are in charge, call exit syscalls
+ * think of better way to encapsulate these syscalls?
+ */
+static noreturn void
+rt·shutdown(int code)
{
if(rt·context.fini)
rt·context.fini();
if(rt·context.exit)
rt·context.exit();
- /* call exit syscalls here */
+ _syscall1(·ExitGroup, code);
+ for(;;)
+ _syscall1(·Exit, code);
+}
+weakalias(rt·shutdown, exit);
- for(;;);
+noreturn void
+rt·exit(int code)
+{
+ rt·shutdown(code);
}
diff --git a/sys/rt/i386/rt1.s b/sys/rt/i386/rt1.s
new file mode 100644
index 0000000..aef4f05
--- /dev/null
+++ b/sys/rt/i386/rt1.s
@@ -0,0 +1,14 @@
+.extern rt·thunk
+
+.text
+.global _start
+_start:
+ xor %ebp,%ebp
+ mov %esp,%eax
+ and $-16,%esp
+ push %eax
+ push %eax
+ push %eax
+ push %eax
+ call rt·thunk
+");
diff --git a/sys/rt/i386/rti.s b/sys/rt/i386/rti.s
new file mode 100644
index 0000000..d2682a2
--- /dev/null
+++ b/sys/rt/i386/rti.s
@@ -0,0 +1,9 @@
+.section .init
+.global _init
+_init:
+ sub $12,%esp
+
+.section .fini
+.global _fini
+_fini:
+ sub $12,%esp
diff --git a/sys/rt/i386/rtn.s b/sys/rt/i386/rtn.s
new file mode 100644
index 0000000..f3b61e0
--- /dev/null
+++ b/sys/rt/i386/rtn.s
@@ -0,0 +1,7 @@
+.section .init
+ add $12,%esp
+ ret
+
+.section .fini
+ add $12,%esp
+ ret
diff --git a/sys/rt/include/rt.h b/sys/rt/include/rt.h
deleted file mode 100644
index dd1598b..0000000
--- a/sys/rt/include/rt.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-
-extern struct rt·context
-{
- void (*init)(void);
- void (*fini)(void);
- void (*exit)(void);
-} rt·context;
-
-extern char **rt·environ;
-
-void rt·exit(int code);
diff --git a/sys/rt/riscv64/rt1.s b/sys/rt/riscv64/rt1.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sys/rt/riscv64/rt1.s
diff --git a/sys/rt/riscv64/rti.s b/sys/rt/riscv64/rti.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sys/rt/riscv64/rti.s
diff --git a/sys/rt/riscv64/rtn.s b/sys/rt/riscv64/rtn.s
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sys/rt/riscv64/rtn.s
diff --git a/sys/rt/stack.c b/sys/rt/stack.c
new file mode 100644
index 0000000..5ab7a8a
--- /dev/null
+++ b/sys/rt/stack.c
@@ -0,0 +1,17 @@
+#include <u.h>
+#include <arch/atomic.h>
+
+/* unprefixed names determined by gcc */
+uintptr __stack_chk_guard;
+
+void
+rt·guardstack(void)
+{
+ __stack_chk_guard = (uintptr)&__stack_chk_guard*1103515245;
+}
+
+void
+__stack_chk_fail(void)
+{
+ atomic·crash();
+}
diff --git a/sys/rt/thunk.c b/sys/rt/thunk.c
new file mode 100644
index 0000000..3e9fa35
--- /dev/null
+++ b/sys/rt/thunk.c
@@ -0,0 +1,17 @@
+#include <u.h>
+#include <rt.h>
+
+int main();
+void _init() __attribute__((weak));
+void _fini() __attribute__((weak));
+
+void rt·boot(int (*)(), int , char **, void (*)(), void (*)(), void (*)());
+
+void
+rt·thunk(intptr *stack)
+{
+ int argc = stack[0];
+ char **argv = (void *)(stack+1);
+
+ rt·boot(main, argc, argv, _init, _fini, 0);
+}
diff --git a/sys/rules.mk b/sys/rules.mk
new file mode 100644
index 0000000..3113915
--- /dev/null
+++ b/sys/rules.mk
@@ -0,0 +1,55 @@
+# rules for rt
+RT1 := $(OBJ_DIR)/rt/rt1.a
+RTI := $(OBJ_DIR)/rt/rti.o
+# rt2 = user program
+RTN := $(OBJ_DIR)/rt/rtn.o
+RT3 := $(OBJ_DIR)/rt/rt3.a
+RUNTIME := $(RT1) $(RTI) $(RTN) $(RT3)
+
+RT1_SRC := \
+ $(SYS_DIR)/rt/env.c\
+ $(SYS_DIR)/rt/context.c\
+ $(SYS_DIR)/rt/boot.c\
+ $(SYS_DIR)/rt/thunk.c
+
+RT3_SRC := \
+ $(SYS_DIR)/rt/dummy.c\
+ $(SYS_DIR)/rt/exit.c\
+
+RT1_OBJ := $(filter %.o, $(RT1_SRC:.c=.o))
+RT1_OBJ := $(patsubst $(SYS_DIR)/rt/%, $(OBJ_DIR)/rt/%, $(RT1_OBJ))
+RT3_OBJ := $(filter %.o, $(RT3_SRC:.c=.o))
+RT3_OBJ := $(patsubst $(SYS_DIR)/rt/%, $(OBJ_DIR)/rt/%, $(RT3_OBJ))
+
+$(RT1_OBJ): TCFLAGS=-fno-builtin -fno-stack-protector
+$(RT1): $(SYS_DIR)/rt/$(ARCH)/rt1.s $(RT1_OBJ)
+ @echo "AS rt1.a"
+ @$(AS) $(AFLAGS) -o $(OBJ_DIR)/rt/rt1.o -c $<
+ @$(AR) crs $@ $(OBJ_DIR)/rt/rt1.o $(RT1_OBJ)
+
+$(RTI): $(SYS_DIR)/rt/$(ARCH)/rti.s
+ $(ASSEMBLE)
+
+$(RTN): $(SYS_DIR)/rt/$(ARCH)/rtn.s
+ $(ASSEMBLE)
+
+$(OBJ_DIR)/rt/%.o: $(SYS_DIR)/rt/%.c
+ $(COMPILE)
+
+$(RT3): $(RT3_OBJ)
+ $(ARCHIVE)
+
+# rules for system layer
+SYS := $(OBJ_DIR)/sys/sys.a
+
+SYS_SRCS := $(sort $(wildcard $(SYS_DIR)/$(OS)/src/*.c))
+SYS_OBJS := $(filter %.o, $(SYS_SRCS:.c=.o))
+SYS_OBJS := $(patsubst $(SYS_DIR)/$(OS)/src/%, $(OBJ_DIR)/$(SYS_DIR)/%, $(SYS_OBJS))
+
+# rules for kernel interface
+$(OBJ_DIR)/sys/%.o: TINCS = -I $(SYS_DIR)/$(OS)/$(ARCH)
+$(OBJ_DIR)/sys/%.o: $(SYS_DIR)/$(OS)/src/%.c
+ $(COMPILE)
+
+$(SYS): $(SYS_OBJS)
+ $(ARCHIVE)