Newer
Older
minerva / Userland / Libraries / LibELF / Arch / riscv64 / tls.h
@minerva minerva on 13 Jul 2 KB Initial commit
/*
 * Copyright (c) 2024, Sönke Holz <sholz8530@gmail.com>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/BitCast.h>
#include <AK/Types.h>

namespace ELF {

struct ThreadControlBlock {
    // NOTE: "ELF Handling For Thread-Local Storage" says that when using variant I of the data structures (which RISC-V does),
    //       the TCB has to have a pointer to the dtv at offset 0.
    //       However, that document also says that the thread pointer has to point to the TCB.
    //       It's probably still a good idea to put the dtv pointer at offset 0.
    // This member is unused, as we currently only support static TLS blocks.
    void* dynamic_thread_vector;
};

static constexpr size_t TLS_VARIANT = 1;
static constexpr size_t TLS_DTV_OFFSET = 0x800;
static constexpr size_t TLS_TP_STATIC_TLS_BLOCK_OFFSET = 0;

// RISC-V ELF TLS Layout
// The padding is needed so tp is correctly aligned.
//
// [..padding..][TCB][static TLS.....]
//                    ^tp

inline size_t calculate_static_tls_region_size(size_t tls_template_size, size_t tls_alignment)
{
    return align_up_to(sizeof(ThreadControlBlock), tls_alignment) + tls_template_size;
}

inline FlatPtr calculate_tp_value_from_static_tls_region_address(FlatPtr static_tls_region_address, size_t tls_template_size, size_t tls_alignment)
{
    (void)tls_template_size;
    return static_tls_region_address + align_up_to(sizeof(ThreadControlBlock), tls_alignment);
}

inline ThreadControlBlock* get_tcb_pointer_from_thread_pointer(FlatPtr thread_pointer)
{
    return bit_cast<ThreadControlBlock*>(thread_pointer - sizeof(ThreadControlBlock));
}

inline void* get_pointer_to_first_static_tls_block_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment)
{
    (void)tls_template_size;
    (void)tls_alignment;
    return bit_cast<void*>(thread_pointer);
}

inline void* get_pointer_to_static_tls_region_from_thread_pointer(FlatPtr thread_pointer, size_t tls_template_size, size_t tls_alignment)
{
    (void)tls_template_size;
    return bit_cast<void*>(thread_pointer - align_up_to(sizeof(ThreadControlBlock), tls_alignment));
}

}