139072Sdfr/*- 239072Sdfr * Copyright 1996-1998 John D. Polstra. 339072Sdfr * All rights reserved. 439072Sdfr * 539072Sdfr * Redistribution and use in source and binary forms, with or without 639072Sdfr * modification, are permitted provided that the following conditions 739072Sdfr * are met: 839072Sdfr * 1. Redistributions of source code must retain the above copyright 939072Sdfr * notice, this list of conditions and the following disclaimer. 1039072Sdfr * 2. Redistributions in binary form must reproduce the above copyright 1139072Sdfr * notice, this list of conditions and the following disclaimer in the 1239072Sdfr * documentation and/or other materials provided with the distribution. 1339072Sdfr * 1439072Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 1539072Sdfr * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 1639072Sdfr * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 1739072Sdfr * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 1839072Sdfr * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 1939072Sdfr * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 2039072Sdfr * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 2139072Sdfr * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 2239072Sdfr * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 2339072Sdfr * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 2439072Sdfr * 2550477Speter * $FreeBSD$ 2639072Sdfr */ 2739072Sdfr 2839072Sdfr#include <sys/param.h> 2939072Sdfr#include <sys/kernel.h> 3039072Sdfr#include <sys/systm.h> 31102808Sjake#include <sys/exec.h> 32102808Sjake#include <sys/imgact.h> 3339072Sdfr#include <sys/malloc.h> 3439072Sdfr#include <sys/proc.h> 3539072Sdfr#include <sys/namei.h> 3639072Sdfr#include <sys/fcntl.h> 37100384Speter#include <sys/sysent.h> 38100384Speter#include <sys/imgact_elf.h> 39100384Speter#include <sys/syscall.h> 40100384Speter#include <sys/signalvar.h> 4139072Sdfr#include <sys/vnode.h> 4239072Sdfr#include <sys/linker.h> 43102808Sjake 44102808Sjake#include <vm/vm.h> 45102808Sjake#include <vm/vm_param.h> 46102808Sjake 47132282Sgrehan#include <machine/cpu.h> 4839072Sdfr#include <machine/elf.h> 49100384Speter#include <machine/md_var.h> 5039072Sdfr 51209975Snwhitehornstruct sysentvec elf64_freebsd_sysvec = { 52183322Skib .sv_size = SYS_MAXSYSCALL, 53183322Skib .sv_table = sysent, 54183322Skib .sv_mask = 0, 55183322Skib .sv_sigsize = 0, 56183322Skib .sv_sigtbl = NULL, 57183322Skib .sv_errsize = 0, 58183322Skib .sv_errtbl = NULL, 59183322Skib .sv_transtrap = NULL, 60183322Skib .sv_fixup = __elfN(freebsd_fixup), 61183322Skib .sv_sendsig = sendsig, 62209975Snwhitehorn .sv_sigcode = sigcode64, 63209975Snwhitehorn .sv_szsigcode = &szsigcode64, 64183322Skib .sv_prepsyscall = NULL, 65209975Snwhitehorn .sv_name = "FreeBSD ELF64", 66183322Skib .sv_coredump = __elfN(coredump), 67183322Skib .sv_imgact_try = NULL, 68183322Skib .sv_minsigstksz = MINSIGSTKSZ, 69183322Skib .sv_pagesize = PAGE_SIZE, 70183322Skib .sv_minuser = VM_MIN_ADDRESS, 71183322Skib .sv_maxuser = VM_MAXUSER_ADDRESS, 72183322Skib .sv_usrstack = USRSTACK, 73183322Skib .sv_psstrings = PS_STRINGS, 74183322Skib .sv_stackprot = VM_PROT_ALL, 75183322Skib .sv_copyout_strings = exec_copyout_strings, 76183322Skib .sv_setregs = exec_setregs, 77183322Skib .sv_fixlimit = NULL, 78185169Skib .sv_maxssiz = NULL, 79217400Skib .sv_flags = SV_ABI_FREEBSD | SV_LP64 | SV_SHP, 80208453Skib .sv_set_syscall_retval = cpu_set_syscall_retval, 81208453Skib .sv_fetch_syscall_args = cpu_fetch_syscall_args, 82208453Skib .sv_syscallnames = syscallnames, 83217400Skib .sv_shared_page_base = SHAREDPAGE, 84217400Skib .sv_shared_page_len = PAGE_SIZE, 85219405Sdchagin .sv_schedtail = NULL, 86293490Sdchagin .sv_thread_detach = NULL, 87294136Sdchagin .sv_trap = NULL, 88100384Speter}; 89217400SkibINIT_SYSENTVEC(elf64_sysvec, &elf64_freebsd_sysvec); 90100384Speter 91209975Snwhitehornstatic Elf64_Brandinfo freebsd_brand_info = { 92183322Skib .brand = ELFOSABI_FREEBSD, 93209975Snwhitehorn .machine = EM_PPC64, 94183322Skib .compat_3_brand = "FreeBSD", 95183322Skib .emul_path = NULL, 96183322Skib .interp_path = "/libexec/ld-elf.so.1", 97209975Snwhitehorn .sysvec = &elf64_freebsd_sysvec, 98183322Skib .interp_newpath = NULL, 99209975Snwhitehorn .brand_note = &elf64_freebsd_brandnote, 100190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 101183322Skib}; 102100384Speter 103209975SnwhitehornSYSINIT(elf64, SI_SUB_EXEC, SI_ORDER_ANY, 104209975Snwhitehorn (sysinit_cfunc_t) elf64_insert_brand_entry, 105183322Skib &freebsd_brand_info); 106100384Speter 107209975Snwhitehornstatic Elf64_Brandinfo freebsd_brand_oinfo = { 108183322Skib .brand = ELFOSABI_FREEBSD, 109209975Snwhitehorn .machine = EM_PPC64, 110183322Skib .compat_3_brand = "FreeBSD", 111183322Skib .emul_path = NULL, 112183322Skib .interp_path = "/usr/libexec/ld-elf.so.1", 113209975Snwhitehorn .sysvec = &elf64_freebsd_sysvec, 114183322Skib .interp_newpath = NULL, 115209975Snwhitehorn .brand_note = &elf64_freebsd_brandnote, 116190708Sdchagin .flags = BI_CAN_EXEC_DYN | BI_BRAND_NOTE 117183322Skib}; 118123742Speter 119209975SnwhitehornSYSINIT(oelf64, SI_SUB_EXEC, SI_ORDER_ANY, 120209975Snwhitehorn (sysinit_cfunc_t) elf64_insert_brand_entry, 121123742Speter &freebsd_brand_oinfo); 122123742Speter 123133464Smarcelvoid 124209975Snwhitehornelf64_dump_thread(struct thread *td __unused, void *dst __unused, 125133464Smarcel size_t *off __unused) 126133464Smarcel{ 127133464Smarcel} 128133464Smarcel 129133464Smarcel 13039072Sdfr/* Process one elf relocation with addend. */ 131109605Sjakestatic int 132129282Speterelf_reloc_internal(linker_file_t lf, Elf_Addr relocbase, const void *data, 133129282Speter int type, int local, elf_lookup_fn lookup) 13439072Sdfr{ 13540435Speter Elf_Addr *where; 13645958Sdt Elf_Addr addr; 13740435Speter Elf_Addr addend; 13895410Smarcel Elf_Word rtype, symidx; 13940435Speter const Elf_Rela *rela; 140288287Skib int error; 14139072Sdfr 14240435Speter switch (type) { 14340435Speter case ELF_RELOC_REL: 144132282Sgrehan panic("PPC only supports RELA relocations"); 14540435Speter break; 14640435Speter case ELF_RELOC_RELA: 14745958Sdt rela = (const Elf_Rela *)data; 14840435Speter where = (Elf_Addr *) (relocbase + rela->r_offset); 14940435Speter addend = rela->r_addend; 15040435Speter rtype = ELF_R_TYPE(rela->r_info); 15195410Smarcel symidx = ELF_R_SYM(rela->r_info); 15240435Speter break; 15340435Speter default: 15440435Speter panic("elf_reloc: unknown relocation mode %d\n", type); 15540435Speter } 15639072Sdfr 15740435Speter switch (rtype) { 15839072Sdfr 159288289Skib case R_PPC_NONE: 160288289Skib break; 16148840Sdfr 162209975Snwhitehorn case R_PPC64_ADDR64: /* doubleword64 S + A */ 163288287Skib error = lookup(lf, symidx, 1, &addr); 164288287Skib if (error != 0) 165288287Skib return -1; 166132282Sgrehan addr += addend; 167288289Skib *where = addr; 168288289Skib break; 16939072Sdfr 170209975Snwhitehorn case R_PPC_RELATIVE: /* doubleword64 B + A */ 171288289Skib *where = elf_relocaddr(lf, relocbase + addend); 172288289Skib break; 17339072Sdfr 174209975Snwhitehorn case R_PPC_JMP_SLOT: /* function descriptor copy */ 175288287Skib lookup(lf, symidx, 1, &addr); 176209975Snwhitehorn memcpy(where, (Elf_Addr *)addr, 3*sizeof(Elf_Addr)); 177209975Snwhitehorn __asm __volatile("dcbst 0,%0; sync" :: "r"(where) : "memory"); 178132282Sgrehan break; 17939072Sdfr 180132282Sgrehan default: 181288289Skib printf("kldload: unexpected relocation type %d\n", 182288289Skib (int) rtype); 183132282Sgrehan return -1; 18439072Sdfr } 18539072Sdfr return(0); 18639072Sdfr} 187105469Smarcel 188105469Smarcelint 189129282Speterelf_reloc(linker_file_t lf, Elf_Addr relocbase, const void *data, int type, 190129282Speter elf_lookup_fn lookup) 191109605Sjake{ 192109605Sjake 193129282Speter return (elf_reloc_internal(lf, relocbase, data, type, 0, lookup)); 194109605Sjake} 195109605Sjake 196109605Sjakeint 197129282Speterelf_reloc_local(linker_file_t lf, Elf_Addr relocbase, const void *data, 198129282Speter int type, elf_lookup_fn lookup) 199109605Sjake{ 200109605Sjake 201129282Speter return (elf_reloc_internal(lf, relocbase, data, type, 1, lookup)); 202109605Sjake} 203109605Sjake 204109605Sjakeint 205132428Sgrehanelf_cpu_load_file(linker_file_t lf) 206105469Smarcel{ 207132428Sgrehan /* Only sync the cache for non-kernel modules */ 208132428Sgrehan if (lf->id != 1) 209132428Sgrehan __syncicache(lf->address, lf->size); 210105469Smarcel return (0); 211105469Smarcel} 212105469Smarcel 213105469Smarcelint 214105469Smarcelelf_cpu_unload_file(linker_file_t lf __unused) 215105469Smarcel{ 216105469Smarcel 217105469Smarcel return (0); 218105469Smarcel} 219