diff options
46 files changed, 834 insertions, 144 deletions
@@ -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 $@ $^ @@ -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)
@@ -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; } @@ -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) @@ -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) |