From bf56be5dced998e397e1c1b30c5683d6b9a2f5ba Mon Sep 17 00:00:00 2001 From: palainp Date: Tue, 7 Feb 2023 14:45:12 +0100 Subject: [PATCH 01/14] export TLS symbols, make tbss next to tdata, set tdata as PT_LOAD to be loaded by the tenders --- bindings/solo5_hvt.lds | 21 +++++--- bindings/solo5_muen.lds | 22 +++++--- bindings/solo5_spt.lds | 22 ++++---- bindings/solo5_stub.lds | 21 +++++--- bindings/solo5_virtio.lds | 22 +++++--- bindings/solo5_xen.lds | 21 +++++--- include/solo5.h | 58 ++++++++++++++++++++++ tests/test_tls/test_tls.c | 102 ++++++++++++++++++++++---------------- 8 files changed, 198 insertions(+), 91 deletions(-) diff --git a/bindings/solo5_hvt.lds b/bindings/solo5_hvt.lds index 60461456..c0f1c09a 100644 --- a/bindings/solo5_hvt.lds +++ b/bindings/solo5_hvt.lds @@ -40,7 +40,7 @@ PHDRS { rodata PT_LOAD FLAGS(4); data PT_LOAD; - tdata PT_TLS; + tdata PT_LOAD; tbss PT_TLS; note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; @@ -115,13 +115,19 @@ SECTIONS { *(.data) *(.data.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _edata = .; + .tdata : { + _stdata = .; *(.tdata) } :tdata - - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; + .tbss (NOLOAD): + { + *(.tbss) + } :tbss /* Read-write data (uninitialized) */ .bss : @@ -129,10 +135,6 @@ SECTIONS { *(.bss) *(COMMON) } - .tbss (NOLOAD) : - { - *(.tbss) - } :tbss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -143,4 +145,7 @@ SECTIONS { /DISCARD/ : { *(.note.gnu.*) } + + _ltdata = SIZEOF(.tdata); + _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_muen.lds b/bindings/solo5_muen.lds index 523d5d6e..d2e654b5 100644 --- a/bindings/solo5_muen.lds +++ b/bindings/solo5_muen.lds @@ -39,7 +39,7 @@ PHDRS { FLAGS values come from PF_x in elf.h */ rodata PT_LOAD; data PT_LOAD; - tdata PT_TLS; + tdata PT_LOAD; tbss PT_TLS; note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; @@ -114,13 +114,20 @@ SECTIONS { *(.data) *(.data.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _edata = .; + + .tdata : { + _stdata = .; *(.tdata) } :tdata - - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; + .tbss (NOLOAD): + { + *(.tbss) + } :tbss /* Read-write data (uninitialized) */ .bss : @@ -128,10 +135,6 @@ SECTIONS { *(.bss) *(COMMON) } - .tbss (NOLOAD) : - { - *(.tbss) - } :tbss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -142,4 +145,7 @@ SECTIONS { /DISCARD/ : { *(.note.gnu.*) } + + _ltdata = SIZEOF(.tdata); + _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_spt.lds b/bindings/solo5_spt.lds index af589646..0aa87ef1 100644 --- a/bindings/solo5_spt.lds +++ b/bindings/solo5_spt.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS; + tdata PT_LOAD; tbss PT_TLS; note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; @@ -113,13 +113,19 @@ SECTIONS { *(.data) *(.data.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _edata = .; + .tdata : { + _stdata = .; *(.tdata) } :tdata - - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; + .tbss (NOLOAD): + { + *(.tbss) + } :tbss /* Read-write data (uninitialized) */ .bss : @@ -127,11 +133,6 @@ SECTIONS { *(.bss) *(COMMON) } - .tbss (NOLOAD): - { - *(.tbss) - } :tbss - . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; _end = .; @@ -141,4 +142,7 @@ SECTIONS { /DISCARD/ : { *(.note.gnu.*) } + + _ltdata = SIZEOF(.tdata); + _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_stub.lds b/bindings/solo5_stub.lds index 09575996..190fc35f 100644 --- a/bindings/solo5_stub.lds +++ b/bindings/solo5_stub.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS; + tdata PT_LOAD; tbss PT_TLS; note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; @@ -113,13 +113,19 @@ SECTIONS { *(.data) *(.data.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _edata = .; + .tdata : { + _stdata = .; *(.tdata) } :tdata - - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; + .tbss (NOLOAD): + { + *(.tbss) + } :tbss /* Read-write data (uninitialized) */ .bss : @@ -127,10 +133,6 @@ SECTIONS { *(.bss) *(COMMON) } - .tbss (NOLOAD): - { - *(.tbss) - } :tbss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -141,4 +143,7 @@ SECTIONS { /DISCARD/ : { *(.note.gnu.*) } + + _ltdata = SIZEOF(.tdata); + _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_virtio.lds b/bindings/solo5_virtio.lds index d9f70128..e8d38c64 100644 --- a/bindings/solo5_virtio.lds +++ b/bindings/solo5_virtio.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS; + tdata PT_LOAD; tbss PT_TLS; note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; @@ -114,13 +114,20 @@ SECTIONS { *(.data) *(.data.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _edata = .; + + .tdata : { + _stdata = .; *(.tdata) } :tdata - - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; + .tbss (NOLOAD): + { + *(.tbss) + } :tbss /* Read-write data (uninitialized) */ .bss : @@ -128,10 +135,6 @@ SECTIONS { *(.bss) *(COMMON) } - .tbss (NOLOAD) : - { - *(.tbss) - } :tbss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -142,4 +145,7 @@ SECTIONS { /DISCARD/ : { *(.note.gnu.*) } + + _ltdata = SIZEOF(.tdata); + _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_xen.lds b/bindings/solo5_xen.lds index 68c4434d..48768c6b 100644 --- a/bindings/solo5_xen.lds +++ b/bindings/solo5_xen.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS; + tdata PT_LOAD; tbss PT_TLS; note.not_openbsd PT_NOTE; /* Must come first. */ note.xen PT_NOTE; @@ -119,13 +119,19 @@ SECTIONS { *(.data) *(.data.*) } + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _edata = .; + .tdata : { + _stdata = .; *(.tdata) } :tdata - - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; + .tbss (NOLOAD): + { + *(.tbss) + } :tbss /* Read-write data (uninitialized) */ .bss : @@ -133,10 +139,6 @@ SECTIONS { *(.bss) *(COMMON) } - .tbss (NOLOAD) : - { - *(.tbss) - } :tbss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -147,4 +149,7 @@ SECTIONS { /DISCARD/ : { *(.note.gnu.*) } + + _ltdata = SIZEOF(.tdata); + _ltbss = SIZEOF(.tbss); } diff --git a/include/solo5.h b/include/solo5.h index 6389b5a7..da5353b2 100644 --- a/include/solo5.h +++ b/include/solo5.h @@ -126,6 +126,64 @@ void solo5_exit(int status) __attribute__((noreturn)); */ void solo5_abort(void) __attribute__((noreturn)); + +/* + * XXX(palainp): This is an incomplete implementation of TLS. + * It's limited to the local-exec pattern (offset directly from the TLS_BASE + * register). + * The usage is as the following for each thread: + * void* tcb1; // defines a TLS block + * tcb1 = calloc(solo5_tls_size(), sizeof(char)); // gets memory for it + * memcpy(solo5_tls_data_offset(tcb1), TDATA, LTDATA); // copy tdata + * solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1); // sets tp ptr + */ + +/* _stdata is the address begining of the "not bss" thread variables block */ +extern char _stdata[]; +#define TDATA ((void*)_stdata) + +/* _ltdata and _ltbss are the lengths of the tdata and tbss blocks */ +extern char _ltdata[], _ltbss[]; +#define LTDATA ((size_t)_ltdata) +#define LTBSS ((size_t)_ltbss) + +/* The following define the overhead to the tdata and tbss blocks + * It's processor related + */ +#if defined(__x86_64__) || defined(__powerpc64__) + /* Variant II */ + struct tcb { + void* tp; + }; + + /* solo5_tls_tp_offset tells where we need to set the tp pointer next to + * the data block. It depends on the Variant, for Variant II it's at the end. + */ + #define solo5_tls_tp_offset(x) (x + LTDATA + LTBSS) + #define solo5_tls_data_offset(x) (x) + + #define PPC64_TLS_OFFSET 0x7000 + +#elif defined(__aarch64__) + /* Variant I */ + struct tcb { + void* tp; + void* pad; + }; + + /* for Vairant I it's at the begining */ + #define tp_offset(x) (x) + #define solo5_tls_data_offset(x) (x + sizeof(struct tcb)) + +#else +#error Unsupported architecture +#endif + +/* + * Returns the size needed for the thread local storage. + */ +#define solo5_tls_size() (LTDATA + LTBSS + sizeof(struct tcb)) + /* * Set the architecture-specific TLS base register to (base). * diff --git a/tests/test_tls/test_tls.c b/tests/test_tls/test_tls.c index b0b76a7a..2ba1bece 100644 --- a/tests/test_tls/test_tls.c +++ b/tests/test_tls/test_tls.c @@ -21,42 +21,33 @@ #include "solo5.h" #include "../../bindings/lib.c" -/* - * XXX TODO: This test contains a bad, incomplete implementation of TLS. - * It's unclear what we should be testing here, and what "TLS support" in - * the context of Solo5 means at all. - */ - -#if defined(__x86_64__) || defined(__powerpc64__) -/* Variant II */ -struct tcb { - volatile uint64_t _data; - void *tp; -}; - -#define PPC64_TLS_OFFSET 0x7000 - -#elif defined(__aarch64__) -/* Variant I */ -struct tcb { - void *tp; - void *pad; - volatile uint64_t _data; -}; -#else -#error Unsupported architecture -#endif - -struct tcb tcb1; -struct tcb tcb2; +void* tcb1; +void* tcb2; static void puts(const char *s) { solo5_console_write(s, strlen(s)); } -__thread volatile uint64_t _data; +/* This just stub a libc malloc setup with a limited 1k heap. + * This does not guard heap overwritting on stack, it's just a testfile. + */ +#define heap_size 1024 +static uint8_t heap[heap_size]; +static uintptr_t heap_top = (uintptr_t)&heap; +static void* malloc_stub(size_t size) +{ + if (heap_top + size <= (uintptr_t)&heap + heap_size) + { + heap_top += size; + return (void*)(heap_top - size); + } + + return NULL; +} + +__thread volatile uint64_t _data; uint64_t __attribute__ ((noinline)) get_data() { return _data; @@ -67,36 +58,63 @@ void __attribute__ ((noinline)) set_data(uint64_t data) _data = data; } -int solo5_app_main(const struct solo5_start_info *si __attribute__((unused))) +__thread volatile uint64_t _data_not_bss = 0x0000000000C0FFEE; +uint64_t __attribute__ ((noinline)) get_data_not_bss() { - puts("\n**** Solo5 standalone test_tls ****\n\n"); + return _data_not_bss; +} -#if defined (__powerpc64__) - tcb1.tp = (void *) (PPC64_TLS_OFFSET + (uintptr_t)&tcb1._data); - tcb2.tp = (void *) (PPC64_TLS_OFFSET + (uintptr_t)&tcb2._data); -#else - tcb1.tp = &tcb1.tp; - tcb2.tp = &tcb2.tp; -#endif +static void putc(const char c) +{ + solo5_console_write(&c, 1); +} - if (solo5_set_tls_base((uintptr_t)tcb1.tp) != SOLO5_R_OK) +static void __attribute__ ((noinline)) printhex64(uint64_t x) +{ + char hex[] = "0123456789ABCDEF"; + for(int i=60; i>=0; i-=4) + { + putc(hex[(x>>i)&0xf]); + } + putc('\n'); +} + +int solo5_app_main(const struct solo5_start_info *si __attribute__((unused))) +{ + puts("\n**** Solo5 standalone test_tls ****\n\n"); + puts(".tdata is at 0x"); + printhex64((uint64_t)(TDATA)); + puts(".tdata length is "); + printhex64((uint64_t)(LTDATA)); + puts(".tbss length is "); + printhex64((uint64_t)(LTBSS)); + + tcb1 = malloc_stub(solo5_tls_size()); + memcpy(solo5_tls_data_offset(tcb1), TDATA, LTDATA); + tcb2 = malloc_stub(solo5_tls_size()); + memcpy(solo5_tls_data_offset(tcb2), TDATA, LTDATA); + + if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1)) != SOLO5_R_OK) return 1; set_data(1); - if (solo5_set_tls_base((uintptr_t)tcb2.tp) != SOLO5_R_OK) + if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb2)) != SOLO5_R_OK) return 2; set_data(2); - if (solo5_set_tls_base((uintptr_t)tcb1.tp) != SOLO5_R_OK) + if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1)) != SOLO5_R_OK) return 3; if (get_data() != 1) return 4; - if (solo5_set_tls_base((uintptr_t)tcb2.tp) != SOLO5_R_OK) + if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb2)) != SOLO5_R_OK) return 5; if (get_data() != 2) return 6; + if (get_data_not_bss() != 0x0000000000C0FFEE) + return 7; + puts("SUCCESS\n"); return SOLO5_EXIT_SUCCESS; } From b1ad3b46d74cbc4022e8f1ba84f2b095118d8e35 Mon Sep 17 00:00:00 2001 From: palainp Date: Tue, 7 Feb 2023 14:45:45 +0100 Subject: [PATCH 02/14] set memcpy as non inlinable to prevent any compiler optimisation with test_tls.c --- bindings/lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/lib.c b/bindings/lib.c index 285ce218..e4fd6dec 100644 --- a/bindings/lib.c +++ b/bindings/lib.c @@ -67,7 +67,7 @@ void *memset(void *dest, int c, size_t n) return dest; } -void *memcpy(void *restrict dest, const void *restrict src, size_t n) +void *__attribute__ ((noinline)) memcpy(void *restrict dest, const void *restrict src, size_t n) { unsigned char *d = dest; const unsigned char *s = src; From 7e5e664ed2bb8799f6ff91430672b973cf6c267f Mon Sep 17 00:00:00 2001 From: palainp Date: Tue, 7 Feb 2023 15:26:35 +0100 Subject: [PATCH 03/14] skip empty PT_LOAD section in the tenders --- tenders/common/elf.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tenders/common/elf.c b/tenders/common/elf.c index 0a93e192..5422f718 100644 --- a/tenders/common/elf.c +++ b/tenders/common/elf.c @@ -243,7 +243,8 @@ void elf_load(int bin_fd, const char *bin_name, uint8_t *mem, size_t mem_size, Elf64_Xword p_align = phdr[ph_i].p_align; Elf64_Addr temp, p_vaddr_start, p_vaddr_end; - if (phdr[ph_i].p_type != PT_LOAD) + /* Skip non-PT_LOAD and empty PT_LOAD sections */ + if (phdr[ph_i].p_type != PT_LOAD || p_filesz == 0) continue; if (p_vaddr < p_min_loadaddr) From c5d21707eb54da7e6a1baa9bbd18a893201e4912 Mon Sep 17 00:00:00 2001 From: palainp Date: Tue, 7 Feb 2023 16:51:14 +0100 Subject: [PATCH 04/14] update linker scripts for virtio and xen --- bindings/solo5_virtio.lds | 7 +++++-- bindings/solo5_xen.lds | 6 +++++- bindings/virtio/boot.S | 2 +- bindings/xen/boot.S | 2 +- tests/test_tls/test_tls.c | 9 +++++++-- 5 files changed, 19 insertions(+), 7 deletions(-) diff --git a/bindings/solo5_virtio.lds b/bindings/solo5_virtio.lds index e8d38c64..09b65ff2 100644 --- a/bindings/solo5_virtio.lds +++ b/bindings/solo5_virtio.lds @@ -118,12 +118,15 @@ SECTIONS { . = ALIGN(CONSTANT(MAXPAGESIZE)); _edata = .; - .tdata : { _stdata = .; *(.tdata) } :tdata + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _etdata =.; + .tbss (NOLOAD): { *(.tbss) @@ -146,6 +149,6 @@ SECTIONS { *(.note.gnu.*) } - _ltdata = SIZEOF(.tdata); + _ltdata = _etdata - _stdata; _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_xen.lds b/bindings/solo5_xen.lds index 48768c6b..d3efa377 100644 --- a/bindings/solo5_xen.lds +++ b/bindings/solo5_xen.lds @@ -128,6 +128,10 @@ SECTIONS { _stdata = .; *(.tdata) } :tdata + + . = ALIGN(CONSTANT(MAXPAGESIZE)); + _etdata = .; + .tbss (NOLOAD): { *(.tbss) @@ -150,6 +154,6 @@ SECTIONS { *(.note.gnu.*) } - _ltdata = SIZEOF(.tdata); + _ltdata = _etdata - _stdata; _ltbss = SIZEOF(.tbss); } diff --git a/bindings/virtio/boot.S b/bindings/virtio/boot.S index de216127..a8e383ec 100644 --- a/bindings/virtio/boot.S +++ b/bindings/virtio/boot.S @@ -44,7 +44,7 @@ _multiboot_header: .long -(MULTIBOOT_HEADER_MAGIC+MYMULTIBOOT_FLAGS) .long _multiboot_header .long 0x100000 -.long _edata +.long _etdata .long _ebss .long _start32 diff --git a/bindings/xen/boot.S b/bindings/xen/boot.S index 4ddd5935..23b90577 100644 --- a/bindings/xen/boot.S +++ b/bindings/xen/boot.S @@ -39,7 +39,7 @@ .long -(MULTIBOOT_HEADER_MAGIC+MYMULTIBOOT_FLAGS) .long _multiboot_header .long 0x100000 - .long _edata + .long _etdata .long _ebss .long _start32 diff --git a/tests/test_tls/test_tls.c b/tests/test_tls/test_tls.c index 2ba1bece..6d8a9f38 100644 --- a/tests/test_tls/test_tls.c +++ b/tests/test_tls/test_tls.c @@ -29,10 +29,10 @@ static void puts(const char *s) solo5_console_write(s, strlen(s)); } -/* This just stub a libc malloc setup with a limited 1k heap. +/* This just stub a libc malloc setup with a limited 64k heap. * This does not guard heap overwritting on stack, it's just a testfile. */ -#define heap_size 1024 +#define heap_size 65536 static uint8_t heap[heap_size]; static uintptr_t heap_top = (uintptr_t)&heap; @@ -90,8 +90,13 @@ int solo5_app_main(const struct solo5_start_info *si __attribute__((unused))) printhex64((uint64_t)(LTBSS)); tcb1 = malloc_stub(solo5_tls_size()); + if (tcb1 == NULL) + return 10; memcpy(solo5_tls_data_offset(tcb1), TDATA, LTDATA); + tcb2 = malloc_stub(solo5_tls_size()); + if (tcb2 == NULL) + return 11; memcpy(solo5_tls_data_offset(tcb2), TDATA, LTDATA); if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1)) != SOLO5_R_OK) From b2b6acb7f3de443afe86be0c73e321c711584ca8 Mon Sep 17 00:00:00 2001 From: palainp Date: Wed, 8 Feb 2023 08:05:10 +0100 Subject: [PATCH 05/14] - adapt the elf reader in the tenders to allow reading the tdata section which is not a PT_LOAD but a PT_TLS section (and pass it in the case where there is no __thread variables (p_filesz==0)) - align correctly the tdata section (and set it read-only) to match the expectation of the tenders elf reader - add a bss section in the elf header as lld can merge that section with the previous and calculate TLS offsets badly - now tbss and bss have no RWX permissions (this is important for tbss to be distinct to tdata and not loaded by the elf reader) --- bindings/solo5_hvt.lds | 29 +++++++++++++++++++---------- bindings/solo5_muen.lds | 28 ++++++++++++++++++---------- bindings/solo5_spt.lds | 29 ++++++++++++++++++++--------- bindings/solo5_stub.lds | 27 ++++++++++++++++++--------- bindings/solo5_virtio.lds | 29 +++++++++++++++++------------ bindings/solo5_xen.lds | 29 +++++++++++++++++------------ bindings/virtio/boot.S | 2 +- bindings/xen/boot.S | 2 +- tenders/common/elf.c | 10 ++++++++-- 9 files changed, 119 insertions(+), 66 deletions(-) diff --git a/bindings/solo5_hvt.lds b/bindings/solo5_hvt.lds index c0f1c09a..617d8cbe 100644 --- a/bindings/solo5_hvt.lds +++ b/bindings/solo5_hvt.lds @@ -40,8 +40,9 @@ PHDRS { rodata PT_LOAD FLAGS(4); data PT_LOAD; - tdata PT_LOAD; - tbss PT_TLS; + tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tbss PT_TLS FLAGS(0); /* no perm needed */ + bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; note.manifest PT_NOTE; @@ -116,25 +117,33 @@ SECTIONS { *(.data.*) } - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; - + /* + * tdata and tbss have to be side by side to help the linker caculate the + * various __thread variables offsets. + */ .tdata : { _stdata = .; *(.tdata) + . = ALIGN(CONSTANT(MAXPAGESIZE)); } :tdata - .tbss (NOLOAD): + + /* + * _edata is the address of the end of the area to be copied with multiboot + * (virtio and xen) + */ + _edata = .; + + /* Read-write data (uninitialized) */ + .tbss : { *(.tbss) } :tbss - - /* Read-write data (uninitialized) */ .bss : { *(.bss) *(COMMON) - } + } :bss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -146,6 +155,6 @@ SECTIONS { *(.note.gnu.*) } - _ltdata = SIZEOF(.tdata); + _ltdata = _edata - _stdata; _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_muen.lds b/bindings/solo5_muen.lds index d2e654b5..61d297e9 100644 --- a/bindings/solo5_muen.lds +++ b/bindings/solo5_muen.lds @@ -39,8 +39,9 @@ PHDRS { FLAGS values come from PF_x in elf.h */ rodata PT_LOAD; data PT_LOAD; - tdata PT_LOAD; - tbss PT_TLS; + tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tbss PT_TLS FLAGS(0); /* no perm needed */ + bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; note.manifest PT_NOTE; @@ -115,26 +116,33 @@ SECTIONS { *(.data.*) } - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; - - + /* + * tdata and tbss have to be side by side to help the linker caculate the + * various __thread variables offsets. + */ .tdata : { _stdata = .; *(.tdata) + . = ALIGN(CONSTANT(MAXPAGESIZE)); } :tdata - .tbss (NOLOAD): + + /* + * _edata is the address of the end of the area to be copied with multiboot + * (virtio and xen) + */ + _edata = .; + + /* Read-write data (uninitialized) */ + .tbss : { *(.tbss) } :tbss - - /* Read-write data (uninitialized) */ .bss : { *(.bss) *(COMMON) - } + } :bss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; diff --git a/bindings/solo5_spt.lds b/bindings/solo5_spt.lds index 0aa87ef1..775102dc 100644 --- a/bindings/solo5_spt.lds +++ b/bindings/solo5_spt.lds @@ -38,8 +38,9 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_LOAD; - tbss PT_TLS; + tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tbss PT_TLS FLAGS(0); /* no perm needed */ + bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; note.manifest PT_NOTE; @@ -115,24 +116,34 @@ SECTIONS { } . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; - + /* + * tdata and tbss have to be side by side to help the linker caculate the + * various __thread variables offsets. + */ .tdata : { _stdata = .; *(.tdata) + . = ALIGN(CONSTANT(MAXPAGESIZE)); } :tdata - .tbss (NOLOAD): + + /* + * _edata is the address of the end of the area to be copied with multiboot + * (virtio and xen) + */ + _edata = .; + + /* Read-write data (uninitialized) */ + .tbss : { *(.tbss) } :tbss - - /* Read-write data (uninitialized) */ .bss : { *(.bss) *(COMMON) - } + } :bss + . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; _end = .; @@ -143,6 +154,6 @@ SECTIONS { *(.note.gnu.*) } - _ltdata = SIZEOF(.tdata); + _ltdata = _edata - _stdata; _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_stub.lds b/bindings/solo5_stub.lds index 190fc35f..6858b950 100644 --- a/bindings/solo5_stub.lds +++ b/bindings/solo5_stub.lds @@ -38,8 +38,9 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_LOAD; - tbss PT_TLS; + tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tbss PT_TLS FLAGS(0); /* no perm needed */ + bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; note.manifest PT_NOTE; @@ -114,25 +115,33 @@ SECTIONS { *(.data.*) } - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; - + /* + * tdata and tbss have to be side by side to help the linker caculate the + * various __thread variables offsets. + */ .tdata : { _stdata = .; *(.tdata) + . = ALIGN(CONSTANT(MAXPAGESIZE)); } :tdata - .tbss (NOLOAD): + + /* + * _edata is the address of the end of the area to be copied with multiboot + * (virtio and xen) + */ + _edata = .; + + /* Read-write data (uninitialized) */ + .tbss : { *(.tbss) } :tbss - - /* Read-write data (uninitialized) */ .bss : { *(.bss) *(COMMON) - } + } :bss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; diff --git a/bindings/solo5_virtio.lds b/bindings/solo5_virtio.lds index 09b65ff2..b013f3c8 100644 --- a/bindings/solo5_virtio.lds +++ b/bindings/solo5_virtio.lds @@ -38,8 +38,9 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_LOAD; - tbss PT_TLS; + tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tbss PT_TLS FLAGS(0); /* no perm needed */ + bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ note.abi PT_NOTE; note.manifest PT_NOTE; @@ -115,29 +116,33 @@ SECTIONS { *(.data.*) } - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; - + /* + * tdata and tbss have to be side by side to help the linker caculate the + * various __thread variables offsets. + */ .tdata : { _stdata = .; *(.tdata) + . = ALIGN(CONSTANT(MAXPAGESIZE)); } :tdata - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _etdata =.; + /* + * _edata is the address of the end of the area to be copied with multiboot + * (virtio and xen) + */ + _edata = .; - .tbss (NOLOAD): + /* Read-write data (uninitialized) */ + .tbss : { *(.tbss) } :tbss - - /* Read-write data (uninitialized) */ .bss : { *(.bss) *(COMMON) - } + } :bss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -149,6 +154,6 @@ SECTIONS { *(.note.gnu.*) } - _ltdata = _etdata - _stdata; + _ltdata = _edata - _stdata; _ltbss = SIZEOF(.tbss); } diff --git a/bindings/solo5_xen.lds b/bindings/solo5_xen.lds index d3efa377..1e7bd053 100644 --- a/bindings/solo5_xen.lds +++ b/bindings/solo5_xen.lds @@ -38,8 +38,9 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_LOAD; - tbss PT_TLS; + tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tbss PT_TLS FLAGS(0); /* no perm needed */ + bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ note.xen PT_NOTE; note.abi PT_NOTE; @@ -120,29 +121,33 @@ SECTIONS { *(.data.*) } - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _edata = .; - + /* + * tdata and tbss have to be side by side to help the linker caculate the + * various __thread variables offsets. + */ .tdata : { _stdata = .; *(.tdata) + . = ALIGN(CONSTANT(MAXPAGESIZE)); } :tdata - . = ALIGN(CONSTANT(MAXPAGESIZE)); - _etdata = .; + /* + * _edata is the address of the end of the area to be copied with multiboot + * (virtio and xen) + */ + _edata = .; - .tbss (NOLOAD): + /* Read-write data (uninitialized) */ + .tbss : { *(.tbss) } :tbss - - /* Read-write data (uninitialized) */ .bss : { *(.bss) *(COMMON) - } + } :bss . = ALIGN(CONSTANT(MAXPAGESIZE)); _ebss = .; @@ -154,6 +159,6 @@ SECTIONS { *(.note.gnu.*) } - _ltdata = _etdata - _stdata; + _ltdata = _edata - _stdata; _ltbss = SIZEOF(.tbss); } diff --git a/bindings/virtio/boot.S b/bindings/virtio/boot.S index a8e383ec..de216127 100644 --- a/bindings/virtio/boot.S +++ b/bindings/virtio/boot.S @@ -44,7 +44,7 @@ _multiboot_header: .long -(MULTIBOOT_HEADER_MAGIC+MYMULTIBOOT_FLAGS) .long _multiboot_header .long 0x100000 -.long _etdata +.long _edata .long _ebss .long _start32 diff --git a/bindings/xen/boot.S b/bindings/xen/boot.S index 23b90577..4ddd5935 100644 --- a/bindings/xen/boot.S +++ b/bindings/xen/boot.S @@ -39,7 +39,7 @@ .long -(MULTIBOOT_HEADER_MAGIC+MYMULTIBOOT_FLAGS) .long _multiboot_header .long 0x100000 - .long _etdata + .long _edata .long _ebss .long _start32 diff --git a/tenders/common/elf.c b/tenders/common/elf.c index 5422f718..12bc952c 100644 --- a/tenders/common/elf.c +++ b/tenders/common/elf.c @@ -243,8 +243,14 @@ void elf_load(int bin_fd, const char *bin_name, uint8_t *mem, size_t mem_size, Elf64_Xword p_align = phdr[ph_i].p_align; Elf64_Addr temp, p_vaddr_start, p_vaddr_end; - /* Skip non-PT_LOAD and empty PT_LOAD sections */ - if (phdr[ph_i].p_type != PT_LOAD || p_filesz == 0) + /* + * consider only non empty PT_LOAD and PT_TLS with R flag sections + * (*bss section have no flags in the linker scripts) + */ + if (! \ + (phdr[ph_i].p_filesz != 0 && \ + (phdr[ph_i].p_type == PT_LOAD || \ + (phdr[ph_i].p_type == PT_TLS && (phdr[ph_i].p_flags & PF_R))))) continue; if (p_vaddr < p_min_loadaddr) From 9eeaadaadb9eac725f2b44517ddf2a6a18341ef8 Mon Sep 17 00:00:00 2001 From: palainp Date: Wed, 8 Feb 2023 11:30:56 +0100 Subject: [PATCH 06/14] keep alignement after data --- bindings/solo5_hvt.lds | 1 + bindings/solo5_muen.lds | 1 + bindings/solo5_stub.lds | 1 + bindings/solo5_virtio.lds | 1 + bindings/solo5_xen.lds | 1 + 5 files changed, 5 insertions(+) diff --git a/bindings/solo5_hvt.lds b/bindings/solo5_hvt.lds index 617d8cbe..0f74e32c 100644 --- a/bindings/solo5_hvt.lds +++ b/bindings/solo5_hvt.lds @@ -117,6 +117,7 @@ SECTIONS { *(.data.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); /* * tdata and tbss have to be side by side to help the linker caculate the * various __thread variables offsets. diff --git a/bindings/solo5_muen.lds b/bindings/solo5_muen.lds index 61d297e9..5453a1d3 100644 --- a/bindings/solo5_muen.lds +++ b/bindings/solo5_muen.lds @@ -116,6 +116,7 @@ SECTIONS { *(.data.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); /* * tdata and tbss have to be side by side to help the linker caculate the * various __thread variables offsets. diff --git a/bindings/solo5_stub.lds b/bindings/solo5_stub.lds index 6858b950..667bfac2 100644 --- a/bindings/solo5_stub.lds +++ b/bindings/solo5_stub.lds @@ -115,6 +115,7 @@ SECTIONS { *(.data.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); /* * tdata and tbss have to be side by side to help the linker caculate the * various __thread variables offsets. diff --git a/bindings/solo5_virtio.lds b/bindings/solo5_virtio.lds index b013f3c8..a701d6ab 100644 --- a/bindings/solo5_virtio.lds +++ b/bindings/solo5_virtio.lds @@ -116,6 +116,7 @@ SECTIONS { *(.data.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); /* * tdata and tbss have to be side by side to help the linker caculate the * various __thread variables offsets. diff --git a/bindings/solo5_xen.lds b/bindings/solo5_xen.lds index 1e7bd053..b17a5346 100644 --- a/bindings/solo5_xen.lds +++ b/bindings/solo5_xen.lds @@ -121,6 +121,7 @@ SECTIONS { *(.data.*) } + . = ALIGN(CONSTANT(MAXPAGESIZE)); /* * tdata and tbss have to be side by side to help the linker caculate the * various __thread variables offsets. From 59b902c8f55d455770f4c7bdc588e3be5edb48f0 Mon Sep 17 00:00:00 2001 From: palainp Date: Sat, 11 Feb 2023 10:32:48 +0100 Subject: [PATCH 07/14] - correctly set the TLS tp field of the tcb block, and use functions instead of macros for TLS - update stubs with the new API - update test_tls.c with the new API --- bindings/stub/stubs.c | 15 +++++++++ bindings/tls.c | 65 ++++++++++++++++++++++++++++++++++++ include/solo5.h | 69 +++++++++++++-------------------------- tests/test_tls/test_tls.c | 49 ++++++++------------------- 4 files changed, 115 insertions(+), 83 deletions(-) diff --git a/bindings/stub/stubs.c b/bindings/stub/stubs.c index c8de9739..796a27c4 100644 --- a/bindings/stub/stubs.c +++ b/bindings/stub/stubs.c @@ -105,6 +105,21 @@ solo5_result_t solo5_block_read(solo5_handle_t handle U, solo5_off_t offset U, return SOLO5_R_EUNSPEC; } +size_t solo5_tls_size() +{ + return 0; +} + +uintptr_t solo5_tls_tp_offset(uintptr_t U) +{ + return 0; +} + +solo5_result_t solo5_tls_init(uintptr_t U) +{ + return SOLO5_R_EUNSPEC; +} + solo5_result_t solo5_set_tls_base(uintptr_t base U) { return SOLO5_R_EUNSPEC; diff --git a/bindings/tls.c b/bindings/tls.c index b098310a..7ac87edc 100644 --- a/bindings/tls.c +++ b/bindings/tls.c @@ -20,6 +20,71 @@ #include "bindings.h" +/* _stdata is the address begining of the "not bss" thread variables block */ +extern char _stdata[]; +#define TDATA ((void*)_stdata) + +/* _ltdata and _ltbss are the lengths of the tdata and tbss blocks */ +extern char _ltdata[], _ltbss[]; +#define LTDATA ((size_t)_ltdata) +#define LTBSS ((size_t)_ltbss) + +/* The following define the overhead to the tdata and tbss blocks + * It's processor related + */ +#if defined(__x86_64__) || defined(__powerpc64__) + /* Variant II */ + struct tcb { + void* tp; + }; + + /* solo5_tls_tp_offset tells where we need to set the tp pointer next to + * the data block. It depends on the Variant, for Variant II it's at the end. + */ + #define _solo5_tls_tp_offset(x) (x + LTDATA + LTBSS) + #define _solo5_tls_data_offset(x) (x) + + #define PPC64_TLS_OFFSET 0x7000 + +#elif defined(__aarch64__) + /* Variant I */ + struct tcb { + void* tp; + void* pad; + }; + + /* for Vairant I it's at the begining */ + #define _solo5_tls_tp_offset(x) (x) + #define _solo5_tls_data_offset(x) (x + sizeof(struct tcb)) + +#else +#error Unsupported architecture +#endif + +size_t solo5_tls_size() +{ + return (LTDATA + LTBSS + sizeof(struct tcb)); +} + +uintptr_t solo5_tls_tp_offset(uintptr_t tls) +{ + return _solo5_tls_tp_offset(tls); +} + +solo5_result_t solo5_tls_init(uintptr_t tls) +{ + if ((void*)tls == NULL) return SOLO5_R_EINVAL; + + /* set tp at its proper place in the TLS block */ + uintptr_t *tmp = (uintptr_t*)_solo5_tls_tp_offset(tls); + *tmp = _solo5_tls_tp_offset(tls); + + /* copy the .tdata values */ + memcpy((void*)_solo5_tls_data_offset(tls), TDATA, LTDATA); + + return SOLO5_R_OK; +} + solo5_result_t solo5_set_tls_base(uintptr_t base) { int rc = platform_set_tls_base(base); diff --git a/include/solo5.h b/include/solo5.h index da5353b2..372c194d 100644 --- a/include/solo5.h +++ b/include/solo5.h @@ -128,61 +128,36 @@ void solo5_abort(void) __attribute__((noreturn)); /* - * XXX(palainp): This is an incomplete implementation of TLS. - * It's limited to the local-exec pattern (offset directly from the TLS_BASE - * register). + * XXX(palainp): This implementation of TLS is limited to the local-exec model + * (offset directly from the TLS_BASE register) which is how Solo5 currently + * use TLS. * The usage is as the following for each thread: - * void* tcb1; // defines a TLS block - * tcb1 = calloc(solo5_tls_size(), sizeof(char)); // gets memory for it - * memcpy(solo5_tls_data_offset(tcb1), TDATA, LTDATA); // copy tdata - * solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1); // sets tp ptr + * uintptr_t tcb1; // define a TLS block + * tcb1 = (uintptr_t)calloc(solo5_tls_size(), sizeof(char)); // get memory + * solo5_tls_init(tcb1); // initialize TLS block + * solo5_set_tls_base(solo5_tls_tp_offset(tcb1); // sets tp ptr + * When you want to change for another thread, you just have to: + * solo5_set_tls_base(solo5_tls_tp_offset(tcb2); // sets tp ptr */ -/* _stdata is the address begining of the "not bss" thread variables block */ -extern char _stdata[]; -#define TDATA ((void*)_stdata) - -/* _ltdata and _ltbss are the lengths of the tdata and tbss blocks */ -extern char _ltdata[], _ltbss[]; -#define LTDATA ((size_t)_ltdata) -#define LTBSS ((size_t)_ltbss) +/* + * Returns the size needed for the thread local storage. + */ +size_t solo5_tls_size(); -/* The following define the overhead to the tdata and tbss blocks - * It's processor related +/* + * Returns the tp base address for the TLS block. */ -#if defined(__x86_64__) || defined(__powerpc64__) - /* Variant II */ - struct tcb { - void* tp; - }; - - /* solo5_tls_tp_offset tells where we need to set the tp pointer next to - * the data block. It depends on the Variant, for Variant II it's at the end. - */ - #define solo5_tls_tp_offset(x) (x + LTDATA + LTBSS) - #define solo5_tls_data_offset(x) (x) - - #define PPC64_TLS_OFFSET 0x7000 - -#elif defined(__aarch64__) - /* Variant I */ - struct tcb { - void* tp; - void* pad; - }; - - /* for Vairant I it's at the begining */ - #define tp_offset(x) (x) - #define solo5_tls_data_offset(x) (x + sizeof(struct tcb)) - -#else -#error Unsupported architecture -#endif +uintptr_t solo5_tls_tp_offset(uintptr_t tls); /* - * Returns the size needed for the thread local storage. + * Perform a proper initialisation of the (tls) block (it should be already + * allocated): copy .tdata values and set the last bytes correctly. + * + * Solo5 implementations may return SOLO5_R_EINVAL if the (tls) does not + * satisfy architecture-specific requirements. */ -#define solo5_tls_size() (LTDATA + LTBSS + sizeof(struct tcb)) +solo5_result_t solo5_tls_init(uintptr_t tls); /* * Set the architecture-specific TLS base register to (base). diff --git a/tests/test_tls/test_tls.c b/tests/test_tls/test_tls.c index 6d8a9f38..4bad40c7 100644 --- a/tests/test_tls/test_tls.c +++ b/tests/test_tls/test_tls.c @@ -21,8 +21,8 @@ #include "solo5.h" #include "../../bindings/lib.c" -void* tcb1; -void* tcb2; +uintptr_t tcb1; +uintptr_t tcb2; static void puts(const char *s) { @@ -64,55 +64,32 @@ uint64_t __attribute__ ((noinline)) get_data_not_bss() return _data_not_bss; } -static void putc(const char c) -{ - solo5_console_write(&c, 1); -} - -static void __attribute__ ((noinline)) printhex64(uint64_t x) -{ - char hex[] = "0123456789ABCDEF"; - for(int i=60; i>=0; i-=4) - { - putc(hex[(x>>i)&0xf]); - } - putc('\n'); -} - int solo5_app_main(const struct solo5_start_info *si __attribute__((unused))) { puts("\n**** Solo5 standalone test_tls ****\n\n"); - puts(".tdata is at 0x"); - printhex64((uint64_t)(TDATA)); - puts(".tdata length is "); - printhex64((uint64_t)(LTDATA)); - puts(".tbss length is "); - printhex64((uint64_t)(LTBSS)); - - tcb1 = malloc_stub(solo5_tls_size()); - if (tcb1 == NULL) - return 10; - memcpy(solo5_tls_data_offset(tcb1), TDATA, LTDATA); - tcb2 = malloc_stub(solo5_tls_size()); - if (tcb2 == NULL) + tcb1 = (uintptr_t)malloc_stub(solo5_tls_size()); + if (solo5_tls_init(tcb1) != SOLO5_R_OK) + return 10; + + tcb2 = (uintptr_t)malloc_stub(solo5_tls_size()); + if (solo5_tls_init(tcb2) != SOLO5_R_OK) return 11; - memcpy(solo5_tls_data_offset(tcb2), TDATA, LTDATA); - - if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1)) != SOLO5_R_OK) + + if (solo5_set_tls_base(solo5_tls_tp_offset(tcb1)) != SOLO5_R_OK) return 1; set_data(1); - if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb2)) != SOLO5_R_OK) + if (solo5_set_tls_base(solo5_tls_tp_offset(tcb2)) != SOLO5_R_OK) return 2; set_data(2); - if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb1)) != SOLO5_R_OK) + if (solo5_set_tls_base(solo5_tls_tp_offset(tcb1)) != SOLO5_R_OK) return 3; if (get_data() != 1) return 4; - if (solo5_set_tls_base(solo5_tls_tp_offset((uintptr_t)tcb2)) != SOLO5_R_OK) + if (solo5_set_tls_base(solo5_tls_tp_offset(tcb2)) != SOLO5_R_OK) return 5; if (get_data() != 2) return 6; From 491157f70c0c921e19e1ac9d3ec83ef903562f6c Mon Sep 17 00:00:00 2001 From: palainp Date: Sat, 11 Feb 2023 10:56:58 +0100 Subject: [PATCH 08/14] fix name omission --- bindings/stub/stubs.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bindings/stub/stubs.c b/bindings/stub/stubs.c index 796a27c4..c4532a7c 100644 --- a/bindings/stub/stubs.c +++ b/bindings/stub/stubs.c @@ -110,12 +110,12 @@ size_t solo5_tls_size() return 0; } -uintptr_t solo5_tls_tp_offset(uintptr_t U) +uintptr_t solo5_tls_tp_offset(uintptr_t tls U) { return 0; } -solo5_result_t solo5_tls_init(uintptr_t U) +solo5_result_t solo5_tls_init(uintptr_t tls U) { return SOLO5_R_EUNSPEC; } From 36c9d02f82e3cb3f478614005f768d9f708f0756 Mon Sep 17 00:00:00 2001 From: palainp Date: Sat, 11 Feb 2023 10:58:38 +0100 Subject: [PATCH 09/14] fix indendation --- bindings/stub/stubs.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/bindings/stub/stubs.c b/bindings/stub/stubs.c index c4532a7c..04f504b0 100644 --- a/bindings/stub/stubs.c +++ b/bindings/stub/stubs.c @@ -107,17 +107,17 @@ solo5_result_t solo5_block_read(solo5_handle_t handle U, solo5_off_t offset U, size_t solo5_tls_size() { - return 0; + return 0; } uintptr_t solo5_tls_tp_offset(uintptr_t tls U) { - return 0; + return 0; } solo5_result_t solo5_tls_init(uintptr_t tls U) { - return SOLO5_R_EUNSPEC; + return SOLO5_R_EUNSPEC; } solo5_result_t solo5_set_tls_base(uintptr_t base U) From 7d618d6b09c0d84c102677ebeb72ce5727c04c75 Mon Sep 17 00:00:00 2001 From: palainp Date: Thu, 16 Feb 2023 08:47:00 +0100 Subject: [PATCH 10/14] set tp offset for ppc64 back --- bindings/tls.c | 41 ++++++++++++++++++++++++++++------------- 1 file changed, 28 insertions(+), 13 deletions(-) diff --git a/bindings/tls.c b/bindings/tls.c index 7ac87edc..0bde6663 100644 --- a/bindings/tls.c +++ b/bindings/tls.c @@ -38,12 +38,6 @@ extern char _ltdata[], _ltbss[]; void* tp; }; - /* solo5_tls_tp_offset tells where we need to set the tp pointer next to - * the data block. It depends on the Variant, for Variant II it's at the end. - */ - #define _solo5_tls_tp_offset(x) (x + LTDATA + LTBSS) - #define _solo5_tls_data_offset(x) (x) - #define PPC64_TLS_OFFSET 0x7000 #elif defined(__aarch64__) @@ -53,10 +47,6 @@ extern char _ltdata[], _ltbss[]; void* pad; }; - /* for Vairant I it's at the begining */ - #define _solo5_tls_tp_offset(x) (x) - #define _solo5_tls_data_offset(x) (x + sizeof(struct tcb)) - #else #error Unsupported architecture #endif @@ -68,7 +58,32 @@ size_t solo5_tls_size() uintptr_t solo5_tls_tp_offset(uintptr_t tls) { - return _solo5_tls_tp_offset(tls); + uintptr_t tp; +#if defined(__powerpc64__) + tp = PPC64_TLS_OFFSET + tls; +#elif defined(__x86_64__) + tp = tls + LTDATA + LTBSS; +#elif defined(__aarch64__) + tp = tls; +#else +#error Unsupported architecture +#endif + + return tp; +} + +uintptr_t _solo5_tls_data_offset(uintptr_t tls) +{ + uintptr_t data; +#if defined(__x86_64__) || defined(__powerpc64__) + data = tls; +#elif defined(__aarch64__) + data = data + sizeof(struct tcb); +#else +#error Unsupported architecture +#endif + + return data; } solo5_result_t solo5_tls_init(uintptr_t tls) @@ -76,8 +91,8 @@ solo5_result_t solo5_tls_init(uintptr_t tls) if ((void*)tls == NULL) return SOLO5_R_EINVAL; /* set tp at its proper place in the TLS block */ - uintptr_t *tmp = (uintptr_t*)_solo5_tls_tp_offset(tls); - *tmp = _solo5_tls_tp_offset(tls); + uintptr_t *tmp = (uintptr_t*)solo5_tls_tp_offset(tls); + *tmp = *tmp; /* copy the .tdata values */ memcpy((void*)_solo5_tls_data_offset(tls), TDATA, LTDATA); From e06a111c4666789a9dff54ad082cf3f9b6762dc2 Mon Sep 17 00:00:00 2001 From: palainp Date: Thu, 16 Feb 2023 09:01:09 +0100 Subject: [PATCH 11/14] try fix for BSD systems (if succeed should be rebased) --- bindings/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/tls.c b/bindings/tls.c index 0bde6663..119c1563 100644 --- a/bindings/tls.c +++ b/bindings/tls.c @@ -92,7 +92,7 @@ solo5_result_t solo5_tls_init(uintptr_t tls) /* set tp at its proper place in the TLS block */ uintptr_t *tmp = (uintptr_t*)solo5_tls_tp_offset(tls); - *tmp = *tmp; + *tmp = solo5_tls_tp_offset(tls); /* copy the .tdata values */ memcpy((void*)_solo5_tls_data_offset(tls), TDATA, LTDATA); From 23651e29af4d7a69fad615d65778f55ad5bc20f7 Mon Sep 17 00:00:00 2001 From: palainp Date: Thu, 16 Feb 2023 09:21:28 +0100 Subject: [PATCH 12/14] set tdata back as PT_LOAD, set the elf loader back as loading only PT_LOAD sections (and add non empty test in case .tdata is empty) --- bindings/solo5_hvt.lds | 2 +- bindings/solo5_muen.lds | 2 +- bindings/solo5_spt.lds | 2 +- bindings/solo5_stub.lds | 2 +- bindings/solo5_virtio.lds | 2 +- bindings/solo5_xen.lds | 2 +- tenders/common/elf.c | 8 ++------ 7 files changed, 8 insertions(+), 12 deletions(-) diff --git a/bindings/solo5_hvt.lds b/bindings/solo5_hvt.lds index 0f74e32c..b3cef0cd 100644 --- a/bindings/solo5_hvt.lds +++ b/bindings/solo5_hvt.lds @@ -40,7 +40,7 @@ PHDRS { rodata PT_LOAD FLAGS(4); data PT_LOAD; - tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tdata PT_LOAD FLAGS(4); /* RO: this have to be copied into each thread */ tbss PT_TLS FLAGS(0); /* no perm needed */ bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ diff --git a/bindings/solo5_muen.lds b/bindings/solo5_muen.lds index 5453a1d3..31f68b2e 100644 --- a/bindings/solo5_muen.lds +++ b/bindings/solo5_muen.lds @@ -39,7 +39,7 @@ PHDRS { FLAGS values come from PF_x in elf.h */ rodata PT_LOAD; data PT_LOAD; - tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tdata PT_LOAD FLAGS(4); /* RO: this have to be copied into each thread */ tbss PT_TLS FLAGS(0); /* no perm needed */ bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ diff --git a/bindings/solo5_spt.lds b/bindings/solo5_spt.lds index 775102dc..9d0465c7 100644 --- a/bindings/solo5_spt.lds +++ b/bindings/solo5_spt.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tdata PT_LOAD FLAGS(4); /* RO: this have to be copied into each thread */ tbss PT_TLS FLAGS(0); /* no perm needed */ bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ diff --git a/bindings/solo5_stub.lds b/bindings/solo5_stub.lds index 667bfac2..6dd27f7c 100644 --- a/bindings/solo5_stub.lds +++ b/bindings/solo5_stub.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tdata PT_LOAD FLAGS(4); /* RO: this have to be copied into each thread */ tbss PT_TLS FLAGS(0); /* no perm needed */ bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ diff --git a/bindings/solo5_virtio.lds b/bindings/solo5_virtio.lds index a701d6ab..fa6cc4f9 100644 --- a/bindings/solo5_virtio.lds +++ b/bindings/solo5_virtio.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tdata PT_LOAD FLAGS(4); /* RO: this have to be copied into each thread */ tbss PT_TLS FLAGS(0); /* no perm needed */ bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ diff --git a/bindings/solo5_xen.lds b/bindings/solo5_xen.lds index b17a5346..d8b11ea4 100644 --- a/bindings/solo5_xen.lds +++ b/bindings/solo5_xen.lds @@ -38,7 +38,7 @@ PHDRS { text PT_LOAD FLAGS(5); /* No FILEHDR or PHDRS, force R/E only. FLAGS values come from PF_x in elf.h */ data PT_LOAD; - tdata PT_TLS FLAGS(4); /* RO: this have to be copied into each thread */ + tdata PT_LOAD FLAGS(4); /* RO: this have to be copied into each thread */ tbss PT_TLS FLAGS(0); /* no perm needed */ bss PT_NULL FLAGS(0); note.not_openbsd PT_NOTE; /* Must come first. */ diff --git a/tenders/common/elf.c b/tenders/common/elf.c index 12bc952c..50ddcce2 100644 --- a/tenders/common/elf.c +++ b/tenders/common/elf.c @@ -244,13 +244,9 @@ void elf_load(int bin_fd, const char *bin_name, uint8_t *mem, size_t mem_size, Elf64_Addr temp, p_vaddr_start, p_vaddr_end; /* - * consider only non empty PT_LOAD and PT_TLS with R flag sections - * (*bss section have no flags in the linker scripts) + * consider only non empty PT_LOAD */ - if (! \ - (phdr[ph_i].p_filesz != 0 && \ - (phdr[ph_i].p_type == PT_LOAD || \ - (phdr[ph_i].p_type == PT_TLS && (phdr[ph_i].p_flags & PF_R))))) + if (phdr[ph_i].p_filesz == 0 || phdr[ph_i].p_type != PT_LOAD) continue; if (p_vaddr < p_min_loadaddr) From de8661facea569945334874f784ad2b4159bb05f Mon Sep 17 00:00:00 2001 From: palainp Date: Wed, 22 Feb 2023 20:54:56 +0100 Subject: [PATCH 13/14] use calculated tp value --- bindings/tls.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bindings/tls.c b/bindings/tls.c index 119c1563..69a17015 100644 --- a/bindings/tls.c +++ b/bindings/tls.c @@ -92,7 +92,7 @@ solo5_result_t solo5_tls_init(uintptr_t tls) /* set tp at its proper place in the TLS block */ uintptr_t *tmp = (uintptr_t*)solo5_tls_tp_offset(tls); - *tmp = solo5_tls_tp_offset(tls); + *tmp = (uintptr_t)tmp; /* copy the .tdata values */ memcpy((void*)_solo5_tls_data_offset(tls), TDATA, LTDATA); From ec9ca09cd900899eb086ebd75f8521de02cc4ebd Mon Sep 17 00:00:00 2001 From: palainp Date: Tue, 14 Mar 2023 12:32:59 +0100 Subject: [PATCH 14/14] fix indentation --- bindings/tls.c | 2 +- include/solo5.h | 5 ++--- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/bindings/tls.c b/bindings/tls.c index 69a17015..0f14480e 100644 --- a/bindings/tls.c +++ b/bindings/tls.c @@ -88,7 +88,7 @@ uintptr_t _solo5_tls_data_offset(uintptr_t tls) solo5_result_t solo5_tls_init(uintptr_t tls) { - if ((void*)tls == NULL) return SOLO5_R_EINVAL; + if ((void*)tls == NULL) return SOLO5_R_EINVAL; /* set tp at its proper place in the TLS block */ uintptr_t *tmp = (uintptr_t*)solo5_tls_tp_offset(tls); diff --git a/include/solo5.h b/include/solo5.h index 372c194d..28e5c9b2 100644 --- a/include/solo5.h +++ b/include/solo5.h @@ -128,9 +128,8 @@ void solo5_abort(void) __attribute__((noreturn)); /* - * XXX(palainp): This implementation of TLS is limited to the local-exec model - * (offset directly from the TLS_BASE register) which is how Solo5 currently - * use TLS. + * This implementation of TLS is limited to the local-exec model (offset + * directly from the TLS_BASE register) which is how Solo5 currently use TLS. * The usage is as the following for each thread: * uintptr_t tcb1; // define a TLS block * tcb1 = (uintptr_t)calloc(solo5_tls_size(), sizeof(char)); // get memory