]> git.proxmox.com Git - pve-kernel.git/blame - patches/kernel/0029-x86-xen-Get-rid-of-paravirt-op-adjust_exception_fram.patch
build: reformat existing patches
[pve-kernel.git] / patches / kernel / 0029-x86-xen-Get-rid-of-paravirt-op-adjust_exception_fram.patch
CommitLineData
59d5af67 1From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
321d628a
FG
2From: Juergen Gross <jgross@suse.com>
3Date: Thu, 31 Aug 2017 19:42:49 +0200
59d5af67 4Subject: [PATCH] x86/xen: Get rid of paravirt op adjust_exception_frame
321d628a
FG
5MIME-Version: 1.0
6Content-Type: text/plain; charset=UTF-8
7Content-Transfer-Encoding: 8bit
8
9CVE-2017-5754
10
11When running as Xen pv-guest the exception frame on the stack contains
12%r11 and %rcx additional to the other data pushed by the processor.
13
14Instead of having a paravirt op being called for each exception type
15prepend the Xen specific code to each exception entry. When running as
16Xen pv-guest just use the exception entry with prepended instructions,
17otherwise use the entry without the Xen specific code.
18
19[ tglx: Merged through tip to avoid ugly merge conflict ]
20
21Signed-off-by: Juergen Gross <jgross@suse.com>
22Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
23Cc: xen-devel@lists.xenproject.org
24Cc: boris.ostrovsky@oracle.com
25Cc: luto@amacapital.net
26Link: http://lkml.kernel.org/r/20170831174249.26853-1-jg@pfupf.net
27(backported from commit 5878d5d6fdef6447d73b0acc121ba445bef37f53)
28Signed-off-by: Andy Whitcroft <apw@canonical.com>
29Signed-off-by: Kleber Sacilotto de Souza <kleber.souza@canonical.com>
30(cherry picked from commit 9a6fb927deb3ebbe831741ca82081714637181a7)
31Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
32---
33 arch/x86/include/asm/paravirt.h | 5 --
34 arch/x86/include/asm/paravirt_types.h | 3 --
35 arch/x86/include/asm/proto.h | 3 ++
36 arch/x86/include/asm/traps.h | 28 ++++++++--
37 arch/x86/xen/xen-ops.h | 1 -
38 arch/x86/kernel/asm-offsets_64.c | 1 -
39 arch/x86/kernel/paravirt.c | 3 --
40 arch/x86/xen/enlighten_pv.c | 98 +++++++++++++++++++++++------------
41 arch/x86/xen/irq.c | 3 --
42 arch/x86/entry/entry_64.S | 23 ++------
43 arch/x86/entry/entry_64_compat.S | 1 -
44 arch/x86/xen/xen-asm_64.S | 41 +++++++++++++--
45 12 files changed, 133 insertions(+), 77 deletions(-)
46
47diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h
48index 9ccac1926587..c25dd22f7c70 100644
49--- a/arch/x86/include/asm/paravirt.h
50+++ b/arch/x86/include/asm/paravirt.h
51@@ -960,11 +960,6 @@ extern void default_banner(void);
52 #define GET_CR2_INTO_RAX \
53 call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2)
54
55-#define PARAVIRT_ADJUST_EXCEPTION_FRAME \
56- PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_adjust_exception_frame), \
57- CLBR_NONE, \
58- call PARA_INDIRECT(pv_irq_ops+PV_IRQ_adjust_exception_frame))
59-
60 #define USERGS_SYSRET64 \
61 PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
62 CLBR_NONE, \
63diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h
64index 9ffc36bfe4cd..6b64fc6367f2 100644
65--- a/arch/x86/include/asm/paravirt_types.h
66+++ b/arch/x86/include/asm/paravirt_types.h
67@@ -196,9 +196,6 @@ struct pv_irq_ops {
68 void (*safe_halt)(void);
69 void (*halt)(void);
70
71-#ifdef CONFIG_X86_64
72- void (*adjust_exception_frame)(void);
73-#endif
74 } __no_randomize_layout;
75
76 struct pv_mmu_ops {
77diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h
78index 8d3964fc5f91..b408b1886195 100644
79--- a/arch/x86/include/asm/proto.h
80+++ b/arch/x86/include/asm/proto.h
81@@ -24,6 +24,9 @@ void entry_SYSENTER_compat(void);
82 void __end_entry_SYSENTER_compat(void);
83 void entry_SYSCALL_compat(void);
84 void entry_INT80_compat(void);
85+#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
86+void xen_entry_INT80_compat(void);
87+#endif
88 #endif
89
90 void x86_configure_nx(void);
91diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h
92index b4f322d6c95f..feb89dbe359d 100644
93--- a/arch/x86/include/asm/traps.h
94+++ b/arch/x86/include/asm/traps.h
95@@ -13,9 +13,6 @@ asmlinkage void divide_error(void);
96 asmlinkage void debug(void);
97 asmlinkage void nmi(void);
98 asmlinkage void int3(void);
99-asmlinkage void xen_debug(void);
100-asmlinkage void xen_int3(void);
101-asmlinkage void xen_stack_segment(void);
102 asmlinkage void overflow(void);
103 asmlinkage void bounds(void);
104 asmlinkage void invalid_op(void);
105@@ -56,6 +53,31 @@ asmlinkage void simd_coprocessor_error(void);
106 #define trace_page_fault page_fault
107 #endif
108
109+#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
110+asmlinkage void xen_divide_error(void);
111+asmlinkage void xen_xendebug(void);
112+asmlinkage void xen_xenint3(void);
113+asmlinkage void xen_nmi(void);
114+asmlinkage void xen_overflow(void);
115+asmlinkage void xen_bounds(void);
116+asmlinkage void xen_invalid_op(void);
117+asmlinkage void xen_device_not_available(void);
118+asmlinkage void xen_double_fault(void);
119+asmlinkage void xen_coprocessor_segment_overrun(void);
120+asmlinkage void xen_invalid_TSS(void);
121+asmlinkage void xen_segment_not_present(void);
122+asmlinkage void xen_stack_segment(void);
123+asmlinkage void xen_general_protection(void);
124+asmlinkage void xen_page_fault(void);
125+asmlinkage void xen_spurious_interrupt_bug(void);
126+asmlinkage void xen_coprocessor_error(void);
127+asmlinkage void xen_alignment_check(void);
128+#ifdef CONFIG_X86_MCE
129+asmlinkage void xen_machine_check(void);
130+#endif /* CONFIG_X86_MCE */
131+asmlinkage void xen_simd_coprocessor_error(void);
132+#endif
133+
134 dotraplinkage void do_divide_error(struct pt_regs *, long);
135 dotraplinkage void do_debug(struct pt_regs *, long);
136 dotraplinkage void do_nmi(struct pt_regs *, long);
137diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h
138index 70301ac0d414..c8a6d224f7ed 100644
139--- a/arch/x86/xen/xen-ops.h
140+++ b/arch/x86/xen/xen-ops.h
141@@ -138,7 +138,6 @@ __visible void xen_restore_fl_direct(unsigned long);
142 __visible void xen_iret(void);
143 __visible void xen_sysret32(void);
144 __visible void xen_sysret64(void);
145-__visible void xen_adjust_exception_frame(void);
146
147 extern int xen_panic_handler_init(void);
148
149diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c
150index 99332f550c48..cf42206926af 100644
151--- a/arch/x86/kernel/asm-offsets_64.c
152+++ b/arch/x86/kernel/asm-offsets_64.c
153@@ -20,7 +20,6 @@ static char syscalls_ia32[] = {
154 int main(void)
155 {
156 #ifdef CONFIG_PARAVIRT
157- OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame);
158 OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64);
159 OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
160 BLANK();
161diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c
162index bc0a849589bb..a14df9eecfed 100644
163--- a/arch/x86/kernel/paravirt.c
164+++ b/arch/x86/kernel/paravirt.c
165@@ -319,9 +319,6 @@ __visible struct pv_irq_ops pv_irq_ops = {
166 .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable),
167 .safe_halt = native_safe_halt,
168 .halt = native_halt,
169-#ifdef CONFIG_X86_64
170- .adjust_exception_frame = paravirt_nop,
171-#endif
172 };
173
174 __visible struct pv_cpu_ops pv_cpu_ops = {
175diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c
176index c76f5ff4d0d7..ae2a2e2d6362 100644
177--- a/arch/x86/xen/enlighten_pv.c
178+++ b/arch/x86/xen/enlighten_pv.c
179@@ -586,6 +586,70 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
180 preempt_enable();
181 }
182
183+#ifdef CONFIG_X86_64
184+struct trap_array_entry {
185+ void (*orig)(void);
186+ void (*xen)(void);
187+ bool ist_okay;
188+};
189+
190+static struct trap_array_entry trap_array[] = {
191+ { debug, xen_xendebug, true },
192+ { int3, xen_xenint3, true },
193+ { double_fault, xen_double_fault, true },
194+#ifdef CONFIG_X86_MCE
195+ { machine_check, xen_machine_check, true },
196+#endif
197+ { nmi, xen_nmi, true },
198+ { overflow, xen_overflow, false },
199+#ifdef CONFIG_IA32_EMULATION
200+ { entry_INT80_compat, xen_entry_INT80_compat, false },
201+#endif
202+ { page_fault, xen_page_fault, false },
203+ { divide_error, xen_divide_error, false },
204+ { bounds, xen_bounds, false },
205+ { invalid_op, xen_invalid_op, false },
206+ { device_not_available, xen_device_not_available, false },
207+ { coprocessor_segment_overrun, xen_coprocessor_segment_overrun, false },
208+ { invalid_TSS, xen_invalid_TSS, false },
209+ { segment_not_present, xen_segment_not_present, false },
210+ { stack_segment, xen_stack_segment, false },
211+ { general_protection, xen_general_protection, false },
212+ { spurious_interrupt_bug, xen_spurious_interrupt_bug, false },
213+ { coprocessor_error, xen_coprocessor_error, false },
214+ { alignment_check, xen_alignment_check, false },
215+ { simd_coprocessor_error, xen_simd_coprocessor_error, false },
216+};
217+
218+static bool get_trap_addr(void **addr, unsigned int ist)
219+{
220+ unsigned int nr;
221+ bool ist_okay = false;
222+
223+ /*
224+ * Replace trap handler addresses by Xen specific ones.
225+ * Check for known traps using IST and whitelist them.
226+ * The debugger ones are the only ones we care about.
227+ * Xen will handle faults like double_fault, * so we should never see
228+ * them. Warn if there's an unexpected IST-using fault handler.
229+ */
230+ for (nr = 0; nr < ARRAY_SIZE(trap_array); nr++) {
231+ struct trap_array_entry *entry = trap_array + nr;
232+
233+ if (*addr == entry->orig) {
234+ *addr = entry->xen;
235+ ist_okay = entry->ist_okay;
236+ break;
237+ }
238+ }
239+
240+ if (WARN_ON(ist != 0 && !ist_okay))
241+ return false;
242+
243+ return true;
244+}
245+#endif
246+
247 static int cvt_gate_to_trap(int vector, const gate_desc *val,
248 struct trap_info *info)
249 {
250@@ -598,40 +662,8 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
251
252 addr = gate_offset(val);
253 #ifdef CONFIG_X86_64
254- /*
255- * Look for known traps using IST, and substitute them
256- * appropriately. The debugger ones are the only ones we care
257- * about. Xen will handle faults like double_fault,
258- * so we should never see them. Warn if
259- * there's an unexpected IST-using fault handler.
260- */
261- if (addr == (unsigned long)debug)
262- addr = (unsigned long)xen_debug;
263- else if (addr == (unsigned long)int3)
264- addr = (unsigned long)xen_int3;
265- else if (addr == (unsigned long)stack_segment)
266- addr = (unsigned long)xen_stack_segment;
267- else if (addr == (unsigned long)double_fault) {
268- /* Don't need to handle these */
269+ if (!get_trap_addr((void **)&addr, val->bits.ist))
270 return 0;
271-#ifdef CONFIG_X86_MCE
272- } else if (addr == (unsigned long)machine_check) {
273- /*
274- * when xen hypervisor inject vMCE to guest,
275- * use native mce handler to handle it
276- */
277- ;
278-#endif
279- } else if (addr == (unsigned long)nmi)
280- /*
281- * Use the native version as well.
282- */
283- ;
284- else {
285- /* Some other trap using IST? */
286- if (WARN_ON(val->bits.ist != 0))
287- return 0;
288- }
289 #endif /* CONFIG_X86_64 */
290 info->address = addr;
291
292diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c
293index 33e92955e09d..d4eff5676cfa 100644
294--- a/arch/x86/xen/irq.c
295+++ b/arch/x86/xen/irq.c
296@@ -123,9 +123,6 @@ static const struct pv_irq_ops xen_irq_ops __initconst = {
297
298 .safe_halt = xen_safe_halt,
299 .halt = xen_halt,
300-#ifdef CONFIG_X86_64
301- .adjust_exception_frame = xen_adjust_exception_frame,
302-#endif
303 };
304
305 void __init xen_init_irq_ops(void)
306diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
307index dfabcbf8e813..c12260ef3e4b 100644
308--- a/arch/x86/entry/entry_64.S
309+++ b/arch/x86/entry/entry_64.S
310@@ -829,7 +829,6 @@ ENTRY(\sym)
311 .endif
312
313 ASM_CLAC
314- PARAVIRT_ADJUST_EXCEPTION_FRAME
315
316 .ifeq \has_error_code
317 pushq $-1 /* ORIG_RAX: no syscall to restart */
318@@ -975,7 +974,7 @@ ENTRY(do_softirq_own_stack)
319 ENDPROC(do_softirq_own_stack)
320
321 #ifdef CONFIG_XEN
322-idtentry xen_hypervisor_callback xen_do_hypervisor_callback has_error_code=0
323+idtentry hypervisor_callback xen_do_hypervisor_callback has_error_code=0
324
325 /*
326 * A note on the "critical region" in our callback handler.
327@@ -1042,8 +1041,6 @@ ENTRY(xen_failsafe_callback)
328 movq 8(%rsp), %r11
329 addq $0x30, %rsp
330 pushq $0 /* RIP */
331- pushq %r11
332- pushq %rcx
333 UNWIND_HINT_IRET_REGS offset=8
334 jmp general_protection
335 1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
336@@ -1074,9 +1071,8 @@ idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
337 idtentry stack_segment do_stack_segment has_error_code=1
338
339 #ifdef CONFIG_XEN
340-idtentry xen_debug do_debug has_error_code=0
341-idtentry xen_int3 do_int3 has_error_code=0
342-idtentry xen_stack_segment do_stack_segment has_error_code=1
343+idtentry xendebug do_debug has_error_code=0
344+idtentry xenint3 do_int3 has_error_code=0
345 #endif
346
347 idtentry general_protection do_general_protection has_error_code=1
348@@ -1240,20 +1236,9 @@ ENTRY(error_exit)
349 END(error_exit)
350
351 /* Runs on exception stack */
352+/* XXX: broken on Xen PV */
353 ENTRY(nmi)
354 UNWIND_HINT_IRET_REGS
355- /*
356- * Fix up the exception frame if we're on Xen.
357- * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
358- * one value to the stack on native, so it may clobber the rdx
359- * scratch slot, but it won't clobber any of the important
360- * slots past it.
361- *
362- * Xen is a different story, because the Xen frame itself overlaps
363- * the "NMI executing" variable.
364- */
365- PARAVIRT_ADJUST_EXCEPTION_FRAME
366-
367 /*
368 * We allow breakpoints in NMIs. If a breakpoint occurs, then
369 * the iretq it performs will take us out of NMI context.
370diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
371index 5314d7b8e5ad..d8468ba24be0 100644
372--- a/arch/x86/entry/entry_64_compat.S
373+++ b/arch/x86/entry/entry_64_compat.S
374@@ -293,7 +293,6 @@ ENTRY(entry_INT80_compat)
375 /*
376 * Interrupts are off on entry.
377 */
378- PARAVIRT_ADJUST_EXCEPTION_FRAME
379 ASM_CLAC /* Do this early to minimize exposure */
380 SWAPGS
381
382diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S
383index 3a3b6a211584..dae2cc33afb5 100644
384--- a/arch/x86/xen/xen-asm_64.S
385+++ b/arch/x86/xen/xen-asm_64.S
386@@ -16,11 +16,42 @@
387
388 #include <linux/linkage.h>
389
390-ENTRY(xen_adjust_exception_frame)
391- mov 8+0(%rsp), %rcx
392- mov 8+8(%rsp), %r11
393- ret $16
394-ENDPROC(xen_adjust_exception_frame)
395+.macro xen_pv_trap name
396+ENTRY(xen_\name)
397+ pop %rcx
398+ pop %r11
399+ jmp \name
400+END(xen_\name)
401+.endm
402+
403+xen_pv_trap divide_error
404+xen_pv_trap debug
405+xen_pv_trap xendebug
406+xen_pv_trap int3
407+xen_pv_trap xenint3
408+xen_pv_trap nmi
409+xen_pv_trap overflow
410+xen_pv_trap bounds
411+xen_pv_trap invalid_op
412+xen_pv_trap device_not_available
413+xen_pv_trap double_fault
414+xen_pv_trap coprocessor_segment_overrun
415+xen_pv_trap invalid_TSS
416+xen_pv_trap segment_not_present
417+xen_pv_trap stack_segment
418+xen_pv_trap general_protection
419+xen_pv_trap page_fault
420+xen_pv_trap spurious_interrupt_bug
421+xen_pv_trap coprocessor_error
422+xen_pv_trap alignment_check
423+#ifdef CONFIG_X86_MCE
424+xen_pv_trap machine_check
425+#endif /* CONFIG_X86_MCE */
426+xen_pv_trap simd_coprocessor_error
427+#ifdef CONFIG_IA32_EMULATION
428+xen_pv_trap entry_INT80_compat
429+#endif
430+xen_pv_trap hypervisor_callback
431
432 hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32
433 /*
434--
4352.14.2
436