From f5475890894b4d542f622cee27604de15b41bb4b Mon Sep 17 00:00:00 2001 From: Jaymes Wilks Date: Mon, 4 Feb 2019 14:06:56 -0600 Subject: Support thread local storage Generally adds support to declare variables as thread_local - Add support in HBRT start assembly to skip adjusting TLS relocations - Add support in linker to generate tagged TLS entries - Update linker to process TLS relocations correctly - Update TLS code to ignore top half of module ID - Update module images to hold a "module ID" - Update custome linker to update module ID during binary link - Update TLS code to track TLS sections via module ID Change-Id: I1589550d7787beb08827ca24a728397dedf0373b RTC: 147599 Reviewed-on: http://rchgit01.rchland.ibm.com/gerrit1/71709 Reviewed-by: Ilya Smirnov Reviewed-by: Michael Baiocchi Tested-by: Jenkins Server Tested-by: FSP CI Jenkins Tested-by: Jenkins OP Build CI Tested-by: Jenkins OP HW Reviewed-by: Daniel M. Crowell --- src/build/linker/linker.C | 123 ++++++++++++++++++++++++++++++++++-- src/include/util/nolockfree/stack.H | 115 +++++++++++++++++++++++++++++++++ src/lib/makefile | 3 +- src/lib/tls.C | 123 ++++++++++++++++++++++++------------ src/lib/tlsrt.C | 31 +++++++++ src/makefile | 5 +- src/runtime/rt_start.S | 35 +++++++++- src/usr/module_init.C | 18 +++++- src/usr/testcore/rtloader/loader.H | 2 +- 9 files changed, 400 insertions(+), 55 deletions(-) create mode 100644 src/include/util/nolockfree/stack.H create mode 100644 src/lib/tlsrt.C (limited to 'src') diff --git a/src/build/linker/linker.C b/src/build/linker/linker.C index fe5f651ea..9e4751e41 100644 --- a/src/build/linker/linker.C +++ b/src/build/linker/linker.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2018 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* [+] Jan Hlavac */ /* */ @@ -132,6 +132,10 @@ struct Object FILE * iv_output; //!< output file handle ssize_t tls_module; //!< module id of this module's // thread local storage. + map tls_vars; //!< keep track of TLS variables in + // this module by mapping offsets + // to names for use with identifying + // unnamed DTPRELs /** * Read the object from it's file and extract bfd, text, & data image * @param[in] i_file : file path @@ -219,7 +223,7 @@ inline bool Object::isELF() } /** - * Infomraiton needed to build the Module table in each output image + * Information needed to build the Module table in each output image */ class ModuleTable { @@ -289,11 +293,24 @@ vector module_tables; map weak_symbols; set all_symbols; set weak_symbols_to_check; + +// map TLS symbol names to TLS module IDs +map tls_modules; + +// map TLS symbol names to TLS offsets +map tls_offsets; + bool includes_extended_image = false; bool relocation = true; size_t next_tls_id = 0; +/** + * @brief Marker (ASCII 'TLS' + 0x00) or'd into bit 0 position of a TLS module + * relocation to flag it as such for runtime relocation processing + */ +const uint64_t TLS_MARKER = 0x544C530000000000ULL; + //----------------------------------------------------------------------------- // MAIN //----------------------------------------------------------------------------- @@ -612,6 +629,38 @@ bool Object::write_object() cout << strerror(error) << endl; } + // Look for the "TLS_MODULE_ID" symbol in the module. If found, seek to + // its location in the final binary and update it with the TLS module ID + // for this module. + if (symbols.find(VFS_TOSTRING(TLS_MODULE_ID)) != symbols.end()) + { + fseek(iv_output, symbols[VFS_TOSTRING(TLS_MODULE_ID)].address + + offset + data.vma_offset, SEEK_SET); + size_t tlsModuleId = 0; + bfd_putb64(get_tls_module(),&tlsModuleId); + if (sizeof(tlsModuleId) != fwrite(&tlsModuleId, sizeof(uint8_t), + sizeof(tlsModuleId), iv_output)) + { + const int error = errno; + cout << "Error writing TLS_MODULE_ID to output: " << endl; + cout << strerror(error) << endl; + } + else + { + cout << "Setting module ID to " << get_tls_module() << " for " + << name << " addr = " + << symbols[VFS_TOSTRING(TLS_MODULE_ID)].address + << " + " << offset + data.vma_offset << endl; + } + + // Seek back to where the cursor would have been, had the module + // ID not been updated + fseek(iv_output, offset + data.vma_offset + data.size, SEEK_SET); + } + else + { + cout << " module ID not found for " << name << endl; + } } else // binary blob { @@ -690,11 +739,27 @@ bool Object::read_relocation() cout << "\tSymbol: " << syms[i]->name << endl; cout << "\t\tAddress: " << std::hex << syms[i]->value << endl; + bool is_tls = false; + // Determine symbol types. + if (syms[i]->flags & BSF_THREAD_LOCAL) + { + cout << "\t\tTLS_VARIABLE" << endl; + is_tls = true; + } + if (syms[i]->flags & BSF_GLOBAL) { s.type |= Symbol::GLOBAL; - cout << "\t\tGLOBAL" << endl; + cout << "\t\tGLOBAL"; + if (is_tls) + { + cout << " TLS offset: " << bfd_asymbol_value(syms[i]); + + // store the name in a map of offsets to TLS variable names + tls_vars[bfd_asymbol_value(syms[i])] = s.name; + } + cout << endl; } else if (syms[i]->flags & (BSF_LOCAL | BSF_WEAK | BSF_GNU_UNIQUE)) { @@ -827,10 +892,19 @@ bool Object::perform_local_relocations() bool needs_relocation = true; + bool is_weak = false; + fseek(iv_output, offset + i->address, SEEK_SET); fread(data, sizeof(uint64_t), 1, iv_output); + if (weak_symbols.find(i->name) != weak_symbols.end()) + { + cout << "\t\tWEAK" << endl; + is_weak = true; + } + address = bfd_getb64(data); + if ((address != i->addend) && (address != 0)) { ostringstream oss; @@ -855,13 +929,25 @@ bool Object::perform_local_relocations() address = get_tls_module(); needs_relocation = false; relocation = address; + + cout << "\t\tTLS_MODULE" << endl; } else if (i->type & Symbol::TLS_OFFSET) { // Set value to TLS offset. - address = i->addend - VFS_PPC64_DTPREL_OFFSET; + cout << "\t\tTLS_OFFSET" << endl; + address = relocation = i->addend - VFS_PPC64_DTPREL_OFFSET; needs_relocation = false; - relocation = address; + + // look up the offset in tls_vars find the name and use that + // to map the name to the correct TLS offset + tls_offsets[tls_vars[i->addend]] = relocation; + tls_modules[tls_vars[i->addend]] = get_tls_module(); + } + else if (is_weak && address == 0) + { + cout << "\tWEAK NULL" << endl; + relocation = 0; } else // Perform relocation. { @@ -956,6 +1042,12 @@ bool Object::perform_global_relocations() } else { + bool is_tls = false; + if (tls_modules.find(i->name) != tls_modules.end()) + { + is_tls = true; + } + if (s.type & Symbol::FUNCTION) { cout << "\tTOC link for function: " << s.name @@ -966,7 +1058,28 @@ bool Object::perform_global_relocations() cout << "\tOffset to " << i->addend << endl; symbol_addr += i->addend; } + symbol_addr += j->base_addr; + + if (is_tls) + { + if (i->type & Symbol::TLS_MODULE) + { + symbol_addr = tls_modules[i->name]; + + // Bitwise OR the TLS marker into the relocation + // to flag it as a TLS module entry for + // relocation processing code. This is safe + // since it would take 4 giga-modules to over + // flow into that space. + symbol_addr |= TLS_MARKER; + } + else if (i->type & Symbol::TLS_OFFSET) + { + symbol_addr = tls_offsets[i->name]; + } + } + bfd_putb64(symbol_addr, data); fseek(iv_output, offset + i->address, SEEK_SET); fwrite(data, sizeof(uint64_t), 1, iv_output); diff --git a/src/include/util/nolockfree/stack.H b/src/include/util/nolockfree/stack.H new file mode 100644 index 000000000..bc2bb5fbb --- /dev/null +++ b/src/include/util/nolockfree/stack.H @@ -0,0 +1,115 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/include/util/nolockfree/stack.H $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2010,2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +#ifndef __UTIL_NOLOCKFREE_STACK_H +#define __UTIL_NOLOCKFREE_STACK_H + +#include +#include + +namespace Util +{ + namespace NoLockFree + { + + /** + * @brief Non-lockfree stack implementation + * + * This is an intrusive container design, meaning elements being + * added to the stack must have a 'next' member of _T* type. This + * container is not threadsafe. + * + * @note: For a lockfree stack implementation, see Util::LockFree::Stack + */ + template + class Stack + { + public: + + /** + * @brief Constructor + */ + Stack() + : head(nullptr) + { + } + + /** + * @brief Pop an element from the stack. + * + * @return _T* The pointer to the element popped from the stack + */ + _T* pop(); + + /** + * @brief Push an element to the stack. + * + * @param[in] p Pointer to the element to add to the stack. + */ + void push(_T* p); + + /** + * @brief Get a pointer to the first element in the stack + * + * @return _T* The pointer to the first element + * @Note: SMP safety of this pointer is not guaranteed. + */ + _T* first(); + + private: + _T* head; + }; + + template + _T* Stack<_T>::first() + { + return head; + } + + template + _T* Stack<_T>::pop() + { + auto original = head; + if (unlikely(nullptr == original)) + { + return nullptr; + } + head = original->next; + return original; + } + + template + void Stack<_T>::push(_T* p) + { + p->next = head; + head = p; + } + + } // End NoLockFree namespace + +} // End Util namespace + +#endif // __UTIL_NOLOCKFREE_STACK_H + diff --git a/src/lib/makefile b/src/lib/makefile index 5e64025d1..406d5ead8 100644 --- a/src/lib/makefile +++ b/src/lib/makefile @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2010,2017 +# Contributors Listed Below - COPYRIGHT 2010,2019 # [+] International Business Machines Corp. # # @@ -50,6 +50,7 @@ OBJS += utilmisc.o OBJS += tls.o OBJS += errno.o +OBJS += tlsrt.o ifdef HOSTBOOT_MEMORY_LEAKS COMMONFLAGS += -DHOSTBOOT_MEMORY_LEAKS=1 diff --git a/src/lib/tls.C b/src/lib/tls.C index 4fcafb23b..3e2294251 100644 --- a/src/lib/tls.C +++ b/src/lib/tls.C @@ -31,9 +31,21 @@ #include #include #include +#ifndef __HOSTBOOT_RUNTIME #include +#else +#include +#endif #include +/** + * @brief Mask which suppresses ignored portions of a TLS module ID. When + * The linker creates a module ID, it prefixes it with "TLS" + 0x00 + * as the first 32 bits. This mask slices that off to leave just the + * normalized module ID + */ +const size_t TLS_MODULE_MASK = 0x00000000FFFFFFFFULL; + /** Thread Local Storage - How it works. * * For background: @@ -86,8 +98,36 @@ struct __tls_linker_tuple /** Info about the .tdata section for each module. */ struct __tls_module { - void* sect_addr; - size_t size; + void* sect_addr; //< Starting address of module + size_t size; //< Size of module + size_t module; //< Module ID of this module + //< (set by custom linker) + + /** + * @brief Default constructor + */ + __tls_module() + : sect_addr(0), + size(0), + module(0) + { + } + + /** + * @brief Specialized contstructor + * + * @param[in] i_start Module starting address. Must not be nullptr. + * @param[in] i_size Module size in bytes + * @param[in] i_module Modue ID of the module + */ + __tls_module(void* const i_start, + const size_t i_size, + const size_t i_module) + : sect_addr(i_start), + size(i_size), + module(i_module) + { + } }; /** TLS destructor data. */ @@ -103,7 +143,11 @@ struct __tls_dtor struct __tls_thread_info { size_t count; +#ifndef __HOSTBOOT_RUNTIME Util::Lockfree::Stack<__tls_dtor> dtors; +#else + Util::NoLockFree::Stack<__tls_dtor> dtors; +#endif void* blobs[0]; }; @@ -114,51 +158,47 @@ std::vector<__tls_module> __tls_pending_modules; /** Get the previously registered __tls_module data for a TLS variable */ const __tls_module* __tls_get_module(const __tls_linker_tuple* tuple) { + size_t tuple_module = tuple->module & TLS_MODULE_MASK; + // Look the module up in the __tls_modules first, in case we've seen // this module before in another thread. - if ((__tls_modules.size() > tuple->module) && - (__tls_modules[tuple->module].sect_addr != nullptr)) + if ((__tls_modules.size() > tuple_module) && + (__tls_modules[tuple_module].sect_addr != nullptr)) { - return &__tls_modules[tuple->module]; + return &__tls_modules[tuple_module]; } // We plan to insert a new module, so make sure we can contain it. - if (__tls_modules.size() <= tuple->module) + if (__tls_modules.size() <= tuple_module) { - __tls_modules.resize(tuple->module+1); + __tls_modules.resize(tuple_module+1); } // This is the first time we've seen this module. Need to look up in // pending. - // The TLS sections are at the beginning of the .rodata section and the - // linker tuples are somewhere in .data. Therefore sect_addr < tuple. - // Search __tls_pending_modules for the highest address section that is - // less than the tuple address. - auto best = __tls_pending_modules.begin(); - auto curr = best; - while(curr != __tls_pending_modules.end()) - { - if ((curr->sect_addr > best->sect_addr) && - (curr->sect_addr < tuple)) + // The module should have pre-registered its module ID in association + // with its starting address and size; look for a module ID match. + auto moduleItr = std::find_if( + __tls_pending_modules.begin(), + __tls_pending_modules.end(), + [&tuple_module](const __tls_module& i_module) { - best = curr; - } - ++curr; - } - assert(best != __tls_pending_modules.end()); + return (tuple_module == i_module.module); + }); + assert(moduleItr != __tls_pending_modules.end()); // Copy it into the __tls_modules and remove it from the pending list. - __tls_modules[tuple->module] = *best; - __tls_pending_modules.erase(best); + __tls_modules[tuple_module] = *moduleItr; + __tls_pending_modules.erase(moduleItr); - return &__tls_modules[tuple->module]; + return &__tls_modules[tuple_module]; } /* Since Hostboot runtime only has a single thread, we'll just create a * single global TLS area. */ #ifdef __HOSTBOOT_RUNTIME -task_t __tls_task_struct; +task_t tls_task_struct; #endif /** Get a TLS variable address @@ -168,6 +208,8 @@ task_t __tls_task_struct; extern "C" void* __tls_get_addr(const __tls_linker_tuple* tuple) { + size_t tuple_module = tuple->module & TLS_MODULE_MASK; + task_t* task = nullptr; #ifdef __HOSTBOOT_RUNTIME task = &tls_task_struct; @@ -184,36 +226,36 @@ void* __tls_get_addr(const __tls_linker_tuple* tuple) // - tls[module] is nullptr // Then: module blob needs to be allocated. if ((tls_info == nullptr) || - (tls_info->count <= tuple->module) || - (tls_info->blobs[tuple->module] == nullptr)) + (tls_info->count <= tuple_module) || + (tls_info->blobs[tuple_module] == nullptr)) { // If there isn't room for the module's blob, we need to allocate it. - if ((tls_info == nullptr) || (tls_info->count <= tuple->module)) + if ((tls_info == nullptr) || (tls_info->count <= tuple_module)) { - decltype(__tls_thread_info::count) old_size = 0; + decltype(__tls_thread_info::count) old_count = 0; auto new_size = sizeof(__tls_thread_info) + - sizeof(void*)*(tuple->module+1); + sizeof(void*)*(tuple_module+1); // Allocate or reallocate the tls info. if (tls_info == nullptr) { - old_size = 0; + old_count = 0; tls_info = reinterpret_cast( malloc(new_size)); memset(&tls_info->dtors, '\0', sizeof(tls_info->dtors)); } else { - old_size = tls_info->count; + old_count = tls_info->count; tls_info = reinterpret_cast( realloc(tls_info, new_size)); } // Clear the newly allocated area and update the count. - memset(&tls_info->blobs[old_size], '\0', new_size - - (sizeof(__tls_thread_info) + sizeof(void*)*old_size)); - tls_info->count = tuple->module+1; + memset(&tls_info->blobs[old_count], '\0', new_size - + (sizeof(__tls_thread_info) + sizeof(void*)*old_count)); + tls_info->count = tuple_module+1; // save into task struct. task->tls_context = tls_info; @@ -224,7 +266,7 @@ void* __tls_get_addr(const __tls_linker_tuple* tuple) mutex_lock(&__tls_mutex); { auto module = __tls_get_module(tuple); - auto blob = tls_info->blobs[tuple->module] = malloc(module->size); + auto blob = tls_info->blobs[tuple_module] = malloc(module->size); memcpy(blob, module->sect_addr, module->size); } mutex_unlock(&__tls_mutex); @@ -232,7 +274,7 @@ void* __tls_get_addr(const __tls_linker_tuple* tuple) } // Return the offset of the TLS variable from this module's blob. - return &reinterpret_cast(tls_info->blobs[tuple->module]) + return &reinterpret_cast(tls_info->blobs[tuple_module]) [tuple->offset+VFS_PPC64_DTPREL_OFFSET]; } @@ -240,13 +282,12 @@ void* __tls_get_addr(const __tls_linker_tuple* tuple) * * Called by init() in module_init. */ -void __tls_register(void* s, void* e) +void __tls_register(void* s, void* e, const size_t i_module) { if (s == e) return; - __tls_module m = { s, ((size_t)e) - ((size_t)s) }; - + __tls_module m(s, ((size_t)e) - ((size_t)s), i_module ); mutex_lock(&__tls_mutex); { __tls_pending_modules.push_back(m); diff --git a/src/lib/tlsrt.C b/src/lib/tlsrt.C new file mode 100644 index 000000000..100299d16 --- /dev/null +++ b/src/lib/tlsrt.C @@ -0,0 +1,31 @@ +/* IBM_PROLOG_BEGIN_TAG */ +/* This is an automatically generated prolog. */ +/* */ +/* $Source: src/lib/tlsrt.C $ */ +/* */ +/* OpenPOWER HostBoot Project */ +/* */ +/* Contributors Listed Below - COPYRIGHT 2015,2019 */ +/* [+] International Business Machines Corp. */ +/* */ +/* */ +/* Licensed under the Apache License, Version 2.0 (the "License"); */ +/* you may not use this file except in compliance with the License. */ +/* You may obtain a copy of the License at */ +/* */ +/* http://www.apache.org/licenses/LICENSE-2.0 */ +/* */ +/* Unless required by applicable law or agreed to in writing, software */ +/* distributed under the License is distributed on an "AS IS" BASIS, */ +/* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or */ +/* implied. See the License for the specific language governing */ +/* permissions and limitations under the License. */ +/* */ +/* IBM_PROLOG_END_TAG */ + +// There are no good ways to apply the runtime condition to a non-module +// object, so this facilitates creating two different verisions of the +// same object +#define __HOSTBOOT_RUNTIME 1 +#include "tls.C" + diff --git a/src/makefile b/src/makefile index 6b562d166..a9c918dd0 100644 --- a/src/makefile +++ b/src/makefile @@ -58,7 +58,6 @@ BASE_OBJECTS += cxxtest_data.o BASE_OBJECTS += sprintf.o BASE_OBJECTS += crc32.o BASE_OBJECTS += utilmisc.o -BASE_OBJECTS += tls.o ifdef HOSTBOOT_PROFILE BASE_OBJECTS += gcov.o @@ -340,7 +339,7 @@ hbibl_OBJECTS += ${BOOTLDR_OBJECTS} hbibl_LDFILE = bootloader.ld hbibl_NO_RELOCATION = 1 -hbicore_OBJECTS += ${BASE_OBJECTS} +hbicore_OBJECTS += ${BASE_OBJECTS} tls.o hbicore_OBJECTS += ${DIRECT_BOOT_OBJECTS} hbicore_MODULES += ${BASE_MODULES} hbicore_EXTENDED_MODULES += ${EXTENDED_MODULES} @@ -369,7 +368,7 @@ endif hbicore_test_LDFILE = kernel.ld hbirt_OBJECTS += ${RUNTIME_OBJECTS} -hbirt_OBJECTS += ${BASE_OBJECTS} +hbirt_OBJECTS += ${BASE_OBJECTS} tlsrt.o hbirt_MODULES += ${RUNTIME_MODULES} hbirt_DATA_MODULES += ${RUNTIME_DATA_MODULES} hbirt_DATA_MODULES += $(if $(CONFIG_HBRT_PRD),$(prd_rule_prf_targets)) diff --git a/src/runtime/rt_start.S b/src/runtime/rt_start.S index ba1a975d7..aaf4ee59e 100644 --- a/src/runtime/rt_start.S +++ b/src/runtime/rt_start.S @@ -5,7 +5,7 @@ # # OpenPOWER HostBoot Project # -# Contributors Listed Below - COPYRIGHT 2013,2017 +# Contributors Listed Below - COPYRIGHT 2013,2019 # [+] International Business Machines Corp. # [+] Joel Stanley # @@ -52,13 +52,46 @@ _init: cmpwi cr0, r8, 0 # Perform relocations (if any). beq 2f + + # TLS workaround + # Load ASCII 'T','L','S' + 0x00 into bits 32:63 of r6, which will be used + # to compare against bits 0-31 of each relocation entry. A match signifies + # that this and the next relocation entry are the TLS module and offset + # relocations respectively. Skip both relocations before continuing the + # processing. These first two directives create the reference pattern to + # compare against. Also skip a relocation entry if its value is 0. + rldicl r6,r6,0,63 # Clear r6 to zero + addis r6, 0, 0x544C # Load ASCII "TL" into bits 32:47 of r6 + ori r6, r6, 0x5300 # Load ASCII "S" + 0x00 into bits 48:63 of r6 + mtctr r8 1: ldu r8, 8(r10) # Get relocation destination add r8, r8, r4 ld r7, 0(r8) # Get relocation address + + + # TLS workaround (continued for next 8 instructions) + rldicl r5,r5,0,63 # Clear r5 to zero + cmp cr0, 0, r5, r7 # Compare the relocation address (r7) to zero (r5) + beq cr0, 3f # If the relocation address is zero, do + # not adjust it and instead jump to the loop + # decrement/branch instruction + + rldicl r5,r7,32,32 # Rotate bits 0-31 of the relocation address + # into 32-63 and clear bits 0-31, saving result + # to r5, to set up the next comparison + cmp cr0, 0, r6, r5 # Compare bits 32-63, which should both contain + # ASCII TLS+0x00 if this is a TLS module + bne cr0, 4f # If not a TLS module relocation, keep going; + ldu r8, 8(r10) # otherwise, skip the TLS module relocation + bdnz 3f # and decrement the loop counter to match. Jump + # to a 2nd skip/decrement pair to effectively skip + # the next TLS module relocation as well +4: add r7, r7, r4 std r7, 0(r8) # Update relocation address. +3: bdnz 1b # Decrement CTR and continue loop. 2: addi r10, r4, 0x2008 # Find pointer to main TOC. diff --git a/src/usr/module_init.C b/src/usr/module_init.C index 3e9a25e58..91df9a952 100644 --- a/src/usr/module_init.C +++ b/src/usr/module_init.C @@ -5,7 +5,7 @@ /* */ /* OpenPOWER HostBoot Project */ /* */ -/* Contributors Listed Below - COPYRIGHT 2011,2015 */ +/* Contributors Listed Below - COPYRIGHT 2011,2019 */ /* [+] International Business Machines Corp. */ /* */ /* */ @@ -22,20 +22,32 @@ /* permissions and limitations under the License. */ /* */ /* IBM_PROLOG_END_TAG */ + +#include + void call_dtors(void * i_dso_handle); -void __tls_register(void * tls_start, void * tls_end); + +/** + * @note: See documentation in src/lib/tls.C + */ +void __tls_register(void * tls_start, void * tls_end,const size_t i_module); + void __tls_unregister(void * tls_start, void * tls_end); // This identifies the module void* __dso_handle = (void*) &__dso_handle; +// TLS Module ID to be updated by custom linker during final binary creation. +// Set to max ID so that if it's not replaced, it will lead to obvious crashes. +size_t TLS_MODULE_ID = 0xFFFFFFFFFFFFFFFFULL; + extern "C" void _init(void*) { // Register thread-local storage. extern void* tls_start_address; extern void* tls_end_address; - __tls_register(&tls_start_address, &tls_end_address); + __tls_register(&tls_start_address, &tls_end_address, TLS_MODULE_ID); // Call default constructors for any static objects. extern void (*ctor_start_address)(); diff --git a/src/usr/testcore/rtloader/loader.H b/src/usr/testcore/rtloader/loader.H index 1c4423484..64db72dc4 100644 --- a/src/usr/testcore/rtloader/loader.H +++ b/src/usr/testcore/rtloader/loader.H @@ -228,7 +228,7 @@ class RuntimeLoaderTest : public CxxTest::TestSuite "std 2, 40(1); bctrl; ld 2, 40(1); " "mr %0, 3" : "=r" (result) : "r" (entry), "r" (param0), "r" (param1) : - "lr","ctr","r0","r3","r4","r5","r6","r7","r8","r9", + "lr","ctr","cr0","r0","r3","r4","r5","r6","r7","r8","r9", "r10","r11"); // TODO: Need to double check the ABI here. return result; -- cgit v1.2.1