summaryrefslogtreecommitdiff
path: root/Kernel/Syscalls/mmap.cpp
diff options
context:
space:
mode:
authorItamar <itamar8910@gmail.com>2020-10-10 12:17:07 +0300
committerAndreas Kling <kling@serenityos.org>2020-12-14 23:05:53 +0100
commit9ca1a0731f3074265bbbc0402b4021ba2685b994 (patch)
tree417eedd131d40650983937168997c71ecd495f58 /Kernel/Syscalls/mmap.cpp
parent5b87904ab502812639dfcde39e766427e35773a2 (diff)
downloadserenity-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.cpp43
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();
+}
+
}