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:
committed by
waddlesplash
parent
40205ec46a
commit
7981c1d1c7
@@ -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;
|
||||||
|
|||||||
@@ -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. */
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user