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