arm64: Add runtime_loader support + TLS

Change-Id: Ic462c6b08e6949039457e6141c83468e6a6a6964
Reviewed-on: https://review.haiku-os.org/c/haiku/+/10604
Tested-by: Commit checker robot <[email protected]>
Reviewed-by: waddlesplash <[email protected]>
This commit is contained in:
Sam Roberts
2026-03-30 22:16:51 +00:00
committed by waddlesplash
parent 40205ec46a
commit 7981c1d1c7
7 changed files with 95 additions and 18 deletions
@@ -136,6 +136,7 @@ struct iframe {
uint64 fp; uint64 fp;
uint64 lr; uint64 lr;
uint64 sp; uint64 sp;
uint64 tpidr;
// exception info // exception info
uint64 esr; uint64 esr;
+2 -2
View File
@@ -20,8 +20,8 @@
#define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ #define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */
#define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */ #define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */
#define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */ #define R_AARCH64_RELATIVE 1027 /* Add load address of shared object */
#define R_AARCH64_TLS_DTPREL64 1028 /* Module-relative offset, 64 bit. */ #define R_AARCH64_TLS_DTPMOD64 1028 /* Module number, 64 bit. */
#define R_AARCH64_TLS_DTPMOD64 1029 /* Module number, 64 bit. */ #define R_AARCH64_TLS_DTPREL64 1029 /* Module-relative offset, 64 bit. */
#define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */ #define R_AARCH64_TLS_TPREL64 1030 /* TP-relative offset, 64 bit. */
#define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */ #define R_AARCH64_TLSDESC 1031 /* Identify the TLS descriptor */
#define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */ #define R_AARCH64_IRELATIVE 1032 /* STT_GNU_IFUNC relocation. */
+8 -4
View File
@@ -58,12 +58,14 @@ sub sp, sp, \xt
mrs x2, SPSR_EL1 mrs x2, SPSR_EL1
mrs x3, ESR_EL1 mrs x3, ESR_EL1
mrs x4, FAR_EL1 mrs x4, FAR_EL1
mrs x5, TPIDR_EL0
str x0, [x19, #(IFRAME_sp)] str x0, [x19, #(IFRAME_sp)]
str x1, [x19, #(IFRAME_elr)] str x1, [x19, #(IFRAME_elr)]
str x2, [x19, #(IFRAME_spsr)] str x2, [x19, #(IFRAME_spsr)]
str x3, [x19, #(IFRAME_esr)] str x3, [x19, #(IFRAME_esr)]
str x4, [x19, #(IFRAME_far)] str x4, [x19, #(IFRAME_far)]
str x5, [x19, #(IFRAME_tpidr)]
.endm .endm
.macro EXCEPTION_RETURN el .macro EXCEPTION_RETURN el
@@ -108,6 +110,9 @@ sub sp, sp, \xt
mov sp, x18 mov sp, x18
.endif .endif
ldr x0, [x19, #(IFRAME_tpidr)]
msr TPIDR_EL0, x0
// finally restore remaining registers // finally restore remaining registers
ldp x0, x1, [x19, #(IFRAME_x + 0 * 8)] ldp x0, x1, [x19, #(IFRAME_x + 0 * 8)]
ldp x18, x19, [x19, #(IFRAME_x + 18 * 8)] ldp x18, x19, [x19, #(IFRAME_x + 18 * 8)]
@@ -192,6 +197,7 @@ FUNCTION(_eret_with_iframe):
EXCEPTION_RETURN 0 EXCEPTION_RETURN 0
FUNCTION_END(_eret_with_iframe) FUNCTION_END(_eret_with_iframe)
FUNCTION(_fp_save): FUNCTION(_fp_save):
stp q0, q1, [x0], #32 stp q0, q1, [x0], #32
stp q2, q3, [x0], #32 stp q2, q3, [x0], #32
@@ -264,8 +270,7 @@ FUNCTION(_arch_context_swap):
stp x29, x30, [x0], #16 stp x29, x30, [x0], #16
mov x2, sp mov x2, sp
mrs x3, TPIDR_EL0 str x2, [x0], #8
stp x2, x3, [x0], #16
stp d8, d9, [x0], #16 stp d8, d9, [x0], #16
stp d10, d11, [x0], #16 stp d10, d11, [x0], #16
@@ -280,9 +285,8 @@ FUNCTION(_arch_context_swap):
ldp x27, x28, [x1], #16 ldp x27, x28, [x1], #16
ldp x29, x30, [x1], #16 ldp x29, x30, [x1], #16
ldp x2, x3, [x1], #16 ldr x2, [x1], #8
mov sp, x2 mov sp, x2
msr TPIDR_EL0, x3
ldp d8, d9, [x1], #16 ldp d8, d9, [x1], #16
ldp d10, d11, [x1], #16 ldp d10, d11, [x1], #16
+1 -10
View File
@@ -84,13 +84,6 @@ arch_thread_init_tls(Thread *thread)
return B_OK; return B_OK;
} }
static void
arm64_set_tls_context(Thread *thread)
{
WRITE_SPECIALREG(tpidrro_el0, thread->user_local_storage);
}
extern "C" void _arch_context_swap(arch_thread *from, arch_thread *to); extern "C" void _arch_context_swap(arch_thread *from, arch_thread *to);
@@ -98,7 +91,6 @@ void
arch_thread_context_switch(Thread *from, Thread *to) arch_thread_context_switch(Thread *from, Thread *to)
{ {
arch_vm_aspace_swap(from->team->address_space, to->team->address_space); arch_vm_aspace_swap(from->team->address_space, to->team->address_space);
arm64_set_tls_context(to);
_arch_context_swap(&from->arch_info, &to->arch_info); _arch_context_swap(&from->arch_info, &to->arch_info);
} }
@@ -116,8 +108,6 @@ status_t
arch_thread_enter_userspace(Thread *thread, addr_t entry, arch_thread_enter_userspace(Thread *thread, addr_t entry,
void *arg1, void *arg2) void *arg1, void *arg2)
{ {
arm64_set_tls_context(thread);
addr_t threadExitAddr; addr_t threadExitAddr;
{ {
addr_t commpageAdr = (addr_t)thread->team->commpage_address; addr_t commpageAdr = (addr_t)thread->team->commpage_address;
@@ -137,6 +127,7 @@ arch_thread_enter_userspace(Thread *thread, addr_t entry,
frame.x[1] = (uint64_t)arg2; frame.x[1] = (uint64_t)arg2;
frame.lr = threadExitAddr; frame.lr = threadExitAddr;
frame.sp = thread->user_stack_base + thread->user_stack_size; frame.sp = thread->user_stack_base + thread->user_stack_size;
frame.tpidr = thread->user_local_storage;
_eret_with_iframe(&frame); _eret_with_iframe(&frame);
return B_ERROR; return B_ERROR;
@@ -40,6 +40,7 @@ dummy()
DEFINE_OFFSET_MACRO(IFRAME, iframe, fp); DEFINE_OFFSET_MACRO(IFRAME, iframe, fp);
DEFINE_OFFSET_MACRO(IFRAME, iframe, esr); DEFINE_OFFSET_MACRO(IFRAME, iframe, esr);
DEFINE_OFFSET_MACRO(IFRAME, iframe, far); DEFINE_OFFSET_MACRO(IFRAME, iframe, far);
DEFINE_OFFSET_MACRO(IFRAME, iframe, tpidr);
DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler); DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler);
DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer); DEFINE_OFFSET_MACRO(CPU_ENT, cpu_ent, fault_handler_stack_pointer);
+1 -1
View File
@@ -24,7 +24,7 @@ static inline void**
get_tls() get_tls()
{ {
void **tls; void **tls;
asm volatile("MRS %0, tpidrro_el0" : "=r" (tls)); asm volatile("MRS %0, tpidr_el0" : "=r" (tls));
return tls; return tls;
} }
@@ -7,6 +7,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include "arch_elf.h"
#include "runtime_loader_private.h" #include "runtime_loader_private.h"
#include <runtime_loader.h> #include <runtime_loader.h>
@@ -20,10 +21,89 @@
#endif #endif
static status_t
relocate_rela(image_t* rootImage, image_t* image, Elf64_Rela* rel,
size_t relLength, SymbolLookupCache* cache)
{
for (size_t i = 0; i < relLength / sizeof(Elf64_Rela); i++) {
int type = ELF64_R_TYPE(rel[i].r_info);
int symIndex = ELF64_R_SYM(rel[i].r_info);
Elf64_Addr symAddr = 0;
image_t* symbolImage = NULL;
// Resolve the symbol, if any.
if (symIndex != 0) {
Elf64_Sym* sym = SYMBOL(image, symIndex);
status_t status = resolve_symbol(rootImage, image, sym, cache,
&symAddr, &symbolImage);
if (status != B_OK) {
TRACE(("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
SYMNAME(image, sym), status));
printf("resolve symbol \"%s\" returned: %" B_PRId32 "\n",
SYMNAME(image, sym), status);
return status;
}
}
// Address of the relocation.
Elf64_Addr relocAddr = image->regions[0].delta + rel[i].r_offset;
// Calculate the relocation value.
Elf64_Addr relocValue;
switch (type) {
case R_AARCH64_NONE:
continue;
case R_AARCH64_ABS64:
case R_AARCH64_GLOB_DAT:
case R_AARCH64_JUMP_SLOT:
relocValue = symAddr + rel[i].r_addend;
break;
case R_AARCH64_RELATIVE:
relocValue = image->regions[0].delta + rel[i].r_addend;
break;
case R_AARCH64_TLS_DTPMOD64:
relocValue = symbolImage == NULL
? image->dso_tls_id : symbolImage->dso_tls_id;
break;
case R_AARCH64_TLS_DTPREL64:
relocValue = symAddr;
break;
default:
TRACE(("unhandled relocation type %d\n", type));
return B_BAD_DATA;
}
*(Elf64_Addr *)relocAddr = relocValue;
}
return B_OK;
}
status_t status_t
arch_relocate_image(image_t *rootImage, image_t *image, arch_relocate_image(image_t *rootImage, image_t *image,
SymbolLookupCache* cache) SymbolLookupCache* cache)
{ {
debugger("arch_relocate_image: Not Yet Implemented!"); status_t status;
// No REL on arm64.
// Perform RELA relocations.
if (image->rela) {
status = relocate_rela(rootImage, image, image->rela, image->rela_len,
cache);
if (status != B_OK)
return status;
}
// PLT relocations (they are RELA on arm64).
if (image->pltrel) {
status = relocate_rela(rootImage, image, (Elf64_Rela*)image->pltrel,
image->pltrel_len, cache);
if (status != B_OK)
return status;
}
return B_OK; return B_OK;
} }