forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 9999e48639b3cecb08ffb37358bcba3b48161b29
kernel/arch/x86/mm/extable.c
....@@ -1,14 +1,17 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 #include <linux/extable.h>
23 #include <linux/uaccess.h>
34 #include <linux/sched/debug.h>
45 #include <xen/xen.h>
56
67 #include <asm/fpu/internal.h>
8
+#include <asm/sev-es.h>
79 #include <asm/traps.h>
810 #include <asm/kdebug.h>
911
1012 typedef bool (*ex_handler_t)(const struct exception_table_entry *,
11
- struct pt_regs *, int);
13
+ struct pt_regs *, int, unsigned long,
14
+ unsigned long);
1215
1316 static inline unsigned long
1417 ex_fixup_addr(const struct exception_table_entry *x)
....@@ -22,7 +25,9 @@
2225 }
2326
2427 __visible bool ex_handler_default(const struct exception_table_entry *fixup,
25
- struct pt_regs *regs, int trapnr)
28
+ struct pt_regs *regs, int trapnr,
29
+ unsigned long error_code,
30
+ unsigned long fault_addr)
2631 {
2732 regs->ip = ex_fixup_addr(fixup);
2833 return true;
....@@ -30,60 +35,15 @@
3035 EXPORT_SYMBOL(ex_handler_default);
3136
3237 __visible bool ex_handler_fault(const struct exception_table_entry *fixup,
33
- struct pt_regs *regs, int trapnr)
38
+ struct pt_regs *regs, int trapnr,
39
+ unsigned long error_code,
40
+ unsigned long fault_addr)
3441 {
3542 regs->ip = ex_fixup_addr(fixup);
3643 regs->ax = trapnr;
3744 return true;
3845 }
3946 EXPORT_SYMBOL_GPL(ex_handler_fault);
40
-
41
-/*
42
- * Handler for UD0 exception following a failed test against the
43
- * result of a refcount inc/dec/add/sub.
44
- */
45
-__visible bool ex_handler_refcount(const struct exception_table_entry *fixup,
46
- struct pt_regs *regs, int trapnr)
47
-{
48
- /* First unconditionally saturate the refcount. */
49
- *(int *)regs->cx = INT_MIN / 2;
50
-
51
- /*
52
- * Strictly speaking, this reports the fixup destination, not
53
- * the fault location, and not the actually overflowing
54
- * instruction, which is the instruction before the "js", but
55
- * since that instruction could be a variety of lengths, just
56
- * report the location after the overflow, which should be close
57
- * enough for finding the overflow, as it's at least back in
58
- * the function, having returned from .text.unlikely.
59
- */
60
- regs->ip = ex_fixup_addr(fixup);
61
-
62
- /*
63
- * This function has been called because either a negative refcount
64
- * value was seen by any of the refcount functions, or a zero
65
- * refcount value was seen by refcount_dec().
66
- *
67
- * If we crossed from INT_MAX to INT_MIN, OF (Overflow Flag: result
68
- * wrapped around) will be set. Additionally, seeing the refcount
69
- * reach 0 will set ZF (Zero Flag: result was zero). In each of
70
- * these cases we want a report, since it's a boundary condition.
71
- * The SF case is not reported since it indicates post-boundary
72
- * manipulations below zero or above INT_MAX. And if none of the
73
- * flags are set, something has gone very wrong, so report it.
74
- */
75
- if (regs->flags & (X86_EFLAGS_OF | X86_EFLAGS_ZF)) {
76
- bool zero = regs->flags & X86_EFLAGS_ZF;
77
-
78
- refcount_error_report(regs, zero ? "hit zero" : "overflow");
79
- } else if ((regs->flags & X86_EFLAGS_SF) == 0) {
80
- /* Report if none of OF, ZF, nor SF are set. */
81
- refcount_error_report(regs, "unexpected saturation");
82
- }
83
-
84
- return true;
85
-}
86
-EXPORT_SYMBOL(ex_handler_refcount);
8747
8848 /*
8949 * Handler for when we fail to restore a task's FPU state. We should never get
....@@ -96,7 +56,9 @@
9656 * out all the FPU registers) if we can't restore from the task's FPU state.
9757 */
9858 __visible bool ex_handler_fprestore(const struct exception_table_entry *fixup,
99
- struct pt_regs *regs, int trapnr)
59
+ struct pt_regs *regs, int trapnr,
60
+ unsigned long error_code,
61
+ unsigned long fault_addr)
10062 {
10163 regs->ip = ex_fixup_addr(fixup);
10264
....@@ -108,20 +70,35 @@
10870 }
10971 EXPORT_SYMBOL_GPL(ex_handler_fprestore);
11072
111
-__visible bool ex_handler_ext(const struct exception_table_entry *fixup,
112
- struct pt_regs *regs, int trapnr)
73
+__visible bool ex_handler_uaccess(const struct exception_table_entry *fixup,
74
+ struct pt_regs *regs, int trapnr,
75
+ unsigned long error_code,
76
+ unsigned long fault_addr)
11377 {
114
- /* Special hack for uaccess_err */
115
- current->thread.uaccess_err = 1;
78
+ WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
11679 regs->ip = ex_fixup_addr(fixup);
11780 return true;
11881 }
119
-EXPORT_SYMBOL(ex_handler_ext);
82
+EXPORT_SYMBOL(ex_handler_uaccess);
83
+
84
+__visible bool ex_handler_copy(const struct exception_table_entry *fixup,
85
+ struct pt_regs *regs, int trapnr,
86
+ unsigned long error_code,
87
+ unsigned long fault_addr)
88
+{
89
+ WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?");
90
+ regs->ip = ex_fixup_addr(fixup);
91
+ regs->ax = trapnr;
92
+ return true;
93
+}
94
+EXPORT_SYMBOL(ex_handler_copy);
12095
12196 __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup,
122
- struct pt_regs *regs, int trapnr)
97
+ struct pt_regs *regs, int trapnr,
98
+ unsigned long error_code,
99
+ unsigned long fault_addr)
123100 {
124
- if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pF)\n",
101
+ if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n",
125102 (unsigned int)regs->cx, regs->ip, (void *)regs->ip))
126103 show_stack_regs(regs);
127104
....@@ -134,9 +111,11 @@
134111 EXPORT_SYMBOL(ex_handler_rdmsr_unsafe);
135112
136113 __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup,
137
- struct pt_regs *regs, int trapnr)
114
+ struct pt_regs *regs, int trapnr,
115
+ unsigned long error_code,
116
+ unsigned long fault_addr)
138117 {
139
- if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pF)\n",
118
+ if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n",
140119 (unsigned int)regs->cx, (unsigned int)regs->dx,
141120 (unsigned int)regs->ax, regs->ip, (void *)regs->ip))
142121 show_stack_regs(regs);
....@@ -148,30 +127,37 @@
148127 EXPORT_SYMBOL(ex_handler_wrmsr_unsafe);
149128
150129 __visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup,
151
- struct pt_regs *regs, int trapnr)
130
+ struct pt_regs *regs, int trapnr,
131
+ unsigned long error_code,
132
+ unsigned long fault_addr)
152133 {
153134 if (static_cpu_has(X86_BUG_NULL_SEG))
154135 asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS));
155136 asm volatile ("mov %0, %%fs" : : "rm" (0));
156
- return ex_handler_default(fixup, regs, trapnr);
137
+ return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr);
157138 }
158139 EXPORT_SYMBOL(ex_handler_clear_fs);
159140
160
-__visible bool ex_has_fault_handler(unsigned long ip)
141
+enum handler_type ex_get_fault_handler_type(unsigned long ip)
161142 {
162143 const struct exception_table_entry *e;
163144 ex_handler_t handler;
164145
165146 e = search_exception_tables(ip);
166147 if (!e)
167
- return false;
148
+ return EX_HANDLER_NONE;
168149 handler = ex_fixup_handler(e);
169
-
170
- return handler == ex_handler_fault;
150
+ if (handler == ex_handler_fault)
151
+ return EX_HANDLER_FAULT;
152
+ else if (handler == ex_handler_uaccess || handler == ex_handler_copy)
153
+ return EX_HANDLER_UACCESS;
154
+ else
155
+ return EX_HANDLER_OTHER;
171156 }
172157
173158 __nocfi
174
-int fixup_exception(struct pt_regs *regs, int trapnr)
159
+int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code,
160
+ unsigned long fault_addr)
175161 {
176162 const struct exception_table_entry *e;
177163 ex_handler_t handler;
....@@ -195,7 +181,7 @@
195181 return 0;
196182
197183 handler = ex_fixup_handler(e);
198
- return handler(e, regs, trapnr);
184
+ return handler(e, regs, trapnr, error_code, fault_addr);
199185 }
200186
201187 extern unsigned int early_recursion_flag;
....@@ -231,13 +217,24 @@
231217 * result in a hard-to-debug panic.
232218 *
233219 * Keep in mind that not all vectors actually get here. Early
234
- * fage faults, for example, are special.
220
+ * page faults, for example, are special.
235221 */
236
- if (fixup_exception(regs, trapnr))
222
+ if (fixup_exception(regs, trapnr, regs->orig_ax, 0))
237223 return;
238224
239
- if (fixup_bug(regs, trapnr))
240
- return;
225
+ if (trapnr == X86_TRAP_UD) {
226
+ if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) {
227
+ /* Skip the ud2. */
228
+ regs->ip += LEN_UD2;
229
+ return;
230
+ }
231
+
232
+ /*
233
+ * If this was a BUG and report_bug returns or if this
234
+ * was just a normal #UD, we want to continue onward and
235
+ * crash.
236
+ */
237
+ }
241238
242239 fail:
243240 early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n",