diff --git a/sys/arm64/arm64/elf_machdep.c b/sys/arm64/arm64/elf_machdep.c index 08a297b..1abc362 100644 --- a/sys/arm64/arm64/elf_machdep.c +++ b/sys/arm64/arm64/elf_machdep.c @@ -132,12 +132,127 @@ elf64_dump_thread(struct thread *td __unused, void *dst __unused, } +#define Page(x) ((x) & ~0xfffULL) +#define FMASK 0xffffffffffffffffULL + +static void +set_bitslice(uint64_t *place, uint64_t val, u_int val_start, u_int val_end, + u_int place_start) +{ + uint64_t fmask; + u_int len; + + KASSERT(val_end < 64, ("val_start %d", val_end)); + KASSERT(val_start < val_end, + ("val_start %d >= val_end %d", val_start, val_end)); + len = val_end - val_start + 1; + KASSERT(len + place_start < 64, + ("place_start %d len %d", place_start, len)); + fmask = (1ULL << len) - 1; + val >>= val_start; + val &= fmask; + *place &= ~(fmask << place_start); + *place |= val << place_start; +} + +static int +elf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, + int type, int local, elf_lookup_fn lookup) +{ + Elf64_Addr *where, val; + Elf_Addr addr, addend; + Elf_Size rtype, symidx; + const Elf_Rel *rel; + const Elf_Rela *rela; + u_int x; + int error; + + switch (type) { + case ELF_RELOC_REL: + rel = (const Elf_Rel *)data; + where = (Elf_Addr *) (relocbase + rel->r_offset); + rtype = ELF_R_TYPE(rel->r_info); + symidx = ELF_R_SYM(rel->r_info); + addend = *where; + break; + case ELF_RELOC_RELA: + rela = (const Elf_Rela *)data; + where = (Elf_Addr *) (relocbase + rela->r_offset); + addend = rela->r_addend; + rtype = ELF_R_TYPE(rela->r_info); + symidx = ELF_R_SYM(rela->r_info); + break; + default: + panic("unknown reloc type %d\n", type); + } + + x = 0; + switch (rtype) { + case R_AARCH64_LDST64_ABS_LO12_NC: + x++; + case R_AARCH64_LDST32_ABS_LO12_NC: + x++; + case R_AARCH64_LDST16_ABS_LO12_NC: + x++; + } + switch (rtype) { + case R_AARCH64_NONE: + break; + case R_AARCH64_ABS64: /* S + A */ + error = lookup(lf, symidx, 1, &addr); + val = addr + addend; + if (error != 0) + return (-1); + *where = val; + break; + case R_AARCH64_JUMP26: /* S + A - P */ + case R_AARCH64_CALL26: + error = lookup(lf, symidx, 1, &addr); + if (error != 0) + return (-1); + val = addr + addend - (Elf_Addr)where; + set_bitslice(where, val, 2, 27, 0); + break; + case R_AARCH64_LDST8_ABS_LO12_NC: /* S + A */ + case R_AARCH64_LDST16_ABS_LO12_NC: + case R_AARCH64_LDST32_ABS_LO12_NC: + case R_AARCH64_LDST64_ABS_LO12_NC: + error = lookup(lf, symidx, 1, &addr); + if (error != 0) + return (-1); + val = addr + addend; + set_bitslice(where, val, x, 11, 10 + x); + break; + case R_AARCH64_ADR_PREL_PG_HI21: /* Page(S + A) - Page(P) */ + case R_AARCH64_ADR_PREL_PG_HI21_NC: + error = lookup(lf, symidx, 1, &addr); + if (error != 0) + return (-1); + val = Page(addr + addend) - Page((Elf_Addr)where); + set_bitslice(where, val, 14, 30, 5); + set_bitslice(where, val, 12, 13, 29); + break; + case R_AARCH64_ADD_ABS_LO12_NC: /* S + A */ + error = lookup(lf, symidx, 1, &addr); + if (error != 0) + return (-1); + val = addr + addend; + set_bitslice(where, val, 0, 11, 10); + break; + default: + printf("kldload: unexpected relocation type %ld\n", rtype); + return (-1); + } + + return (0); +} + int elf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup __unused) { - panic("ARM64TODO: elf_reloc_local"); + return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); } /* Process one elf relocation with addend. */ @@ -146,7 +261,7 @@ elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup) { - panic("ARM64TODO: elf_reloc"); + return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); } int diff --git a/sys/arm64/arm64/trap.c b/sys/arm64/arm64/trap.c index e54c20e..058490c 100644 --- a/sys/arm64/arm64/trap.c +++ b/sys/arm64/arm64/trap.c @@ -275,7 +275,7 @@ do_el1h_sync(struct trapframe *frame) */ KASSERT((esr & ESR_ELx_IL) == ESR_ELx_IL || (exception == EXCP_DATA_ABORT && ((esr & ISS_DATA_ISV) == 0)), - ("Invalid instruction length in exception")); + ("Invalid instruction length in exception, esr %lx", esr)); CTR4(KTR_TRAP, "do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", diff --git a/sys/arm64/conf/GENERIC b/sys/arm64/conf/GENERIC index 26ca51d..1486f07 100644 --- a/sys/arm64/conf/GENERIC +++ b/sys/arm64/conf/GENERIC @@ -22,7 +22,6 @@ cpu ARM64 ident GENERIC makeoptions DEBUG=-g # Build kernel with gdb(1) debug symbols -makeoptions NO_MODULES=1 # We don't yet support modules on arm64 options SCHED_ULE # ULE scheduler options PREEMPTION # Enable kernel thread preemption diff --git a/sys/conf/files.arm64 b/sys/conf/files.arm64 index 399a35e..6e0faf9 100644 --- a/sys/conf/files.arm64 +++ b/sys/conf/files.arm64 @@ -69,6 +69,7 @@ dev/uart/uart_cpu_fdt.c optional uart fdt dev/uart/uart_dev_pl011.c optional uart pl011 dev/usb/controller/dwc_otg_hisi.c optional dwcotg soc_hisi_hi6220 kern/kern_clocksource.c standard +kern/link_elf_obj.c standard kern/subr_dummy_vdso_tc.c standard libkern/bcmp.c standard libkern/ffs.c standard diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index 0703cc8..55b4fd7 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -212,7 +212,7 @@ SRCS= assym.s vnode_if.h ${BEFORE_DEPEND} ${CFILES} \ mv .newdep .depend _ILINKS= machine -.if ${MACHINE} != ${MACHINE_CPUARCH} +.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" _ILINKS+= ${MACHINE_CPUARCH} .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 47bc593..87c96e2 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -71,8 +71,10 @@ OBJCOPY?= objcopy .SUFFIXES: .out .o .c .cc .cxx .C .y .l .s .S .m -# amd64 and mips use direct linking for kmod, all others use shared binaries -.if ${MACHINE_CPUARCH} != amd64 && ${MACHINE_CPUARCH} != mips +# aarch64, amd64 and mips use direct linking for kmod, all others +# use shared binaries +.if ${MACHINE_CPUARCH} != amd64 && ${MACHINE_CPUARCH} != mips && \ + ${MACHINE_CPUARCH} != aarch64 __KLD_SHARED=yes .else __KLD_SHARED=no @@ -220,7 +222,7 @@ ${FULLPROG}: ${OBJS} .endif _ILINKS=machine -.if ${MACHINE} != ${MACHINE_CPUARCH} +.if ${MACHINE} != ${MACHINE_CPUARCH} && ${MACHINE} != "arm64" _ILINKS+=${MACHINE_CPUARCH} .endif .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" diff --git a/sys/dev/sym/sym_hipd.c b/sys/dev/sym/sym_hipd.c index f2485c0..491aa54 100644 --- a/sys/dev/sym/sym_hipd.c +++ b/sys/dev/sym/sym_hipd.c @@ -136,6 +136,8 @@ typedef u_int32_t u32; #define MEMORY_BARRIER() __asm__ volatile("membar #Sync" : : : "memory") #elif defined __arm__ #define MEMORY_BARRIER() dmb() +#elif defined __aarch64__ +#define MEMORY_BARRIER() dmb(sy) #else #error "Not supported platform" #endif diff --git a/sys/modules/Makefile b/sys/modules/Makefile index f5f9b4c..90ce29b 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -480,7 +480,7 @@ _cxgbe= cxgbe .endif .if ${MACHINE_CPUARCH} != "arm" && ${MACHINE_CPUARCH} != "mips" && \ - ${MACHINE_CPUARCH} != "powerpc" + ${MACHINE_CPUARCH} != "powerpc" && ${MACHINE_CPUARCH} != "aarch64" _syscons= syscons _vpo= vpo .endif diff --git a/sys/sys/elf_common.h b/sys/sys/elf_common.h index 67f37d8..f941d02 100644 --- a/sys/sys/elf_common.h +++ b/sys/sys/elf_common.h @@ -876,6 +876,15 @@ typedef struct { #define R_AARCH64_PREL64 260 /* PC relative */ #define R_AARCH64_PREL32 261 /* PC relative, 32-bit overflow check */ #define R_AARCH64_PREL16 262 /* PC relative, 16-bit overflow check */ +#define R_AARCH64_ADR_PREL_PG_HI21 275 +#define R_AARCH64_ADR_PREL_PG_HI21_NC 276 +#define R_AARCH64_ADD_ABS_LO12_NC 277 +#define R_AARCH64_JUMP26 282 +#define R_AARCH64_CALL26 283 +#define R_AARCH64_LDST8_ABS_LO12_NC 278 +#define R_AARCH64_LDST16_ABS_LO12_NC 284 +#define R_AARCH64_LDST32_ABS_LO12_NC 285 +#define R_AARCH64_LDST64_ABS_LO12_NC 286 #define R_AARCH64_COPY 1024 /* Copy data from shared object */ #define R_AARCH64_GLOB_DAT 1025 /* Set GOT entry to data address */ #define R_AARCH64_JUMP_SLOT 1026 /* Set GOT entry to code address */