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