xref: /OK3568_Linux_fs/kernel/arch/s390/include/asm/extable.h (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /* SPDX-License-Identifier: GPL-2.0 */
2*4882a593Smuzhiyun #ifndef __S390_EXTABLE_H
3*4882a593Smuzhiyun #define __S390_EXTABLE_H
4*4882a593Smuzhiyun 
5*4882a593Smuzhiyun #include <asm/ptrace.h>
6*4882a593Smuzhiyun #include <linux/compiler.h>
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun /*
9*4882a593Smuzhiyun  * The exception table consists of three addresses:
10*4882a593Smuzhiyun  *
11*4882a593Smuzhiyun  * - Address of an instruction that is allowed to fault.
12*4882a593Smuzhiyun  * - Address at which the program should continue.
13*4882a593Smuzhiyun  * - Optional address of handler that takes pt_regs * argument and runs in
14*4882a593Smuzhiyun  *   interrupt context.
15*4882a593Smuzhiyun  *
16*4882a593Smuzhiyun  * No registers are modified, so it is entirely up to the continuation code
17*4882a593Smuzhiyun  * to figure out what to do.
18*4882a593Smuzhiyun  *
19*4882a593Smuzhiyun  * All the routines below use bits of fixup code that are out of line
20*4882a593Smuzhiyun  * with the main instruction path.  This means when everything is well,
21*4882a593Smuzhiyun  * we don't even have to jump over them.  Further, they do not intrude
22*4882a593Smuzhiyun  * on our cache or tlb entries.
23*4882a593Smuzhiyun  */
24*4882a593Smuzhiyun 
25*4882a593Smuzhiyun struct exception_table_entry
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	int insn, fixup;
28*4882a593Smuzhiyun 	long handler;
29*4882a593Smuzhiyun };
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun extern struct exception_table_entry *__start_dma_ex_table;
32*4882a593Smuzhiyun extern struct exception_table_entry *__stop_dma_ex_table;
33*4882a593Smuzhiyun 
34*4882a593Smuzhiyun const struct exception_table_entry *s390_search_extables(unsigned long addr);
35*4882a593Smuzhiyun 
extable_fixup(const struct exception_table_entry * x)36*4882a593Smuzhiyun static inline unsigned long extable_fixup(const struct exception_table_entry *x)
37*4882a593Smuzhiyun {
38*4882a593Smuzhiyun 	return (unsigned long)&x->fixup + x->fixup;
39*4882a593Smuzhiyun }
40*4882a593Smuzhiyun 
41*4882a593Smuzhiyun typedef bool (*ex_handler_t)(const struct exception_table_entry *,
42*4882a593Smuzhiyun 			     struct pt_regs *);
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun static inline ex_handler_t
ex_fixup_handler(const struct exception_table_entry * x)45*4882a593Smuzhiyun ex_fixup_handler(const struct exception_table_entry *x)
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun 	if (likely(!x->handler))
48*4882a593Smuzhiyun 		return NULL;
49*4882a593Smuzhiyun 	return (ex_handler_t)((unsigned long)&x->handler + x->handler);
50*4882a593Smuzhiyun }
51*4882a593Smuzhiyun 
ex_handle(const struct exception_table_entry * x,struct pt_regs * regs)52*4882a593Smuzhiyun static inline bool ex_handle(const struct exception_table_entry *x,
53*4882a593Smuzhiyun 			     struct pt_regs *regs)
54*4882a593Smuzhiyun {
55*4882a593Smuzhiyun 	ex_handler_t handler = ex_fixup_handler(x);
56*4882a593Smuzhiyun 
57*4882a593Smuzhiyun 	if (unlikely(handler))
58*4882a593Smuzhiyun 		return handler(x, regs);
59*4882a593Smuzhiyun 	regs->psw.addr = extable_fixup(x);
60*4882a593Smuzhiyun 	return true;
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define ARCH_HAS_RELATIVE_EXTABLE
64*4882a593Smuzhiyun 
swap_ex_entry_fixup(struct exception_table_entry * a,struct exception_table_entry * b,struct exception_table_entry tmp,int delta)65*4882a593Smuzhiyun static inline void swap_ex_entry_fixup(struct exception_table_entry *a,
66*4882a593Smuzhiyun 				       struct exception_table_entry *b,
67*4882a593Smuzhiyun 				       struct exception_table_entry tmp,
68*4882a593Smuzhiyun 				       int delta)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	a->fixup = b->fixup + delta;
71*4882a593Smuzhiyun 	b->fixup = tmp.fixup - delta;
72*4882a593Smuzhiyun 	a->handler = b->handler;
73*4882a593Smuzhiyun 	if (a->handler)
74*4882a593Smuzhiyun 		a->handler += delta;
75*4882a593Smuzhiyun 	b->handler = tmp.handler;
76*4882a593Smuzhiyun 	if (b->handler)
77*4882a593Smuzhiyun 		b->handler -= delta;
78*4882a593Smuzhiyun }
79*4882a593Smuzhiyun #define swap_ex_entry_fixup swap_ex_entry_fixup
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun #endif
82