From 2f85ac948493e62e3001436588360dc411933ee8 Mon Sep 17 00:00:00 2001 From: Calascibetta Romain Date: Sun, 19 Jan 2025 20:34:58 +0100 Subject: [PATCH] Support tls --- GNUmakefile | 56 +++++++++++++++++++++++++++---------------------- configure.sh | 1 + gilbraltar.ld | 4 ++++ include/tls.h | 10 +++++++++ kernel/kernel.c | 13 ++++++++++++ kernel/memory.c | 4 +--- kernel/tls.c | 35 +++++++++++++++++++++++++++++++ toolchain/cc.in | 6 +++--- 8 files changed, 98 insertions(+), 31 deletions(-) create mode 100644 include/tls.h create mode 100644 kernel/tls.c diff --git a/GNUmakefile b/GNUmakefile index 3974cc3..6419e7c 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -19,37 +19,39 @@ include/$(CONFIG_TARGET_TRIPLE): @echo "GEN $@" @./gen-headers.sh $@ -CPU ?= -mcpu=cortex-a76 -mlittle-endian -ARCH += -DAARCH=64 $(CPU) -TARGET ?= kernel_2712 +BUILD_INCLUDE += -I $(TOPDIR)/include \ + -I $(TOPDIR)/include/$(CONFIG_TARGET_TRIPLE) \ + -I $(TOPDIR)/nolibc/include \ + -I $(TOPDIR)/openlibm/include \ + -I $(TOPDIR)/openlibm/src -DEFINE += -DSSP_GUARD_SYMBOL=__stack_chk_guard \ +BUILD_AFLAGS += $(BUILD_INCLUDE) \ + -DAARCH=64 -mcpu=cortex-a76 -mlittle-endian \ + -DSSP_GUARD_SYMBOL=__stack_chk_guard \ -DSSP_FAIL_SYMBOL=__stack_chk_fail -INCLUDE += -I $(TOPDIR)/include -I $(TOPDIR)/include/$(CONFIG_TARGET_TRIPLE) \ - -I $(TOPDIR)/nolibc/include -I $(TOPDIR)/openlibm/include -I $(TOPDIR)/openlibm/src - -AFLAGS += $(ARCH) $(DEFINE) $(INCLUDE) - # CFLAGS & LDFLAGS are used with $(CC). Link arguments must be passed with -Wl # Also, CONFIG_TARGET_LD_LDFLAGS are specific when we use CONFIG_TARGET_LD -CFLAGS += -ffreestanding -fstack-protector-strong -nostdlib \ - -nostartfiles -mstrict-align -Wall \ - $(ARCH) $(DEFINE) $(INCLUDE) $(CONFIG_TARGET_CC_CFLAGS) +BUILD_CFLAGS += $(BUILD_INCLUDE) \ + -ffreestanding -fstack-protector-strong -nostdlib -nostartfiles -mstrict-align -Wall \ + -DAARCH=64 -mcpu=cortex-a76 -mlittle-endian \ + -DSSP_GUARD_SYMBOL=__stack_chk_guard \ + -DSSP_FAIL_SYMBOL=__stack_chk_fail \ + $(CONFIG_TARGET_CC_CFLAGS) comma := , empty:= space := $(empty) $(empty) -LDFLAGS += -static -Wl,--no-warn-rwx-segments \ +BUILD_CC_LDFLAGS += -static -Wl,--no-warn-rwx-segments \ -Wl,--section-start=.init=0x80000 \ -Wl,--start-group \ -L lib/$(CONFIG_TARGET_TRIPLE) -lgilbraltar -lopenlibm -lnolibc -lgcc \ -Wl,--end-group \ -Wl,$(subst $(space),$(comma),${CONFIG_TARGET_CC_LDFLAGS}) -LD_LDFLAGS += -static --no-warn-rwx-segments \ +BUILD_LD_LDFLAGS += -static --no-warn-rwx-segments \ --section-start=.init=0x80000 \ --start-group \ -L lib/$(CONFIG_TARGET_TRIPLE) -lgilbraltar -lopenlibm -lnolibc -lgcc \ @@ -58,7 +60,7 @@ LD_LDFLAGS += -static --no-warn-rwx-segments \ SRCS= kernel.c timer.c led.c interrupt_handler.c exception_handler.c \ mbox.c clock.c crt.c serial.c log.c power.c tag.c coherent_page.c dtb.c \ - synchronize.c spinlock.c memory.c pager.c translation_table.c + synchronize.c spinlock.c memory.c pager.c translation_table.c tls.c ASMS= startup.S exception_stub.S @@ -72,6 +74,9 @@ ALLTOOLS := $(foreach tool,$(ALLTOOLS),\ $(CONFIG_TARGET_TRIPLE)-$(tool)) TOOLCHAIN_FOR_BUILD := $(addprefix bin/build/,$(ALLTOOLS)) +ALLLIBS := libnolibc.a libopenlibm.a libgilbraltar.a +LIBS_FOR_BUILD := $(addprefix lib/$(CONFIG_TARGET_TRIPLE)/,$(ALLLIBS)) + bin/build: @test ! -d $@ @mkdir -p $@ @@ -81,10 +86,10 @@ bin/build/$(CONFIG_TARGET_TRIPLE)-%: toolchain/%.in | bin/build @sed -e 's!@@CONFIG_TARGET_ARCH@@!$(CONFIG_TARGET_ARCH)!g' \ -e 's!@@CONFIG_TARGET_TRIPLE@@!$(CONFIG_TARGET_TRIPLE)!g' \ -e 's!@@CONFIG_TARGET_CC@@!$(CONFIG_TARGET_CC)!g' \ - -e 's!@@CONFIG_TARGET_CC_CFLAGS@@!$(CFLAGS)!g' \ - -e 's!@@CONFIG_TARGET_CC_LDFLAGS@@!$(LDFLAGS)!g' \ + -e 's!@@CONFIG_TARGET_CC_CFLAGS@@!$(BUILD_CFLAGS)!g' \ + -e 's!@@CONFIG_TARGET_CC_LDFLAGS@@!$(BUILD_CC_LDFLAGS)!g' \ -e 's!@@CONFIG_TARGET_LD@@!$(CONFIG_TARGET_LD)!g' \ - -e 's!@@CONFIG_TARGET_LD_LDFLAGS@@!$(LD_LDFLAGS)!g' \ + -e 's!@@CONFIG_TARGET_LD_LDFLAGS@@!$(BUILD_LD_LDFLAGS)!g' \ -e 's!@@CONFIG_TARGET_OBJCOPY@@!$(CONFIG_TARGET_OBJCOPY)!g' \ -e 's!@@CONFIG_HOST_CC@@!$(CONFIG_HOST_CC)!g' \ -e 's!@@CONFIG_TARGET_NM@@!$(CONFIG_TARGET_NM)!g' \ @@ -100,11 +105,11 @@ toolchains: bin/build %.o: %.S @echo "AS $@" - @$(AS) $(AFLAGS) -c -o $@ $< + @$(AS) $(BUILD_AFLAGS) -c -o $@ $< %.o: %.c include/$(CONFIG_TARGET_TRIPLE) @echo "CC $@" - @$(CC) $(CFLAGS) -c -o $@ $< + @$(CC) $(BUILD_CFLAGS) -c -o $@ $< lib/$(CONFIG_TARGET_TRIPLE): @test ! -d $@ @@ -126,7 +131,7 @@ lib/$(CONFIG_TARGET_TRIPLE)/libopenlibm.a: openlibm/libopenlibm.a | lib/$(CONFIG .PHONY: phony-openlibm phony-openlibm: include/$(CONFIG_TARGET_TRIPLE) @$(MAKE) -C openlibm \ - "CC=$(CC)" "CPPFLAGS=$(CFLAGS)" libopenlibm.a + "CC=$(CC)" "CPPFLAGS=$(BUILD_CFLAGS)" libopenlibm.a openlibm/libopenlibm.a: phony-openlibm @@ -138,7 +143,7 @@ ocaml: git apply --directory=$@ "patches/$$VERSION"/*; \ fi -ocaml/Makefile.config: $(TOOLCHAIN_FOR_BUILD) | ocaml +ocaml/Makefile.config: $(TOOLCHAIN_FOR_BUILD) $(LIBS_FOR_BUILD) | ocaml PATH="$$PWD/bin/build:$$PATH" ; \ cd ocaml && \ ./configure \ @@ -164,7 +169,7 @@ $(OCAML_IS_BUILT): ocaml/Makefile.config | build cd ocaml && ocamlrun tools/stripdebug ocamlopt ocamlopt.tmp touch $@ -NOLIBC_CFLAGS= $(CFLAGS) \ +NOLIBC_CFLAGS= $(BUILD_CFLAGS) \ -I $(TOPDIR)/nolibc/include \ -I $(TOPDIR)/openlibm/src \ -I $(TOPDIR)/openlibm/include @@ -198,9 +203,10 @@ distclean: clean test/%.o: test/%.c @echo "CC $@" - @$(CC) $(CFLAGS) -c -o $@ $< + @$(CC) $(BUILD_CFLAGS) -c -o $@ $< kernel_2712.img: lib/$(CONFIG_TARGET_TRIPLE)/libgilbraltar.a lib/$(CONFIG_TARGET_TRIPLE)/libnolibc.a lib/$(CONFIG_TARGET_TRIPLE)/libopenlibm.a test/test.o @echo "LD ${@:img=elf}" - @$(CC) test/test.o -o ${@:img=elf} $(CFLAGS) $(LDFLAGS) -Wl,-Map,${@:img=map} -T gilbraltar.ld + @$(CC) test/test.o -o ${@:img=elf} $(BUILD_CFLAGS) $(BUILD_CC_LDFLAGS) \ + -Wl,-Map,${@:img=map} -T gilbraltar.ld @$(OBJCOPY) ${@:img=elf} -O binary $@ diff --git a/configure.sh b/configure.sh index 26d5c03..8a8f325 100755 --- a/configure.sh +++ b/configure.sh @@ -463,6 +463,7 @@ CONFIG_TARGET_OBJCOPY=${TARGET_OBJCOPY} CONFIG_TARGET_OBJDUMP=${TARGET_OBJDUMP} CONFIG_TARGET_READELF=${TARGET_READELF} CONFIG_TARGET_STRIP=${TARGET_STRIP} +CONFIG_SYSROOT=${OPT_PREFIX}/gilbraltar-sysroot/ EOM # diff --git a/gilbraltar.ld b/gilbraltar.ld index dcdba50..3a73e97 100644 --- a/gilbraltar.ld +++ b/gilbraltar.ld @@ -2,6 +2,7 @@ ENTRY(_start) PHDRS { tdata PT_LOAD FLAGS(4); + tbss PT_TLS FLAGS(0); } SECTIONS @@ -49,4 +50,7 @@ SECTIONS *(COMMON) _end = .; } + + _ltdata = _edata - _stdata; + _ltbss = SIZEOF(.tbss); } diff --git a/include/tls.h b/include/tls.h new file mode 100644 index 0000000..798be1a --- /dev/null +++ b/include/tls.h @@ -0,0 +1,10 @@ +#ifndef __GILBRALTAR_TLS__ +#define __GILBRALTAR_TLS__ + +#include + +size_t gilbraltar_tls_size(void); +void gilbraltar_set_tls_base(uintptr_t); +void gilbraltar_tls_init(uintptr_t); + +#endif diff --git a/kernel/kernel.c b/kernel/kernel.c index 88f51c8..23191ca 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -10,12 +10,14 @@ #include #include #include +#include extern int main(); extern char __bss_start; extern char _etext[]; extern char _end[]; +static uintptr_t tls_main; #define PROPTAG_GET_COMMAND_LINE 0x00050001 @@ -87,6 +89,8 @@ void gilbraltar_dump(void) { coherent_region_start, coherent_region_end); gilbraltar_log(INFO, " heap @ 0x%08lx - 0x%08lx\r\n", heap_start, heap_end); + gilbraltar_log(INFO, " tls @ 0x%08lx - 0x%08lx\r\n", + tls_main, tls_main + gilbraltar_tls_size()); gilbraltar_log(INFO, "\r\n"); } @@ -116,6 +120,15 @@ void gilbraltar_sysinit(void) { } gilbraltar_dtb_init(); + tls_main = (uintptr_t)calloc(gilbraltar_tls_size(), sizeof(uint8_t)); + + if (tls_main == (uintptr_t)NULL) { + gilbraltar_log(ERROR, "Impossible to allocate TLS\r\n"); + abort(); + } + + gilbraltar_tls_init(tls_main); + gilbraltar_set_tls_base(tls_main); gilbraltar_dump(); int ret = main(ac + 1, cmdline); diff --git a/kernel/memory.c b/kernel/memory.c index 31009e8..6e847a7 100644 --- a/kernel/memory.c +++ b/kernel/memory.c @@ -93,12 +93,10 @@ static uintptr_t sbrk_guard_size; void *sbrk(intptr_t increment) { uintptr_t prev, brk; - uintptr_t max = (uintptr_t)&prev - sbrk_guard_size; prev = brk = sbrk_cur; brk += increment; - - if (brk >= max || brk >= sbrk_end || brk < sbrk_start) + if (brk >= sbrk_end || brk < sbrk_start) return ((void *)(-1)); sbrk_cur = brk; diff --git a/kernel/tls.c b/kernel/tls.c new file mode 100644 index 0000000..290ffb3 --- /dev/null +++ b/kernel/tls.c @@ -0,0 +1,35 @@ +#include +#include +#include + +extern char _stdata[]; +#define TDATA ((void *)_stdata) + +extern char _ltdata[], _ltbss[]; +#define LTDATA ((size_t)_ltdata) +#define LTBSS ((size_t)_ltbss) + +struct tcb { + void *tp; + void *pad; +}; + +size_t gilbraltar_tls_size(void) { + return (LTDATA + LTBSS + sizeof(struct tcb)); +} + +void gilbraltar_set_tls_base(uintptr_t base) { + __asm__ __volatile("msr tpidr_el0, %0" ::"r"(base)); +} + +static uintptr_t tls_data_offset(uintptr_t tls) { + uintptr_t data; + data = tls + sizeof(struct tcb); + return data; +} + +void gilbraltar_tls_init(uintptr_t tls) { + uintptr_t *tmp = (uintptr_t *)tls; + *tmp = (uintptr_t)tmp; + memcpy((void *)tls_data_offset(tls), TDATA, LTDATA); +} diff --git a/toolchain/cc.in b/toolchain/cc.in index 7d26617..dafbb66 100644 --- a/toolchain/cc.in +++ b/toolchain/cc.in @@ -88,7 +88,7 @@ case ${M} in -DAARCH=64 \ -mcpu=cortex-a76 \ "$@" - ;; + ;; link) [ -n "${B}" ] && B="-Wl,-T,gilbraltar.ld" [ -n "${LDFLAGS}" ] && LDFLAGS=$(echo "-Wl @@CONFIG_TARGET_LD_LDFLAGS@@" | tr ' ' ',') @@ -101,9 +101,9 @@ case ${M} in -ffreestanding \ -fstack-protector-strong \ "$@" \ - @@CONFIG_TARGET_CC_LDFLAGS@@ + @@CONFIG_TARGET_CC_LDFLAGS@@ \ -Wl,${LDFLAGS} \ ${B} \ - -static \ + -static ;; esac