xref: /openbmc/linux/arch/alpha/include/asm/extable.h (revision 498495dba268b20e8eadd7fe93c140c68b6cc9d2)
1*b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2b5478c1bSAl Viro #ifndef _ASM_EXTABLE_H
3b5478c1bSAl Viro #define _ASM_EXTABLE_H
4b5478c1bSAl Viro 
5b5478c1bSAl Viro /*
6b5478c1bSAl Viro  * About the exception table:
7b5478c1bSAl Viro  *
8b5478c1bSAl Viro  * - insn is a 32-bit pc-relative offset from the faulting insn.
9b5478c1bSAl Viro  * - nextinsn is a 16-bit offset off of the faulting instruction
10b5478c1bSAl Viro  *   (not off of the *next* instruction as branches are).
11b5478c1bSAl Viro  * - errreg is the register in which to place -EFAULT.
12b5478c1bSAl Viro  * - valreg is the final target register for the load sequence
13b5478c1bSAl Viro  *   and will be zeroed.
14b5478c1bSAl Viro  *
15b5478c1bSAl Viro  * Either errreg or valreg may be $31, in which case nothing happens.
16b5478c1bSAl Viro  *
17b5478c1bSAl Viro  * The exception fixup information "just so happens" to be arranged
18b5478c1bSAl Viro  * as in a MEM format instruction.  This lets us emit our three
19b5478c1bSAl Viro  * values like so:
20b5478c1bSAl Viro  *
21b5478c1bSAl Viro  *      lda valreg, nextinsn(errreg)
22b5478c1bSAl Viro  *
23b5478c1bSAl Viro  */
24b5478c1bSAl Viro 
25b5478c1bSAl Viro struct exception_table_entry
26b5478c1bSAl Viro {
27b5478c1bSAl Viro 	signed int insn;
28b5478c1bSAl Viro 	union exception_fixup {
29b5478c1bSAl Viro 		unsigned unit;
30b5478c1bSAl Viro 		struct {
31b5478c1bSAl Viro 			signed int nextinsn : 16;
32b5478c1bSAl Viro 			unsigned int errreg : 5;
33b5478c1bSAl Viro 			unsigned int valreg : 5;
34b5478c1bSAl Viro 		} bits;
35b5478c1bSAl Viro 	} fixup;
36b5478c1bSAl Viro };
37b5478c1bSAl Viro 
38b5478c1bSAl Viro /* Returns the new pc */
39b5478c1bSAl Viro #define fixup_exception(map_reg, _fixup, pc)			\
40b5478c1bSAl Viro ({								\
41b5478c1bSAl Viro 	if ((_fixup)->fixup.bits.valreg != 31)			\
42b5478c1bSAl Viro 		map_reg((_fixup)->fixup.bits.valreg) = 0;	\
43b5478c1bSAl Viro 	if ((_fixup)->fixup.bits.errreg != 31)			\
44b5478c1bSAl Viro 		map_reg((_fixup)->fixup.bits.errreg) = -EFAULT;	\
45b5478c1bSAl Viro 	(pc) + (_fixup)->fixup.bits.nextinsn;			\
46b5478c1bSAl Viro })
47b5478c1bSAl Viro 
48b5478c1bSAl Viro #define ARCH_HAS_RELATIVE_EXTABLE
49b5478c1bSAl Viro 
50b5478c1bSAl Viro #define swap_ex_entry_fixup(a, b, tmp, delta)			\
51b5478c1bSAl Viro 	do {							\
52b5478c1bSAl Viro 		(a)->fixup.unit = (b)->fixup.unit;		\
53b5478c1bSAl Viro 		(b)->fixup.unit = (tmp).fixup.unit;		\
54b5478c1bSAl Viro 	} while (0)
55b5478c1bSAl Viro 
56b5478c1bSAl Viro #endif
57