1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Copyright (C) 2020-2022 Loongson Technology Corporation Limited 4 */ 5 #ifndef _ASM_ELF_H 6 #define _ASM_ELF_H 7 8 #include <linux/auxvec.h> 9 #include <linux/fs.h> 10 #include <uapi/linux/elf.h> 11 12 #include <asm/current.h> 13 #include <asm/vdso.h> 14 15 /* The ABI of a file. */ 16 #define EF_LOONGARCH_ABI_LP64_SOFT_FLOAT 0x1 17 #define EF_LOONGARCH_ABI_LP64_SINGLE_FLOAT 0x2 18 #define EF_LOONGARCH_ABI_LP64_DOUBLE_FLOAT 0x3 19 20 #define EF_LOONGARCH_ABI_ILP32_SOFT_FLOAT 0x5 21 #define EF_LOONGARCH_ABI_ILP32_SINGLE_FLOAT 0x6 22 #define EF_LOONGARCH_ABI_ILP32_DOUBLE_FLOAT 0x7 23 24 /* LoongArch relocation types used by the dynamic linker */ 25 #define R_LARCH_NONE 0 26 #define R_LARCH_32 1 27 #define R_LARCH_64 2 28 #define R_LARCH_RELATIVE 3 29 #define R_LARCH_COPY 4 30 #define R_LARCH_JUMP_SLOT 5 31 #define R_LARCH_TLS_DTPMOD32 6 32 #define R_LARCH_TLS_DTPMOD64 7 33 #define R_LARCH_TLS_DTPREL32 8 34 #define R_LARCH_TLS_DTPREL64 9 35 #define R_LARCH_TLS_TPREL32 10 36 #define R_LARCH_TLS_TPREL64 11 37 #define R_LARCH_IRELATIVE 12 38 #define R_LARCH_MARK_LA 20 39 #define R_LARCH_MARK_PCREL 21 40 #define R_LARCH_SOP_PUSH_PCREL 22 41 #define R_LARCH_SOP_PUSH_ABSOLUTE 23 42 #define R_LARCH_SOP_PUSH_DUP 24 43 #define R_LARCH_SOP_PUSH_GPREL 25 44 #define R_LARCH_SOP_PUSH_TLS_TPREL 26 45 #define R_LARCH_SOP_PUSH_TLS_GOT 27 46 #define R_LARCH_SOP_PUSH_TLS_GD 28 47 #define R_LARCH_SOP_PUSH_PLT_PCREL 29 48 #define R_LARCH_SOP_ASSERT 30 49 #define R_LARCH_SOP_NOT 31 50 #define R_LARCH_SOP_SUB 32 51 #define R_LARCH_SOP_SL 33 52 #define R_LARCH_SOP_SR 34 53 #define R_LARCH_SOP_ADD 35 54 #define R_LARCH_SOP_AND 36 55 #define R_LARCH_SOP_IF_ELSE 37 56 #define R_LARCH_SOP_POP_32_S_10_5 38 57 #define R_LARCH_SOP_POP_32_U_10_12 39 58 #define R_LARCH_SOP_POP_32_S_10_12 40 59 #define R_LARCH_SOP_POP_32_S_10_16 41 60 #define R_LARCH_SOP_POP_32_S_10_16_S2 42 61 #define R_LARCH_SOP_POP_32_S_5_20 43 62 #define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44 63 #define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45 64 #define R_LARCH_SOP_POP_32_U 46 65 #define R_LARCH_ADD8 47 66 #define R_LARCH_ADD16 48 67 #define R_LARCH_ADD24 49 68 #define R_LARCH_ADD32 50 69 #define R_LARCH_ADD64 51 70 #define R_LARCH_SUB8 52 71 #define R_LARCH_SUB16 53 72 #define R_LARCH_SUB24 54 73 #define R_LARCH_SUB32 55 74 #define R_LARCH_SUB64 56 75 #define R_LARCH_GNU_VTINHERIT 57 76 #define R_LARCH_GNU_VTENTRY 58 77 78 #ifndef ELF_ARCH 79 80 /* ELF register definitions */ 81 82 /* 83 * General purpose have the following registers: 84 * Register Number 85 * GPRs 32 86 * ORIG_A0 1 87 * ERA 1 88 * BADVADDR 1 89 * CRMD 1 90 * PRMD 1 91 * EUEN 1 92 * ECFG 1 93 * ESTAT 1 94 * Reserved 5 95 */ 96 #define ELF_NGREG 45 97 98 /* 99 * Floating point have the following registers: 100 * Register Number 101 * FPR 32 102 * FCC 1 103 * FCSR 1 104 */ 105 #define ELF_NFPREG 34 106 107 typedef unsigned long elf_greg_t; 108 typedef elf_greg_t elf_gregset_t[ELF_NGREG]; 109 110 typedef double elf_fpreg_t; 111 typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG]; 112 113 void loongarch_dump_regs64(u64 *uregs, const struct pt_regs *regs); 114 115 #ifdef CONFIG_32BIT 116 /* 117 * This is used to ensure we don't load something for the wrong architecture. 118 */ 119 #define elf_check_arch elf32_check_arch 120 121 /* 122 * These are used to set parameters in the core dumps. 123 */ 124 #define ELF_CLASS ELFCLASS32 125 126 #define ELF_CORE_COPY_REGS(dest, regs) \ 127 loongarch_dump_regs32((u32 *)&(dest), (regs)); 128 129 #endif /* CONFIG_32BIT */ 130 131 #ifdef CONFIG_64BIT 132 /* 133 * This is used to ensure we don't load something for the wrong architecture. 134 */ 135 #define elf_check_arch elf64_check_arch 136 137 /* 138 * These are used to set parameters in the core dumps. 139 */ 140 #define ELF_CLASS ELFCLASS64 141 142 #define ELF_CORE_COPY_REGS(dest, regs) \ 143 loongarch_dump_regs64((u64 *)&(dest), (regs)); 144 145 #endif /* CONFIG_64BIT */ 146 147 /* 148 * These are used to set parameters in the core dumps. 149 */ 150 #define ELF_DATA ELFDATA2LSB 151 #define ELF_ARCH EM_LOONGARCH 152 153 #endif /* !defined(ELF_ARCH) */ 154 155 #define loongarch_elf_check_machine(x) ((x)->e_machine == EM_LOONGARCH) 156 157 #define vmcore_elf32_check_arch loongarch_elf_check_machine 158 #define vmcore_elf64_check_arch loongarch_elf_check_machine 159 160 /* 161 * Return non-zero if HDR identifies an 32bit ELF binary. 162 */ 163 #define elf32_check_arch(hdr) \ 164 ({ \ 165 int __res = 1; \ 166 struct elfhdr *__h = (hdr); \ 167 \ 168 if (!loongarch_elf_check_machine(__h)) \ 169 __res = 0; \ 170 if (__h->e_ident[EI_CLASS] != ELFCLASS32) \ 171 __res = 0; \ 172 \ 173 __res; \ 174 }) 175 176 /* 177 * Return non-zero if HDR identifies an 64bit ELF binary. 178 */ 179 #define elf64_check_arch(hdr) \ 180 ({ \ 181 int __res = 1; \ 182 struct elfhdr *__h = (hdr); \ 183 \ 184 if (!loongarch_elf_check_machine(__h)) \ 185 __res = 0; \ 186 if (__h->e_ident[EI_CLASS] != ELFCLASS64) \ 187 __res = 0; \ 188 \ 189 __res; \ 190 }) 191 192 #ifdef CONFIG_32BIT 193 194 #define SET_PERSONALITY2(ex, state) \ 195 do { \ 196 current->thread.vdso = &vdso_info; \ 197 \ 198 loongarch_set_personality_fcsr(state); \ 199 \ 200 if (personality(current->personality) != PER_LINUX) \ 201 set_personality(PER_LINUX); \ 202 } while (0) 203 204 #endif /* CONFIG_32BIT */ 205 206 #ifdef CONFIG_64BIT 207 208 #define SET_PERSONALITY2(ex, state) \ 209 do { \ 210 unsigned int p; \ 211 \ 212 clear_thread_flag(TIF_32BIT_REGS); \ 213 clear_thread_flag(TIF_32BIT_ADDR); \ 214 \ 215 current->thread.vdso = &vdso_info; \ 216 loongarch_set_personality_fcsr(state); \ 217 \ 218 p = personality(current->personality); \ 219 if (p != PER_LINUX32 && p != PER_LINUX) \ 220 set_personality(PER_LINUX); \ 221 } while (0) 222 223 #endif /* CONFIG_64BIT */ 224 225 #define CORE_DUMP_USE_REGSET 226 #define ELF_EXEC_PAGESIZE PAGE_SIZE 227 228 /* 229 * This yields a mask that user programs can use to figure out what 230 * instruction set this cpu supports. This could be done in userspace, 231 * but it's not easy, and we've already done it here. 232 */ 233 234 #define ELF_HWCAP (elf_hwcap) 235 extern unsigned int elf_hwcap; 236 #include <asm/hwcap.h> 237 238 /* 239 * This yields a string that ld.so will use to load implementation 240 * specific libraries for optimization. This is more specific in 241 * intent than poking at uname or /proc/cpuinfo. 242 */ 243 244 #define ELF_PLATFORM __elf_platform 245 extern const char *__elf_platform; 246 247 #define ELF_PLAT_INIT(_r, load_addr) do { \ 248 _r->regs[1] = _r->regs[2] = _r->regs[3] = _r->regs[4] = 0; \ 249 _r->regs[5] = _r->regs[6] = _r->regs[7] = _r->regs[8] = 0; \ 250 _r->regs[9] = _r->regs[10] = _r->regs[11] = _r->regs[12] = 0; \ 251 _r->regs[13] = _r->regs[14] = _r->regs[15] = _r->regs[16] = 0; \ 252 _r->regs[17] = _r->regs[18] = _r->regs[19] = _r->regs[20] = 0; \ 253 _r->regs[21] = _r->regs[22] = _r->regs[23] = _r->regs[24] = 0; \ 254 _r->regs[25] = _r->regs[26] = _r->regs[27] = _r->regs[28] = 0; \ 255 _r->regs[29] = _r->regs[30] = _r->regs[31] = 0; \ 256 } while (0) 257 258 /* 259 * This is the location that an ET_DYN program is loaded if exec'ed. Typical 260 * use of this is to invoke "./ld.so someprog" to test out a new version of 261 * the loader. We need to make sure that it is out of the way of the program 262 * that it will "exec", and that there is sufficient room for the brk. 263 */ 264 265 #define ELF_ET_DYN_BASE (TASK_SIZE / 3 * 2) 266 267 /* update AT_VECTOR_SIZE_ARCH if the number of NEW_AUX_ENT entries changes */ 268 #define ARCH_DLINFO \ 269 do { \ 270 NEW_AUX_ENT(AT_SYSINFO_EHDR, \ 271 (unsigned long)current->mm->context.vdso); \ 272 } while (0) 273 274 #define ARCH_HAS_SETUP_ADDITIONAL_PAGES 1 275 struct linux_binprm; 276 extern int arch_setup_additional_pages(struct linux_binprm *bprm, 277 int uses_interp); 278 279 struct arch_elf_state { 280 int fp_abi; 281 int interp_fp_abi; 282 }; 283 284 #define LOONGARCH_ABI_FP_ANY (0) 285 286 #define INIT_ARCH_ELF_STATE { \ 287 .fp_abi = LOONGARCH_ABI_FP_ANY, \ 288 .interp_fp_abi = LOONGARCH_ABI_FP_ANY, \ 289 } 290 291 extern int arch_elf_pt_proc(void *ehdr, void *phdr, struct file *elf, 292 bool is_interp, struct arch_elf_state *state); 293 294 extern int arch_check_elf(void *ehdr, bool has_interpreter, void *interp_ehdr, 295 struct arch_elf_state *state); 296 297 extern void loongarch_set_personality_fcsr(struct arch_elf_state *state); 298 299 #endif /* _ASM_ELF_H */ 300