diff options
author | Itamar <itamar8910@gmail.com> | 2020-10-10 12:17:07 +0300 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2020-12-14 23:05:53 +0100 |
commit | 9ca1a0731f3074265bbbc0402b4021ba2685b994 (patch) | |
tree | 417eedd131d40650983937168997c71ecd495f58 /Kernel/Syscalls/mmap.cpp | |
parent | 5b87904ab502812639dfcde39e766427e35773a2 (diff) | |
download | serenity-9ca1a0731f3074265bbbc0402b4021ba2685b994.zip |
Kernel: Support TLS allocation from userspace
This adds an allocate_tls syscall through which a userspace process
can request the allocation of a TLS region with a given size.
This will be used by the dynamic loader to allocate TLS for the main
executable & its libraries.
Diffstat (limited to 'Kernel/Syscalls/mmap.cpp')
-rw-r--r-- | Kernel/Syscalls/mmap.cpp | 43 |
1 files changed, 43 insertions, 0 deletions
diff --git a/Kernel/Syscalls/mmap.cpp b/Kernel/Syscalls/mmap.cpp index 74dbe31edf..36aa2a1b67 100644 --- a/Kernel/Syscalls/mmap.cpp +++ b/Kernel/Syscalls/mmap.cpp @@ -24,6 +24,7 @@ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +#include <AK/WeakPtr.h> #include <Kernel/FileSystem/FileDescription.h> #include <Kernel/Process.h> #include <Kernel/VM/PageDirectory.h> @@ -417,4 +418,46 @@ int Process::sys$munmap(void* addr, size_t size) return -EINVAL; } +void* Process::sys$allocate_tls(size_t size) +{ + REQUIRE_PROMISE(stdio); + + dbg() << "allocate TLS: " << size; + + if (!size) + return (void*)-EINVAL; + + if (!m_master_tls_region.is_null()) + return (void*)-EEXIST; + + if (thread_count() != 1) + return (void*)-EFAULT; + + Thread* main_thread = nullptr; + for_each_thread([&main_thread](auto& thread) { + main_thread = &thread; + return IterationDecision::Break; + }); + ASSERT(main_thread); + + auto tls_region = allocate_region({}, size, String(), PROT_READ | PROT_WRITE); + if (!tls_region) + return (void*)-EFAULT; + + m_master_tls_region = tls_region->make_weak_ptr(); + dbg() << "master_tls_region: " << m_master_tls_region->vaddr(); + m_master_tls_size = size; + m_master_tls_alignment = PAGE_SIZE; + + auto tsr_result = main_thread->make_thread_specific_region({}); + if (tsr_result.is_error()) + return (void*)-EFAULT; + + auto& tls_descriptor = Processor::current().get_gdt_entry(GDT_SELECTOR_TLS); + tls_descriptor.set_base(main_thread->thread_specific_data().as_ptr()); + tls_descriptor.set_limit(main_thread->thread_specific_region_size()); + + return m_master_tls_region.unsafe_ptr()->vaddr().as_ptr(); +} + } |