xref: /linux-6.15/arch/xtensa/include/asm/processor.h (revision 5055d82b)
1367b8112SChris Zankel /*
2367b8112SChris Zankel  * This file is subject to the terms and conditions of the GNU General Public
3367b8112SChris Zankel  * License.  See the file "COPYING" in the main directory of this archive
4367b8112SChris Zankel  * for more details.
5367b8112SChris Zankel  *
62d1c645cSMarc Gauthier  * Copyright (C) 2001 - 2008 Tensilica Inc.
738fef73cSMax Filippov  * Copyright (C) 2015 Cadence Design Systems Inc.
8367b8112SChris Zankel  */
9367b8112SChris Zankel 
10367b8112SChris Zankel #ifndef _XTENSA_PROCESSOR_H
11367b8112SChris Zankel #define _XTENSA_PROCESSOR_H
12367b8112SChris Zankel 
138f8d5745SMax Filippov #include <asm/core.h>
14367b8112SChris Zankel 
15367b8112SChris Zankel #include <linux/compiler.h>
16cad6fadeSMax Filippov #include <linux/stringify.h>
17ccf9d278SRandy Dunlap 
18ccf9d278SRandy Dunlap #include <asm/bootparam.h>
19367b8112SChris Zankel #include <asm/ptrace.h>
20367b8112SChris Zankel #include <asm/types.h>
21367b8112SChris Zankel #include <asm/regs.h>
22367b8112SChris Zankel 
23e94dc6bbSMax Filippov #define ARCH_SLAB_MINALIGN XTENSA_STACK_ALIGNMENT
24a81cbd2dSOskar Schirmer 
25367b8112SChris Zankel /*
26367b8112SChris Zankel  * User space process size: 1 GB.
27367b8112SChris Zankel  * Windowed call ABI requires caller and callee to be located within the same
28367b8112SChris Zankel  * 1 GB region. The C compiler places trampoline code on the stack for sources
29367b8112SChris Zankel  * that take the address of a nested C function (a feature used by glibc), so
30367b8112SChris Zankel  * the 1 GB requirement applies to the stack as well.
31367b8112SChris Zankel  */
32367b8112SChris Zankel 
33e5083a63SJohannes Weiner #ifdef CONFIG_MMU
34367b8112SChris Zankel #define TASK_SIZE	__XTENSA_UL_CONST(0x40000000)
35e5083a63SJohannes Weiner #else
363de00482SMax Filippov #define TASK_SIZE	__XTENSA_UL_CONST(0xffffffff)
37e5083a63SJohannes Weiner #endif
38e5083a63SJohannes Weiner 
39367b8112SChris Zankel #define STACK_TOP	TASK_SIZE
40367b8112SChris Zankel #define STACK_TOP_MAX	STACK_TOP
41367b8112SChris Zankel 
42367b8112SChris Zankel /*
4338fef73cSMax Filippov  * General exception cause assigned to fake NMI. Fake NMI needs to be handled
4438fef73cSMax Filippov  * differently from other interrupts, but it uses common kernel entry/exit
4538fef73cSMax Filippov  * code.
4638fef73cSMax Filippov  */
4738fef73cSMax Filippov 
4838fef73cSMax Filippov #define EXCCAUSE_MAPPED_NMI	62
4938fef73cSMax Filippov 
5038fef73cSMax Filippov /*
51367b8112SChris Zankel  * General exception cause assigned to debug exceptions. Debug exceptions go
52367b8112SChris Zankel  * to their own vector, rather than the general exception vectors (user,
53367b8112SChris Zankel  * kernel, double); and their specific causes are reported via DEBUGCAUSE
54367b8112SChris Zankel  * rather than EXCCAUSE.  However it is sometimes convenient to redirect debug
55367b8112SChris Zankel  * exceptions to the general exception mechanism.  To do this, an otherwise
56367b8112SChris Zankel  * unused EXCCAUSE value was assigned to debug exceptions for this purpose.
57367b8112SChris Zankel  */
58367b8112SChris Zankel 
59367b8112SChris Zankel #define EXCCAUSE_MAPPED_DEBUG	63
60367b8112SChris Zankel 
61367b8112SChris Zankel /*
62367b8112SChris Zankel  * We use DEPC also as a flag to distinguish between double and regular
63367b8112SChris Zankel  * exceptions. For performance reasons, DEPC might contain the value of
64367b8112SChris Zankel  * EXCCAUSE for regular exceptions, so we use this definition to mark a
65367b8112SChris Zankel  * valid double exception address.
66367b8112SChris Zankel  * (Note: We use it in bgeui, so it should be 64, 128, or 256)
67367b8112SChris Zankel  */
68367b8112SChris Zankel 
69367b8112SChris Zankel #define VALID_DOUBLE_EXCEPTION_ADDRESS	64
70367b8112SChris Zankel 
7138fef73cSMax Filippov #define XTENSA_INT_LEVEL(intno) _XTENSA_INT_LEVEL(intno)
7238fef73cSMax Filippov #define _XTENSA_INT_LEVEL(intno) XCHAL_INT##intno##_LEVEL
7338fef73cSMax Filippov 
7438fef73cSMax Filippov #define XTENSA_INTLEVEL_MASK(level) _XTENSA_INTLEVEL_MASK(level)
7538fef73cSMax Filippov #define _XTENSA_INTLEVEL_MASK(level) (XCHAL_INTLEVEL##level##_MASK)
7638fef73cSMax Filippov 
77e4629194SMax Filippov #define XTENSA_INTLEVEL_ANDBELOW_MASK(l) _XTENSA_INTLEVEL_ANDBELOW_MASK(l)
78e4629194SMax Filippov #define _XTENSA_INTLEVEL_ANDBELOW_MASK(l) (XCHAL_INTLEVEL##l##_ANDBELOW_MASK)
7938fef73cSMax Filippov 
8038fef73cSMax Filippov #define PROFILING_INTLEVEL XTENSA_INT_LEVEL(XCHAL_PROFILING_INTERRUPT)
8138fef73cSMax Filippov 
82367b8112SChris Zankel /* LOCKLEVEL defines the interrupt level that masks all
83367b8112SChris Zankel  * general-purpose interrupts.
84367b8112SChris Zankel  */
85e4629194SMax Filippov #if defined(CONFIG_XTENSA_FAKE_NMI) && defined(XCHAL_PROFILING_INTERRUPT)
86e4629194SMax Filippov #define LOCKLEVEL (PROFILING_INTLEVEL - 1)
8738fef73cSMax Filippov #else
882d1c645cSMarc Gauthier #define LOCKLEVEL XCHAL_EXCM_LEVEL
8938fef73cSMax Filippov #endif
90e4629194SMax Filippov 
9138fef73cSMax Filippov #define TOPLEVEL XCHAL_EXCM_LEVEL
9238fef73cSMax Filippov #define XTENSA_FAKE_NMI (LOCKLEVEL < TOPLEVEL)
93367b8112SChris Zankel 
94367b8112SChris Zankel /* WSBITS and WBBITS are the width of the WINDOWSTART and WINDOWBASE
95367b8112SChris Zankel  * registers
96367b8112SChris Zankel  */
97367b8112SChris Zankel #define WSBITS  (XCHAL_NUM_AREGS / 4)      /* width of WINDOWSTART in bits */
98367b8112SChris Zankel #define WBBITS  (XCHAL_NUM_AREGS_LOG2 - 2) /* width of WINDOWBASE in bits */
99367b8112SChris Zankel 
1005cce39b6SMax Filippov #if defined(__XTENSA_WINDOWED_ABI__)
1015cce39b6SMax Filippov #define KERNEL_PS_WOE_MASK PS_WOE_MASK
1025cce39b6SMax Filippov #elif defined(__XTENSA_CALL0_ABI__)
1035cce39b6SMax Filippov #define KERNEL_PS_WOE_MASK 0
1045cce39b6SMax Filippov #else
1055cce39b6SMax Filippov #error Unsupported xtensa ABI
1065cce39b6SMax Filippov #endif
1075cce39b6SMax Filippov 
108367b8112SChris Zankel #ifndef __ASSEMBLY__
109367b8112SChris Zankel 
1105cce39b6SMax Filippov #if defined(__XTENSA_WINDOWED_ABI__)
1115cce39b6SMax Filippov 
112367b8112SChris Zankel /* Build a valid return address for the specified call winsize.
113367b8112SChris Zankel  * winsize must be 1 (call4), 2 (call8), or 3 (call12)
114367b8112SChris Zankel  */
115367b8112SChris Zankel #define MAKE_RA_FOR_CALL(ra,ws)   (((ra) & 0x3fffffff) | (ws) << 30)
116367b8112SChris Zankel 
117367b8112SChris Zankel /* Convert return address to a valid pc
1180e60f0b7SMax Filippov  * Note: 'text' is the address within the same 1GB range as the ra
119367b8112SChris Zankel  */
1200e60f0b7SMax Filippov #define MAKE_PC_FROM_RA(ra, text) (((ra) & 0x3fffffff) | ((unsigned long)(text) & 0xc0000000))
121367b8112SChris Zankel 
1225cce39b6SMax Filippov #elif defined(__XTENSA_CALL0_ABI__)
1235cce39b6SMax Filippov 
1245cce39b6SMax Filippov /* Build a valid return address for the specified call winsize.
1255cce39b6SMax Filippov  * winsize must be 1 (call4), 2 (call8), or 3 (call12)
1265cce39b6SMax Filippov  */
1275cce39b6SMax Filippov #define MAKE_RA_FOR_CALL(ra, ws)   (ra)
1285cce39b6SMax Filippov 
1295cce39b6SMax Filippov /* Convert return address to a valid pc
1300e60f0b7SMax Filippov  * Note: 'text' is not used as 'ra' is always the full address
1315cce39b6SMax Filippov  */
1320e60f0b7SMax Filippov #define MAKE_PC_FROM_RA(ra, text)  (ra)
1335cce39b6SMax Filippov 
1345cce39b6SMax Filippov #else
1355cce39b6SMax Filippov #error Unsupported Xtensa ABI
1365cce39b6SMax Filippov #endif
1375cce39b6SMax Filippov 
138062b1c19SMax Filippov /* Spill slot location for the register reg in the spill area under the stack
139062b1c19SMax Filippov  * pointer sp. reg must be in the range [0..4).
140062b1c19SMax Filippov  */
141062b1c19SMax Filippov #define SPILL_SLOT(sp, reg) (*(((unsigned long *)(sp)) - 4 + (reg)))
142062b1c19SMax Filippov 
143062b1c19SMax Filippov /* Spill slot location for the register reg in the spill area under the stack
144062b1c19SMax Filippov  * pointer sp for the call8. reg must be in the range [4..8).
145062b1c19SMax Filippov  */
146062b1c19SMax Filippov #define SPILL_SLOT_CALL8(sp, reg) (*(((unsigned long *)(sp)) - 12 + (reg)))
147062b1c19SMax Filippov 
148062b1c19SMax Filippov /* Spill slot location for the register reg in the spill area under the stack
149062b1c19SMax Filippov  * pointer sp for the call12. reg must be in the range [4..12).
150062b1c19SMax Filippov  */
151062b1c19SMax Filippov #define SPILL_SLOT_CALL12(sp, reg) (*(((unsigned long *)(sp)) - 16 + (reg)))
152062b1c19SMax Filippov 
153367b8112SChris Zankel struct thread_struct {
154367b8112SChris Zankel 
155367b8112SChris Zankel 	/* kernel's return address and stack pointer for context switching */
156367b8112SChris Zankel 	unsigned long ra; /* kernel's a0: return address and window call size */
157367b8112SChris Zankel 	unsigned long sp; /* kernel's a1: stack pointer */
158367b8112SChris Zankel 
159c91e02bdSMax Filippov #ifdef CONFIG_HAVE_HW_BREAKPOINT
160c91e02bdSMax Filippov 	struct perf_event *ptrace_bp[XCHAL_NUM_IBREAK];
161c91e02bdSMax Filippov 	struct perf_event *ptrace_wp[XCHAL_NUM_DBREAK];
162c91e02bdSMax Filippov #endif
163*5055d82bSThorsten Blum } __aligned(16);
164367b8112SChris Zankel 
165367b8112SChris Zankel /* This decides where the kernel will search for a free chunk of vm
166367b8112SChris Zankel  * space during mmap's.
167367b8112SChris Zankel  */
168367b8112SChris Zankel #define TASK_UNMAPPED_BASE	(TASK_SIZE / 2)
169367b8112SChris Zankel 
170367b8112SChris Zankel #define INIT_THREAD  \
171367b8112SChris Zankel {									\
172367b8112SChris Zankel 	ra:		0, 						\
173367b8112SChris Zankel 	sp:		sizeof(init_stack) + (long) &init_stack,	\
174367b8112SChris Zankel }
175367b8112SChris Zankel 
176367b8112SChris Zankel 
177367b8112SChris Zankel /*
178367b8112SChris Zankel  * Do necessary setup to start up a newly executed thread.
17909f8a6dbSMax Filippov  * Note: When windowed ABI is used for userspace we set-up ps
18009f8a6dbSMax Filippov  *       as if we did a call4 to the new pc.
181367b8112SChris Zankel  *       set_thread_state in signal.c depends on it.
182367b8112SChris Zankel  */
18309f8a6dbSMax Filippov #if IS_ENABLED(CONFIG_USER_ABI_CALL0)
18409f8a6dbSMax Filippov #define USER_PS_VALUE ((USER_RING << PS_RING_SHIFT) |			\
18509f8a6dbSMax Filippov 		       (1 << PS_UM_BIT) |				\
18609f8a6dbSMax Filippov 		       (1 << PS_EXCM_BIT))
18709f8a6dbSMax Filippov #else
1889e1e41c4SMax Filippov #define USER_PS_VALUE (PS_WOE_MASK |					\
189367b8112SChris Zankel 		       (1 << PS_CALLINC_SHIFT) |			\
190367b8112SChris Zankel 		       (USER_RING << PS_RING_SHIFT) |			\
191367b8112SChris Zankel 		       (1 << PS_UM_BIT) |				\
192367b8112SChris Zankel 		       (1 << PS_EXCM_BIT))
19309f8a6dbSMax Filippov #endif
194367b8112SChris Zankel 
195367b8112SChris Zankel /* Clearing a0 terminates the backtrace. */
196367b8112SChris Zankel #define start_thread(regs, new_pc, new_sp) \
1972663147dSMax Filippov 	do { \
198ba9c1d65SMax Filippov 		unsigned long syscall = (regs)->syscall; \
199e3ddb8bbSMax Filippov 		unsigned long current_aregs[16]; \
200e3ddb8bbSMax Filippov 		memcpy(current_aregs, (regs)->areg, sizeof(current_aregs)); \
2012663147dSMax Filippov 		memset((regs), 0, sizeof(*(regs))); \
2022663147dSMax Filippov 		(regs)->pc = (new_pc); \
2032663147dSMax Filippov 		(regs)->ps = USER_PS_VALUE; \
204e3ddb8bbSMax Filippov 		memcpy((regs)->areg, current_aregs, sizeof(current_aregs)); \
2052663147dSMax Filippov 		(regs)->areg[1] = (new_sp); \
2062663147dSMax Filippov 		(regs)->areg[0] = 0; \
2072663147dSMax Filippov 		(regs)->wmask = 1; \
2082663147dSMax Filippov 		(regs)->depc = 0; \
2092663147dSMax Filippov 		(regs)->windowbase = 0; \
2102663147dSMax Filippov 		(regs)->windowstart = 1; \
211ba9c1d65SMax Filippov 		(regs)->syscall = syscall; \
2122663147dSMax Filippov 	} while (0)
213367b8112SChris Zankel 
214367b8112SChris Zankel /* Forward declaration */
215367b8112SChris Zankel struct task_struct;
216367b8112SChris Zankel struct mm_struct;
217367b8112SChris Zankel 
21842a20f86SKees Cook extern unsigned long __get_wchan(struct task_struct *p);
219367b8112SChris Zankel 
220ccf9d278SRandy Dunlap void init_arch(bp_tag_t *bp_start);
2214ec4b8b1SRandy Dunlap void do_notify_resume(struct pt_regs *regs);
222ccf9d278SRandy Dunlap 
223367b8112SChris Zankel #define KSTK_EIP(tsk)		(task_pt_regs(tsk)->pc)
224367b8112SChris Zankel #define KSTK_ESP(tsk)		(task_pt_regs(tsk)->areg[1])
225367b8112SChris Zankel 
226367b8112SChris Zankel #define cpu_relax()  barrier()
227367b8112SChris Zankel 
228367b8112SChris Zankel /* Special register access. */
229367b8112SChris Zankel 
230cad6fadeSMax Filippov #define xtensa_set_sr(x, sr) \
231cad6fadeSMax Filippov 	({ \
232a3d0245cSMax Filippov 	 __asm__ __volatile__ ("wsr %0, "__stringify(sr) :: \
233a3d0245cSMax Filippov 			       "a"((unsigned int)(x))); \
234cad6fadeSMax Filippov 	 })
235367b8112SChris Zankel 
236cad6fadeSMax Filippov #define xtensa_get_sr(sr) \
237cad6fadeSMax Filippov 	({ \
238cad6fadeSMax Filippov 	 unsigned int v; \
239cad6fadeSMax Filippov 	 __asm__ __volatile__ ("rsr %0, "__stringify(sr) : "=a"(v)); \
240cad6fadeSMax Filippov 	 v; \
241cad6fadeSMax Filippov 	 })
242367b8112SChris Zankel 
243dedfe259SMax Filippov #define xtensa_xsr(x, sr) \
244dedfe259SMax Filippov 	({ \
245dedfe259SMax Filippov 	 unsigned int __v__ = (unsigned int)(x); \
246dedfe259SMax Filippov 	 __asm__ __volatile__ ("xsr %0, " __stringify(sr) : "+a"(__v__)); \
247dedfe259SMax Filippov 	 __v__; \
248dedfe259SMax Filippov 	 })
249dedfe259SMax Filippov 
25026a8e96aSMax Filippov #if XCHAL_HAVE_EXTERN_REGS
25126a8e96aSMax Filippov 
set_er(unsigned long value,unsigned long addr)25226a8e96aSMax Filippov static inline void set_er(unsigned long value, unsigned long addr)
25326a8e96aSMax Filippov {
25426a8e96aSMax Filippov 	asm volatile ("wer %0, %1" : : "a" (value), "a" (addr) : "memory");
25526a8e96aSMax Filippov }
25626a8e96aSMax Filippov 
get_er(unsigned long addr)25726a8e96aSMax Filippov static inline unsigned long get_er(unsigned long addr)
25826a8e96aSMax Filippov {
25926a8e96aSMax Filippov 	register unsigned long value;
26026a8e96aSMax Filippov 	asm volatile ("rer %0, %1" : "=a" (value) : "a" (addr) : "memory");
26126a8e96aSMax Filippov 	return value;
26226a8e96aSMax Filippov }
26326a8e96aSMax Filippov 
26426a8e96aSMax Filippov #endif /* XCHAL_HAVE_EXTERN_REGS */
26526a8e96aSMax Filippov 
266367b8112SChris Zankel #endif	/* __ASSEMBLY__ */
267367b8112SChris Zankel #endif	/* _XTENSA_PROCESSOR_H */
268