Skip to content

Commit 5878d5d

Browse files
jgross1KAGA-KOKO
authored andcommitted
x86/xen: Get rid of paravirt op adjust_exception_frame
When running as Xen pv-guest the exception frame on the stack contains %r11 and %rcx additional to the other data pushed by the processor. Instead of having a paravirt op being called for each exception type prepend the Xen specific code to each exception entry. When running as Xen pv-guest just use the exception entry with prepended instructions, otherwise use the entry without the Xen specific code. [ tglx: Merged through tip to avoid ugly merge conflict ] Signed-off-by: Juergen Gross <[email protected]> Signed-off-by: Thomas Gleixner <[email protected]> Cc: [email protected] Cc: [email protected] Cc: [email protected] Link: http://lkml.kernel.org/r/[email protected]
1 parent ef1d4de commit 5878d5d

File tree

12 files changed

+133
-77
lines changed

12 files changed

+133
-77
lines changed

arch/x86/entry/entry_64.S

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -821,7 +821,6 @@ ENTRY(\sym)
821821
.endif
822822

823823
ASM_CLAC
824-
PARAVIRT_ADJUST_EXCEPTION_FRAME
825824

826825
.ifeq \has_error_code
827826
pushq $-1 /* ORIG_RAX: no syscall to restart */
@@ -967,7 +966,7 @@ ENTRY(do_softirq_own_stack)
967966
ENDPROC(do_softirq_own_stack)
968967

969968
#ifdef CONFIG_XEN
970-
idtentry xen_hypervisor_callback xen_do_hypervisor_callback has_error_code=0
969+
idtentry hypervisor_callback xen_do_hypervisor_callback has_error_code=0
971970

972971
/*
973972
* A note on the "critical region" in our callback handler.
@@ -1034,8 +1033,6 @@ ENTRY(xen_failsafe_callback)
10341033
movq 8(%rsp), %r11
10351034
addq $0x30, %rsp
10361035
pushq $0 /* RIP */
1037-
pushq %r11
1038-
pushq %rcx
10391036
UNWIND_HINT_IRET_REGS offset=8
10401037
jmp general_protection
10411038
1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */
@@ -1066,9 +1063,8 @@ idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK
10661063
idtentry stack_segment do_stack_segment has_error_code=1
10671064

10681065
#ifdef CONFIG_XEN
1069-
idtentry xen_debug do_debug has_error_code=0
1070-
idtentry xen_int3 do_int3 has_error_code=0
1071-
idtentry xen_stack_segment do_stack_segment has_error_code=1
1066+
idtentry xendebug do_debug has_error_code=0
1067+
idtentry xenint3 do_int3 has_error_code=0
10721068
#endif
10731069

10741070
idtentry general_protection do_general_protection has_error_code=1
@@ -1232,20 +1228,9 @@ ENTRY(error_exit)
12321228
END(error_exit)
12331229

12341230
/* Runs on exception stack */
1231+
/* XXX: broken on Xen PV */
12351232
ENTRY(nmi)
12361233
UNWIND_HINT_IRET_REGS
1237-
/*
1238-
* Fix up the exception frame if we're on Xen.
1239-
* PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most
1240-
* one value to the stack on native, so it may clobber the rdx
1241-
* scratch slot, but it won't clobber any of the important
1242-
* slots past it.
1243-
*
1244-
* Xen is a different story, because the Xen frame itself overlaps
1245-
* the "NMI executing" variable.
1246-
*/
1247-
PARAVIRT_ADJUST_EXCEPTION_FRAME
1248-
12491234
/*
12501235
* We allow breakpoints in NMIs. If a breakpoint occurs, then
12511236
* the iretq it performs will take us out of NMI context.

arch/x86/entry/entry_64_compat.S

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,6 @@ ENTRY(entry_INT80_compat)
293293
/*
294294
* Interrupts are off on entry.
295295
*/
296-
PARAVIRT_ADJUST_EXCEPTION_FRAME
297296
ASM_CLAC /* Do this early to minimize exposure */
298297
SWAPGS
299298

arch/x86/include/asm/paravirt.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -960,11 +960,6 @@ extern void default_banner(void);
960960
#define GET_CR2_INTO_RAX \
961961
call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2)
962962

963-
#define PARAVIRT_ADJUST_EXCEPTION_FRAME \
964-
PARA_SITE(PARA_PATCH(pv_irq_ops, PV_IRQ_adjust_exception_frame), \
965-
CLBR_NONE, \
966-
call PARA_INDIRECT(pv_irq_ops+PV_IRQ_adjust_exception_frame))
967-
968963
#define USERGS_SYSRET64 \
969964
PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \
970965
CLBR_NONE, \

arch/x86/include/asm/paravirt_types.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,9 +196,6 @@ struct pv_irq_ops {
196196
void (*safe_halt)(void);
197197
void (*halt)(void);
198198

199-
#ifdef CONFIG_X86_64
200-
void (*adjust_exception_frame)(void);
201-
#endif
202199
} __no_randomize_layout;
203200

204201
struct pv_mmu_ops {

arch/x86/include/asm/proto.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ void entry_SYSENTER_compat(void);
2424
void __end_entry_SYSENTER_compat(void);
2525
void entry_SYSCALL_compat(void);
2626
void entry_INT80_compat(void);
27+
#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
28+
void xen_entry_INT80_compat(void);
29+
#endif
2730
#endif
2831

2932
void x86_configure_nx(void);

arch/x86/include/asm/traps.h

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,6 @@ asmlinkage void divide_error(void);
1313
asmlinkage void debug(void);
1414
asmlinkage void nmi(void);
1515
asmlinkage void int3(void);
16-
asmlinkage void xen_debug(void);
17-
asmlinkage void xen_int3(void);
18-
asmlinkage void xen_stack_segment(void);
1916
asmlinkage void overflow(void);
2017
asmlinkage void bounds(void);
2118
asmlinkage void invalid_op(void);
@@ -38,6 +35,31 @@ asmlinkage void machine_check(void);
3835
#endif /* CONFIG_X86_MCE */
3936
asmlinkage void simd_coprocessor_error(void);
4037

38+
#if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV)
39+
asmlinkage void xen_divide_error(void);
40+
asmlinkage void xen_xendebug(void);
41+
asmlinkage void xen_xenint3(void);
42+
asmlinkage void xen_nmi(void);
43+
asmlinkage void xen_overflow(void);
44+
asmlinkage void xen_bounds(void);
45+
asmlinkage void xen_invalid_op(void);
46+
asmlinkage void xen_device_not_available(void);
47+
asmlinkage void xen_double_fault(void);
48+
asmlinkage void xen_coprocessor_segment_overrun(void);
49+
asmlinkage void xen_invalid_TSS(void);
50+
asmlinkage void xen_segment_not_present(void);
51+
asmlinkage void xen_stack_segment(void);
52+
asmlinkage void xen_general_protection(void);
53+
asmlinkage void xen_page_fault(void);
54+
asmlinkage void xen_spurious_interrupt_bug(void);
55+
asmlinkage void xen_coprocessor_error(void);
56+
asmlinkage void xen_alignment_check(void);
57+
#ifdef CONFIG_X86_MCE
58+
asmlinkage void xen_machine_check(void);
59+
#endif /* CONFIG_X86_MCE */
60+
asmlinkage void xen_simd_coprocessor_error(void);
61+
#endif
62+
4163
dotraplinkage void do_divide_error(struct pt_regs *, long);
4264
dotraplinkage void do_debug(struct pt_regs *, long);
4365
dotraplinkage void do_nmi(struct pt_regs *, long);

arch/x86/kernel/asm-offsets_64.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ static char syscalls_ia32[] = {
2020
int main(void)
2121
{
2222
#ifdef CONFIG_PARAVIRT
23-
OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame);
2423
OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64);
2524
OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
2625
BLANK();

arch/x86/kernel/paravirt.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -319,9 +319,6 @@ __visible struct pv_irq_ops pv_irq_ops = {
319319
.irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable),
320320
.safe_halt = native_safe_halt,
321321
.halt = native_halt,
322-
#ifdef CONFIG_X86_64
323-
.adjust_exception_frame = paravirt_nop,
324-
#endif
325322
};
326323

327324
__visible struct pv_cpu_ops pv_cpu_ops = {

arch/x86/xen/enlighten_pv.c

Lines changed: 65 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -579,6 +579,70 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum,
579579
preempt_enable();
580580
}
581581

582+
#ifdef CONFIG_X86_64
583+
struct trap_array_entry {
584+
void (*orig)(void);
585+
void (*xen)(void);
586+
bool ist_okay;
587+
};
588+
589+
static struct trap_array_entry trap_array[] = {
590+
{ debug, xen_xendebug, true },
591+
{ int3, xen_xenint3, true },
592+
{ double_fault, xen_double_fault, true },
593+
#ifdef CONFIG_X86_MCE
594+
{ machine_check, xen_machine_check, true },
595+
#endif
596+
{ nmi, xen_nmi, true },
597+
{ overflow, xen_overflow, false },
598+
#ifdef CONFIG_IA32_EMULATION
599+
{ entry_INT80_compat, xen_entry_INT80_compat, false },
600+
#endif
601+
{ page_fault, xen_page_fault, false },
602+
{ divide_error, xen_divide_error, false },
603+
{ bounds, xen_bounds, false },
604+
{ invalid_op, xen_invalid_op, false },
605+
{ device_not_available, xen_device_not_available, false },
606+
{ coprocessor_segment_overrun, xen_coprocessor_segment_overrun, false },
607+
{ invalid_TSS, xen_invalid_TSS, false },
608+
{ segment_not_present, xen_segment_not_present, false },
609+
{ stack_segment, xen_stack_segment, false },
610+
{ general_protection, xen_general_protection, false },
611+
{ spurious_interrupt_bug, xen_spurious_interrupt_bug, false },
612+
{ coprocessor_error, xen_coprocessor_error, false },
613+
{ alignment_check, xen_alignment_check, false },
614+
{ simd_coprocessor_error, xen_simd_coprocessor_error, false },
615+
};
616+
617+
static bool get_trap_addr(void **addr, unsigned int ist)
618+
{
619+
unsigned int nr;
620+
bool ist_okay = false;
621+
622+
/*
623+
* Replace trap handler addresses by Xen specific ones.
624+
* Check for known traps using IST and whitelist them.
625+
* The debugger ones are the only ones we care about.
626+
* Xen will handle faults like double_fault, * so we should never see
627+
* them. Warn if there's an unexpected IST-using fault handler.
628+
*/
629+
for (nr = 0; nr < ARRAY_SIZE(trap_array); nr++) {
630+
struct trap_array_entry *entry = trap_array + nr;
631+
632+
if (*addr == entry->orig) {
633+
*addr = entry->xen;
634+
ist_okay = entry->ist_okay;
635+
break;
636+
}
637+
}
638+
639+
if (WARN_ON(ist != 0 && !ist_okay))
640+
return false;
641+
642+
return true;
643+
}
644+
#endif
645+
582646
static int cvt_gate_to_trap(int vector, const gate_desc *val,
583647
struct trap_info *info)
584648
{
@@ -591,40 +655,8 @@ static int cvt_gate_to_trap(int vector, const gate_desc *val,
591655

592656
addr = gate_offset(val);
593657
#ifdef CONFIG_X86_64
594-
/*
595-
* Look for known traps using IST, and substitute them
596-
* appropriately. The debugger ones are the only ones we care
597-
* about. Xen will handle faults like double_fault,
598-
* so we should never see them. Warn if
599-
* there's an unexpected IST-using fault handler.
600-
*/
601-
if (addr == (unsigned long)debug)
602-
addr = (unsigned long)xen_debug;
603-
else if (addr == (unsigned long)int3)
604-
addr = (unsigned long)xen_int3;
605-
else if (addr == (unsigned long)stack_segment)
606-
addr = (unsigned long)xen_stack_segment;
607-
else if (addr == (unsigned long)double_fault) {
608-
/* Don't need to handle these */
658+
if (!get_trap_addr((void **)&addr, val->bits.ist))
609659
return 0;
610-
#ifdef CONFIG_X86_MCE
611-
} else if (addr == (unsigned long)machine_check) {
612-
/*
613-
* when xen hypervisor inject vMCE to guest,
614-
* use native mce handler to handle it
615-
*/
616-
;
617-
#endif
618-
} else if (addr == (unsigned long)nmi)
619-
/*
620-
* Use the native version as well.
621-
*/
622-
;
623-
else {
624-
/* Some other trap using IST? */
625-
if (WARN_ON(val->bits.ist != 0))
626-
return 0;
627-
}
628660
#endif /* CONFIG_X86_64 */
629661
info->address = addr;
630662

arch/x86/xen/irq.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ static const struct pv_irq_ops xen_irq_ops __initconst = {
123123

124124
.safe_halt = xen_safe_halt,
125125
.halt = xen_halt,
126-
#ifdef CONFIG_X86_64
127-
.adjust_exception_frame = xen_adjust_exception_frame,
128-
#endif
129126
};
130127

131128
void __init xen_init_irq_ops(void)

0 commit comments

Comments
 (0)