Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
1/* SPDX-License-Identifier: GPL-2.0-only */
2#ifndef __ASM_ASM_EXTABLE_H
3#define __ASM_ASM_EXTABLE_H
4
5#include <linux/bits.h>
6#include <asm/gpr-num.h>
7
8#define EX_TYPE_NONE 0
9#define EX_TYPE_BPF 1
10#define EX_TYPE_UACCESS_ERR_ZERO 2
11#define EX_TYPE_KACCESS_ERR_ZERO 3
12#define EX_TYPE_UACCESS_CPY 4
13#define EX_TYPE_LOAD_UNALIGNED_ZEROPAD 5
14
15/* Data fields for EX_TYPE_UACCESS_ERR_ZERO */
16#define EX_DATA_REG_ERR_SHIFT 0
17#define EX_DATA_REG_ERR GENMASK(4, 0)
18#define EX_DATA_REG_ZERO_SHIFT 5
19#define EX_DATA_REG_ZERO GENMASK(9, 5)
20
21/* Data fields for EX_TYPE_LOAD_UNALIGNED_ZEROPAD */
22#define EX_DATA_REG_DATA_SHIFT 0
23#define EX_DATA_REG_DATA GENMASK(4, 0)
24#define EX_DATA_REG_ADDR_SHIFT 5
25#define EX_DATA_REG_ADDR GENMASK(9, 5)
26
27/* Data fields for EX_TYPE_UACCESS_CPY */
28#define EX_DATA_UACCESS_WRITE BIT(0)
29
30#ifdef __ASSEMBLER__
31
32#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
33 .pushsection __ex_table, "a"; \
34 .align 2; \
35 .long ((insn) - .); \
36 .long ((fixup) - .); \
37 .short (type); \
38 .short (data); \
39 .popsection;
40
41#define EX_DATA_REG(reg, gpr) \
42 (.L__gpr_num_##gpr << EX_DATA_REG_##reg##_SHIFT)
43
44#define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \
45 __ASM_EXTABLE_RAW(insn, fixup, \
46 EX_TYPE_UACCESS_ERR_ZERO, \
47 ( \
48 EX_DATA_REG(ERR, err) | \
49 EX_DATA_REG(ZERO, zero) \
50 ))
51
52#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \
53 _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, wzr)
54
55#define _ASM_EXTABLE_UACCESS(insn, fixup) \
56 _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
57
58/*
59 * Create an exception table entry for uaccess `insn`, which will branch to `fixup`
60 * when an unhandled fault is taken.
61 */
62 .macro _asm_extable_uaccess, insn, fixup
63 _ASM_EXTABLE_UACCESS(\insn, \fixup)
64 .endm
65
66/*
67 * Create an exception table entry for `insn` if `fixup` is provided. Otherwise
68 * do nothing.
69 */
70 .macro _cond_uaccess_extable, insn, fixup
71 .ifnc \fixup,
72 _asm_extable_uaccess \insn, \fixup
73 .endif
74 .endm
75
76 .macro _asm_extable_uaccess_cpy, insn, fixup, uaccess_is_write
77 __ASM_EXTABLE_RAW(\insn, \fixup, EX_TYPE_UACCESS_CPY, \uaccess_is_write)
78 .endm
79
80#else /* __ASSEMBLER__ */
81
82#include <linux/stringify.h>
83
84#define __ASM_EXTABLE_RAW(insn, fixup, type, data) \
85 ".pushsection __ex_table, \"a\"\n" \
86 ".align 2\n" \
87 ".long ((" insn ") - .)\n" \
88 ".long ((" fixup ") - .)\n" \
89 ".short (" type ")\n" \
90 ".short (" data ")\n" \
91 ".popsection\n"
92
93#define EX_DATA_REG(reg, gpr) \
94 "((.L__gpr_num_" #gpr ") << " __stringify(EX_DATA_REG_##reg##_SHIFT) ")"
95
96#define _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, zero) \
97 __DEFINE_ASM_GPR_NUMS \
98 __ASM_EXTABLE_RAW(#insn, #fixup, \
99 __stringify(EX_TYPE_UACCESS_ERR_ZERO), \
100 "(" \
101 EX_DATA_REG(ERR, err) " | " \
102 EX_DATA_REG(ZERO, zero) \
103 ")")
104
105#define _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, zero) \
106 __DEFINE_ASM_GPR_NUMS \
107 __ASM_EXTABLE_RAW(#insn, #fixup, \
108 __stringify(EX_TYPE_KACCESS_ERR_ZERO), \
109 "(" \
110 EX_DATA_REG(ERR, err) " | " \
111 EX_DATA_REG(ZERO, zero) \
112 ")")
113
114#define _ASM_EXTABLE_UACCESS_ERR(insn, fixup, err) \
115 _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, err, wzr)
116
117#define _ASM_EXTABLE_UACCESS(insn, fixup) \
118 _ASM_EXTABLE_UACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
119
120#define _ASM_EXTABLE_KACCESS_ERR(insn, fixup, err) \
121 _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, err, wzr)
122
123#define _ASM_EXTABLE_KACCESS(insn, fixup) \
124 _ASM_EXTABLE_KACCESS_ERR_ZERO(insn, fixup, wzr, wzr)
125
126#define _ASM_EXTABLE_LOAD_UNALIGNED_ZEROPAD(insn, fixup, data, addr) \
127 __DEFINE_ASM_GPR_NUMS \
128 __ASM_EXTABLE_RAW(#insn, #fixup, \
129 __stringify(EX_TYPE_LOAD_UNALIGNED_ZEROPAD), \
130 "(" \
131 EX_DATA_REG(DATA, data) " | " \
132 EX_DATA_REG(ADDR, addr) \
133 ")")
134
135#endif /* __ASSEMBLER__ */
136
137#endif /* __ASM_ASM_EXTABLE_H */