Index: boot/common/load_elf.c =================================================================== --- boot/common/load_elf.c +++ boot/common/load_elf.c @@ -175,7 +175,11 @@ * Check to see what sort of module we are. */ kfp = file_findfile(NULL, __elfN(kerneltype)); +#if defined(__powerpc__) && __ELF_WORD_SIZE == 64 + if (ehdr->e_type == ET_DYN && ehdr->e_entry == 0) { +#else if (ehdr->e_type == ET_DYN) { +#endif /* Looks like a kld module */ if (multiboot != 0) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: can't load module as multiboot\n"); @@ -195,7 +199,12 @@ /* Looks OK, got ahead */ ef.kernel = 0; +#if defined(__powerpc__) && __ELF_WORD_SIZE == 64 + } else if (ehdr->e_type == ET_EXEC || + (ehdr->e_type == ET_DYN && ehdr->e_entry != 0)) { +#else } else if (ehdr->e_type == ET_EXEC) { +#endif /* Looks like a kernel */ if (kfp != NULL) { printf("elf" __XSTRING(__ELF_WORD_SIZE) "_loadfile: kernel already loaded\n"); Index: conf/Makefile.powerpc =================================================================== --- conf/Makefile.powerpc +++ conf/Makefile.powerpc @@ -37,6 +37,11 @@ CFLAGS+= -msoft-float -Wa,-many +.if ${MACHINE_ARCH} == "powerpc64" +CFLAGS+= -fPIC +LDFLAGS+= -pie +.endif + .if !empty(DDB_ENABLED) CFLAGS+= -fno-omit-frame-pointer .endif Index: conf/kmod.mk =================================================================== --- conf/kmod.mk +++ conf/kmod.mk @@ -179,6 +179,10 @@ ${OBJCOPY} --only-keep-debug ${FULLPROG} ${.TARGET} .endif +.if ${MACHINE_ARCH} == "powerpc64" +_LDFLAGS+= -e 0 +.endif + .if ${__KLD_SHARED} == yes ${FULLPROG}: ${KMOD}.kld ${LD} -Bshareable ${_LDFLAGS} -o ${.TARGET} ${KMOD}.kld Index: powerpc/aim/locore64.S =================================================================== --- powerpc/aim/locore64.S +++ powerpc/aim/locore64.S @@ -121,14 +121,34 @@ .align 3 0: nop bl 1f - .llong __tocbase + 0x8000 + .llong __tocbase + 0x8000 - . 1: mflr %r2 - ld %r2,0(%r2) + ld %r1,0(%r2) + add %r2,%r1,%r2 /* Set up the stack pointer */ ld %r1,TOC_REF(tmpstk)(%r2) - addi %r1,%r1,TMPSTKSZ-48 + addi %r1,%r1,TMPSTKSZ-96 + /* Relocate kernel */ + std %r3,48(%r1) + std %r4,56(%r1) + std %r5,64(%r1) + std %r6,72(%r1) + bl 1f + .llong _DYNAMIC-. +1: mflr %r3 + ld %r4,0(%r3) + add %r3,%r4,%r3 + ld %r4,-0x8000(%r2) /* First TOC entry is TOC base */ + subf %r4,%r4,%r2 /* Subtract from real TOC base to get base */ + bl elf_reloc_self + nop + ld %r3,48(%r1) + ld %r4,56(%r1) + ld %r5,64(%r1) + ld %r6,72(%r1) + /* Switch to 64-bit mode */ mfmsr %r9 li %r8,1 @@ -121,14 +121,34 @@ .align 3 0: nop bl 1f - .llong __tocbase + 0x8000 + .llong __tocbase + 0x8000 - . 1: mflr %r2 - ld %r2,0(%r2) + ld %r1,0(%r2) + add %r2,%r1,%r2 /* Set up the stack pointer */ ld %r1,TOC_REF(tmpstk)(%r2) - addi %r1,%r1,TMPSTKSZ-48 + addi %r1,%r1,TMPSTKSZ-96 + /* Relocate kernel */ + std %r3,48(%r1) + std %r4,56(%r1) + std %r5,64(%r1) + std %r6,72(%r1) + bl 1f + .llong _DYNAMIC-. +1: mflr %r3 + ld %r4,0(%r3) + add %r3,%r4,%r3 + ld %r4,-0x8000(%r2) /* First TOC entry is TOC base */ + subf %r4,%r4,%r2 /* Subtract from real TOC base to get base */ + bl elf_reloc_self + nop + ld %r3,48(%r1) + ld %r4,56(%r1) + ld %r5,64(%r1) + ld %r6,72(%r1) + /* Switch to 64-bit mode */ mfmsr %r9 li %r8,1 Index: powerpc/aim/trap_subr64.S =================================================================== --- powerpc/aim/trap_subr64.S +++ powerpc/aim/trap_subr64.S @@ -39,6 +39,19 @@ * #include */ +#define ABSOLUTE_JUMP(dest, scratch_sprg) \ + b 9f; \ + .p2align 3; \ +9: nop; \ + bl 9f; \ + .llong dest; \ +9: __CONCAT(mtsprg, scratch_sprg) %r1; \ + mflr %r1; \ + ld %r1,0(%r1); \ + mtlr %r1; \ + __CONCAT(mfsprg, scratch_sprg) %r1; \ + blrl + /* * Save/restore segment registers */ @@ -302,8 +315,12 @@ insrdi %r9,%r8,1,0 mtmsrd %r9 isync - - ba cpu_reset + bl 1f + .llong cpu_reset +1: mflr %r9 + ld %r9,0(%r9) + mtlr %r9 + blr CNAME(rstsize) = . - CNAME(rstcode) cpu_reset: @@ -346,12 +363,18 @@ */ .globl CNAME(trapcode),CNAME(trapsize) + .p2align 3 CNAME(trapcode): mtsprg1 %r1 /* save SP */ mflr %r1 /* Save the old LR in r1 */ mtsprg2 %r1 /* And then in SPRG2 */ - li %r1, 0xA0 /* How to get the vector from LR */ - bla generictrap /* LR & SPRG3 is exception # */ + bl 1f /* Begin branching to generictrap */ + .llong generictrap +1: mflr %r1 + ld %r1,0(%r1) + mtlr %r1 + li %r1, 0x80 /* How to get the vector from LR */ + blrl /* Branch to generictrap */ CNAME(trapsize) = .-CNAME(trapcode) /* @@ -361,6 +384,7 @@ * the only time this can be called. */ .globl CNAME(slbtrap),CNAME(slbtrapsize) + .p2align 3 CNAME(slbtrap): mtsprg1 %r1 /* save SP */ GET_CPUINFO(%r1) @@ -369,7 +393,7 @@ std %r2,(PC_SLBSAVE+104)(%r1) mfsrr1 %r2 /* test kernel mode */ mtcr %r2 - bf 17,1f /* branch if PSL_PR is false */ + bf 17,2f /* branch if PSL_PR is false */ /* User mode */ ld %r2,(PC_SLBSAVE+104)(%r1) /* Restore CR */ mtcr %r2 @@ -376,10 +400,24 @@ ld %r2,(PC_SLBSAVE+16)(%r1) /* Restore R2 */ mflr %r1 /* Save the old LR in r1 */ mtsprg2 %r1 /* And then in SPRG2 */ + /* 52 bytes so far */ + bl 1f + .llong generictrap +1: mflr %r1 + ld %r1,0(%r1) + mtlr %r1 li %r1, 0x80 /* How to get the vector from LR */ - bla generictrap /* LR & SPRG3 is exception # */ -1: mflr %r2 /* Save the old LR in r2 */ - bla kern_slbtrap + blrl /* Branch to generictrap */ + /* 84 bytes */ +2: mflr %r2 /* Save the old LR in r2 */ + nop + bl 3f /* Begin dance to jump to kern_slbtrap*/ + .llong kern_slbtrap +3: mflr %r1 + ld %r1,0(%r1) + mtlr %r1 + GET_CPUINFO(%r1) + blrl /* 124 bytes -- 4 to spare */ CNAME(slbtrapsize) = .-CNAME(slbtrap) kern_slbtrap: @@ -518,6 +556,16 @@ mflr %r28 /* save LR */ mfcr %r29 /* save CR */ + /* Begin dance to branch to s_trap in a bit */ + b 1f + .p2align 3 +1: nop + bl 1f + .llong s_trap +1: mflr %r31 + ld %r31,0(%r31) + mtlr %r31 + /* Put our exception vector in SPRG3 */ li %r31, EXC_ALI mtsprg3 %r31 @@ -525,13 +573,12 @@ /* Test whether we already had PR set */ mfsrr1 %r31 mtcr %r31 - bla s_trap + blrl CNAME(alisize) = .-CNAME(alitrap) /* * Similar to the above for DSI - * Has to handle BAT spills - * and standard pagetable spills + * Has to handle standard pagetable spills */ .globl CNAME(dsitrap),CNAME(dsisize) CNAME(dsitrap): @@ -542,7 +589,6 @@ std %r29,(PC_DISISAVE+CPUSAVE_R29)(%r1) std %r30,(PC_DISISAVE+CPUSAVE_R30)(%r1) std %r31,(PC_DISISAVE+CPUSAVE_R31)(%r1) - mfsprg1 %r1 /* restore SP */ mfcr %r29 /* save CR */ mfxer %r30 /* save XER */ mtsprg2 %r30 /* in SPRG2 */ @@ -549,7 +595,12 @@ mfsrr1 %r31 /* test kernel mode */ mtcr %r31 mflr %r28 /* save LR (SP already saved) */ - bla disitrap + bl 1f /* Begin branching to disitrap */ + .llong disitrap +1: mflr %r1 + ld %r1,0(%r1) + mtlr %r1 + blrl /* Branch to generictrap */ CNAME(dsisize) = .-CNAME(dsitrap) /* @@ -624,7 +675,7 @@ bl restore_kernsrs /* enable kernel mapping */ mfsprg2 %r29 mr %r28,%r27 - ba s_trap + b s_trap /* * generictrap does some standard setup for trap handling to minimize @@ -806,7 +857,7 @@ mtsprg2 %r1 /* And then in SPRG2 */ li %r1, 0 /* How to get the vector from LR */ - bla generictrap /* and we look like a generic trap */ + ABSOLUTE_JUMP(generictrap, 3) /* and we look like a generic trap */ 1: GET_CPUINFO(%r1) std %r27,(PC_DBSAVE+CPUSAVE_R27)(%r1) /* free r27 */ @@ -816,6 +867,6 @@ std %r30,(PC_DBSAVE+CPUSAVE_R30)(%r1) /* free r30 */ std %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */ mflr %r28 /* save LR */ - bla dbtrap + ABSOLUTE_JUMP(dbtrap, 2) CNAME(dbsize) = .-CNAME(dblow) #endif /* KDB */ Index: powerpc/powerpc/elf64_machdep.c =================================================================== --- powerpc/powerpc/elf64_machdep.c +++ powerpc/powerpc/elf64_machdep.c @@ -119,6 +119,8 @@ (sysinit_cfunc_t) elf64_insert_brand_entry, &freebsd_brand_oinfo); +void elf_reloc_self(Elf_Dyn *dynp, Elf_Addr relocbase); + void elf64_dump_thread(struct thread *td, void *dst, size_t *off) { @@ -198,6 +200,37 @@ return(0); } +void +elf_reloc_self(Elf_Dyn *dynp, Elf_Addr relocbase) +{ + Elf_Rela *rela = 0, *relalim; + Elf_Addr relasz = 0; + Elf_Addr *where; + + /* + * Extract the rela/relasz values from the dynamic section + */ + for (; dynp->d_tag != DT_NULL; dynp++) { + switch (dynp->d_tag) { + case DT_RELA: + rela = (Elf_Rela *)(relocbase+dynp->d_un.d_ptr); + break; + case DT_RELASZ: + relasz = dynp->d_un.d_val; + break; + } + } + + /* + * Relocate these values + */ + relalim = (Elf_Rela *)((caddr_t)rela + relasz); + for (; rela < relalim; rela++) { + where = (Elf_Addr *)(relocbase + rela->r_offset); + *where = (Elf_Addr)(relocbase + rela->r_addend); + } +} + int elf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, elf_lookup_fn lookup)