1 /* $NetBSD: kobj_machdep.c,v 1.16 2023/04/28 07:33:56 skrll Exp $ */ 2 3 /*- 4 * Copyright (c) 2008 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /*- 30 * Copyright 1996-1998 John D. Polstra. 31 * All rights reserved. 32 * 33 * Redistribution and use in source and binary forms, with or without 34 * modification, are permitted provided that the following conditions 35 * are met: 36 * 1. Redistributions of source code must retain the above copyright 37 * notice, this list of conditions and the following disclaimer. 38 * 2. Redistributions in binary form must reproduce the above copyright 39 * notice, this list of conditions and the following disclaimer in the 40 * documentation and/or other materials provided with the distribution. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 43 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 44 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 45 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 46 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 47 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 48 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 49 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 50 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 51 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 52 */ 53 54 #include <sys/cdefs.h> 55 __KERNEL_RCSID(0, "$NetBSD: kobj_machdep.c,v 1.16 2023/04/28 07:33:56 skrll Exp $"); 56 57 #define ELFSIZE ARCH_ELFSIZE 58 59 #include <sys/param.h> 60 #include <sys/systm.h> 61 #include <sys/kobj.h> 62 #include <sys/exec.h> 63 #include <sys/exec_elf.h> 64 65 #include <uvm/uvm_extern.h> 66 67 #include <machine/cpufunc.h> 68 #include <machine/pmap.h> 69 70 static inline unsigned int 71 RND(unsigned int x) 72 { 73 return ((x + 0x1000) & 0xffffe000); 74 } 75 76 static inline unsigned int 77 R(unsigned int x) 78 { 79 return (x & 0x000007ff); 80 } 81 82 static inline unsigned int 83 L(unsigned int x) 84 { 85 return (x & 0xfffff800); 86 } 87 88 static inline unsigned int 89 LR(unsigned int x, unsigned int constant) 90 { 91 return L(x + RND(constant)); 92 } 93 94 static inline unsigned int 95 RR(unsigned int x, unsigned int constant) 96 { 97 return R(x + RND(constant)) + (constant - RND(constant)); 98 } 99 100 /* 101 * It is possible for the compiler to emit relocations for unaligned data. 102 * We handle this situation with these inlines. 103 */ 104 #define RELOC_ALIGNED_P(x) \ 105 (((uintptr_t)(x) & (sizeof(void *) - 1)) == 0) 106 107 static inline Elf_Addr 108 load_ptr(void *where) 109 { 110 if (__predict_true(RELOC_ALIGNED_P(where))) 111 return *(Elf_Addr *)where; 112 else { 113 Elf_Addr res; 114 115 (void)memcpy(&res, where, sizeof(res)); 116 return res; 117 } 118 } 119 120 static inline void 121 store_ptr(void *where, Elf_Addr val) 122 { 123 if (__predict_true(RELOC_ALIGNED_P(where))) 124 *(Elf_Addr *)where = val; 125 else 126 (void)memcpy(where, &val, sizeof(val)); 127 } 128 129 int 130 kobj_reloc(kobj_t ko, uintptr_t relocbase, const void *data, 131 bool isrela, bool local) 132 { 133 Elf_Addr *where; 134 Elf_Addr addr, value; 135 Elf_Word rtype, symidx; 136 const Elf_Rela *rela; 137 extern int __data_start; 138 139 unsigned int GP = (int) &__data_start; 140 141 if (!isrela) { 142 printf("kobj_reloc: only support RELA relocations\n"); 143 return -1; 144 } 145 146 rela = (const Elf_Rela *)data; 147 where = (Elf_Addr *) (relocbase + rela->r_offset); 148 value = rela->r_addend; 149 rtype = ELF_R_TYPE(rela->r_info); 150 symidx = ELF_R_SYM(rela->r_info); 151 152 const Elf_Sym *sym = kobj_symbol(ko, symidx); 153 154 if (!local && ELF_ST_BIND(sym->st_info) == STB_LOCAL) { 155 return 0; 156 } 157 158 switch (rtype) { 159 case R_TYPE(NONE): 160 break; 161 162 case R_TYPE(DIR32): 163 /* symbol + addend */ 164 kobj_sym_lookup(ko, symidx, &addr); 165 value += addr; 166 break; 167 168 case R_TYPE(DIR21L): 169 /* LR(symbol, addend) */ 170 kobj_sym_lookup(ko, symidx, &addr); 171 value = LR(addr, value); 172 break; 173 174 case R_TYPE(DIR17R): 175 case R_TYPE(DIR14R): 176 /* RR(symbol, addend) */ 177 kobj_sym_lookup(ko, symidx, &addr); 178 value = RR(addr, value); 179 break; 180 181 case R_TYPE(PCREL32): 182 case R_TYPE(PCREL17F): 183 /* symbol - PC - 8 + addend */ 184 kobj_sym_lookup(ko, symidx, &addr); 185 value += addr - (Elf_Word)where - 8; 186 break; 187 188 case R_TYPE(DPREL21L): 189 /* LR(symbol - GP, addend) */ 190 kobj_sym_lookup(ko, symidx, &addr); 191 value = LR(addr - GP, value); 192 break; 193 194 case R_TYPE(DPREL14R): 195 /* RR(symbol - GP, addend) */ 196 kobj_sym_lookup(ko, symidx, &addr); 197 value = RR(addr - GP, value); 198 break; 199 200 case R_TYPE(PLABEL32): 201 /* fptr(symbol) */ 202 kobj_sym_lookup(ko, symidx, &addr); 203 value = addr; 204 break; 205 206 case R_TYPE(SEGREL32): 207 /* symbol - SB + addend */ 208 /* XXX SB */ 209 kobj_sym_lookup(ko, symidx, &addr); 210 value += addr; 211 break; 212 213 default: 214 printf("%s: unexpected relocation type %d\n", __func__, rtype); 215 return -1; 216 } 217 218 switch (rtype) { 219 case R_TYPE(DIR32): 220 case R_TYPE(PCREL32): 221 case R_TYPE(PLABEL32): 222 case R_TYPE(SEGREL32): 223 store_ptr(where, value); 224 break; 225 226 case R_TYPE(DIR14R): 227 case R_TYPE(DPREL14R): 228 *where |= 229 (((value >> 0) & 0x1fff) << 1) | 230 (((value >> 13) & 0x1) << 0); 231 break; 232 233 case R_TYPE(DIR17R): 234 case R_TYPE(PCREL17F): 235 value >>= 2; /* bottom two bits not needed */ 236 *where |= 237 (((value & 0x10000) >> 16) << 0) | /* w */ 238 (((value & 0x0f800) >> 11) << 16) | /* w1 */ 239 (((value & 0x00400) >> 10) << 2) | 240 (((value & 0x003ff) << 1) << 2); /* w2 */ 241 break; 242 243 case R_TYPE(DIR21L): 244 case R_TYPE(DPREL21L): 245 *where |= 246 (((value >> 31) & 0x001) << 0) | 247 (((value >> 20) & 0x7ff) << 1) | 248 (((value >> 18) & 0x003) << 14) | 249 (((value >> 13) & 0x01f) << 16) | 250 (((value >> 11) & 0x003) << 12); 251 break; 252 } 253 254 return 0; 255 } 256 257 int 258 kobj_machdep(kobj_t ko, void *base, size_t size, bool load) 259 { 260 261 if (load) { 262 fdcache(HPPA_SID_KERNEL, (vaddr_t)base, size); 263 ficache(HPPA_SID_KERNEL, (vaddr_t)base, size); 264 } 265 266 return 0; 267 } 268