diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-04 20:43:56 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-09-04 20:43:56 -0400 |
commit | 24e700e291d52bd200212487e2b654c0aa3f07a2 (patch) | |
tree | 56dfa9d5cdf5f753abbaac91dd68295e32ad2d85 | |
parent | f57091767add2b79d76aac41b83b192d8ba1dce7 (diff) | |
parent | c6ef89421e236d75693ae968d80d44a52409889d (diff) |
Merge branch 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 apic updates from Thomas Gleixner:
"This update provides:
- Cleanup of the IDT management including the removal of the extra
tracing IDT. A first step to cleanup the vector management code.
- The removal of the paravirt op adjust_exception_frame. This is a
XEN specific issue, but merged through this branch to avoid nasty
merge collisions
- Prevent dmesg spam about the TSC DEADLINE bug, when the CPU has
disabled the TSC DEADLINE timer in CPUID.
- Adjust a debug message in the ioapic code to print out the
information correctly"
* 'x86-apic-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (51 commits)
x86/idt: Fix the X86_TRAP_BP gate
x86/xen: Get rid of paravirt op adjust_exception_frame
x86/eisa: Add missing include
x86/idt: Remove superfluous ALIGNment
x86/apic: Silence "FW_BUG TSC_DEADLINE disabled due to Errata" on CPUs without the feature
x86/idt: Remove the tracing IDT leftovers
x86/idt: Hide set_intr_gate()
x86/idt: Simplify alloc_intr_gate()
x86/idt: Deinline setup functions
x86/idt: Remove unused functions/inlines
x86/idt: Move interrupt gate initialization to IDT code
x86/idt: Move APIC gate initialization to tables
x86/idt: Move regular trap init to tables
x86/idt: Move IST stack based traps to table init
x86/idt: Move debug stack init to table based
x86/idt: Switch early trap init to IDT tables
x86/idt: Prepare for table based init
x86/idt: Move early IDT setup out of 32-bit asm
x86/idt: Move early IDT handler setup to IDT code
x86/idt: Consolidate IDT invalidation
...
58 files changed, 901 insertions, 1077 deletions
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c index e007887a33b0..926c2cc4facc 100644 --- a/arch/x86/boot/compressed/eboot.c +++ b/arch/x86/boot/compressed/eboot.c | |||
@@ -1058,7 +1058,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1058 | desc->s = DESC_TYPE_CODE_DATA; | 1058 | desc->s = DESC_TYPE_CODE_DATA; |
1059 | desc->dpl = 0; | 1059 | desc->dpl = 0; |
1060 | desc->p = 1; | 1060 | desc->p = 1; |
1061 | desc->limit = 0xf; | 1061 | desc->limit1 = 0xf; |
1062 | desc->avl = 0; | 1062 | desc->avl = 0; |
1063 | desc->l = 0; | 1063 | desc->l = 0; |
1064 | desc->d = SEG_OP_SIZE_32BIT; | 1064 | desc->d = SEG_OP_SIZE_32BIT; |
@@ -1078,7 +1078,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1078 | desc->s = DESC_TYPE_CODE_DATA; | 1078 | desc->s = DESC_TYPE_CODE_DATA; |
1079 | desc->dpl = 0; | 1079 | desc->dpl = 0; |
1080 | desc->p = 1; | 1080 | desc->p = 1; |
1081 | desc->limit = 0xf; | 1081 | desc->limit1 = 0xf; |
1082 | desc->avl = 0; | 1082 | desc->avl = 0; |
1083 | if (IS_ENABLED(CONFIG_X86_64)) { | 1083 | if (IS_ENABLED(CONFIG_X86_64)) { |
1084 | desc->l = 1; | 1084 | desc->l = 1; |
@@ -1099,7 +1099,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1099 | desc->s = DESC_TYPE_CODE_DATA; | 1099 | desc->s = DESC_TYPE_CODE_DATA; |
1100 | desc->dpl = 0; | 1100 | desc->dpl = 0; |
1101 | desc->p = 1; | 1101 | desc->p = 1; |
1102 | desc->limit = 0xf; | 1102 | desc->limit1 = 0xf; |
1103 | desc->avl = 0; | 1103 | desc->avl = 0; |
1104 | desc->l = 0; | 1104 | desc->l = 0; |
1105 | desc->d = SEG_OP_SIZE_32BIT; | 1105 | desc->d = SEG_OP_SIZE_32BIT; |
@@ -1116,7 +1116,7 @@ struct boot_params *efi_main(struct efi_config *c, | |||
1116 | desc->s = 0; | 1116 | desc->s = 0; |
1117 | desc->dpl = 0; | 1117 | desc->dpl = 0; |
1118 | desc->p = 1; | 1118 | desc->p = 1; |
1119 | desc->limit = 0x0; | 1119 | desc->limit1 = 0x0; |
1120 | desc->avl = 0; | 1120 | desc->avl = 0; |
1121 | desc->l = 0; | 1121 | desc->l = 0; |
1122 | desc->d = 0; | 1122 | desc->d = 0; |
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S index 48ef7bb32c42..8a13d468635a 100644 --- a/arch/x86/entry/entry_32.S +++ b/arch/x86/entry/entry_32.S | |||
@@ -673,16 +673,8 @@ ENTRY(name) \ | |||
673 | jmp ret_from_intr; \ | 673 | jmp ret_from_intr; \ |
674 | ENDPROC(name) | 674 | ENDPROC(name) |
675 | 675 | ||
676 | |||
677 | #ifdef CONFIG_TRACING | ||
678 | # define TRACE_BUILD_INTERRUPT(name, nr) BUILD_INTERRUPT3(trace_##name, nr, smp_trace_##name) | ||
679 | #else | ||
680 | # define TRACE_BUILD_INTERRUPT(name, nr) | ||
681 | #endif | ||
682 | |||
683 | #define BUILD_INTERRUPT(name, nr) \ | 676 | #define BUILD_INTERRUPT(name, nr) \ |
684 | BUILD_INTERRUPT3(name, nr, smp_##name); \ | 677 | BUILD_INTERRUPT3(name, nr, smp_##name); \ |
685 | TRACE_BUILD_INTERRUPT(name, nr) | ||
686 | 678 | ||
687 | /* The include is where all of the SMP etc. interrupts come from */ | 679 | /* The include is where all of the SMP etc. interrupts come from */ |
688 | #include <asm/entry_arch.h> | 680 | #include <asm/entry_arch.h> |
@@ -880,25 +872,17 @@ ENTRY(xen_failsafe_callback) | |||
880 | ENDPROC(xen_failsafe_callback) | 872 | ENDPROC(xen_failsafe_callback) |
881 | 873 | ||
882 | BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR, | 874 | BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR, |
883 | xen_evtchn_do_upcall) | 875 | xen_evtchn_do_upcall) |
884 | 876 | ||
885 | #endif /* CONFIG_XEN */ | 877 | #endif /* CONFIG_XEN */ |
886 | 878 | ||
887 | #if IS_ENABLED(CONFIG_HYPERV) | 879 | #if IS_ENABLED(CONFIG_HYPERV) |
888 | 880 | ||
889 | BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, | 881 | BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR, |
890 | hyperv_vector_handler) | 882 | hyperv_vector_handler) |
891 | 883 | ||
892 | #endif /* CONFIG_HYPERV */ | 884 | #endif /* CONFIG_HYPERV */ |
893 | 885 | ||
894 | #ifdef CONFIG_TRACING | ||
895 | ENTRY(trace_page_fault) | ||
896 | ASM_CLAC | ||
897 | pushl $trace_do_page_fault | ||
898 | jmp common_exception | ||
899 | END(trace_page_fault) | ||
900 | #endif | ||
901 | |||
902 | ENTRY(page_fault) | 886 | ENTRY(page_fault) |
903 | ASM_CLAC | 887 | ASM_CLAC |
904 | pushl $do_page_fault | 888 | pushl $do_page_fault |
diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S index ca0b250eefc4..49167258d587 100644 --- a/arch/x86/entry/entry_64.S +++ b/arch/x86/entry/entry_64.S | |||
@@ -748,18 +748,6 @@ ENTRY(\sym) | |||
748 | END(\sym) | 748 | END(\sym) |
749 | .endm | 749 | .endm |
750 | 750 | ||
751 | #ifdef CONFIG_TRACING | ||
752 | #define trace(sym) trace_##sym | ||
753 | #define smp_trace(sym) smp_trace_##sym | ||
754 | |||
755 | .macro trace_apicinterrupt num sym | ||
756 | apicinterrupt3 \num trace(\sym) smp_trace(\sym) | ||
757 | .endm | ||
758 | #else | ||
759 | .macro trace_apicinterrupt num sym do_sym | ||
760 | .endm | ||
761 | #endif | ||
762 | |||
763 | /* Make sure APIC interrupt handlers end up in the irqentry section: */ | 751 | /* Make sure APIC interrupt handlers end up in the irqentry section: */ |
764 | #define PUSH_SECTION_IRQENTRY .pushsection .irqentry.text, "ax" | 752 | #define PUSH_SECTION_IRQENTRY .pushsection .irqentry.text, "ax" |
765 | #define POP_SECTION_IRQENTRY .popsection | 753 | #define POP_SECTION_IRQENTRY .popsection |
@@ -767,7 +755,6 @@ apicinterrupt3 \num trace(\sym) smp_trace(\sym) | |||
767 | .macro apicinterrupt num sym do_sym | 755 | .macro apicinterrupt num sym do_sym |
768 | PUSH_SECTION_IRQENTRY | 756 | PUSH_SECTION_IRQENTRY |
769 | apicinterrupt3 \num \sym \do_sym | 757 | apicinterrupt3 \num \sym \do_sym |
770 | trace_apicinterrupt \num \sym | ||
771 | POP_SECTION_IRQENTRY | 758 | POP_SECTION_IRQENTRY |
772 | .endm | 759 | .endm |
773 | 760 | ||
@@ -829,7 +816,6 @@ ENTRY(\sym) | |||
829 | .endif | 816 | .endif |
830 | 817 | ||
831 | ASM_CLAC | 818 | ASM_CLAC |
832 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
833 | 819 | ||
834 | .ifeq \has_error_code | 820 | .ifeq \has_error_code |
835 | pushq $-1 /* ORIG_RAX: no syscall to restart */ | 821 | pushq $-1 /* ORIG_RAX: no syscall to restart */ |
@@ -913,17 +899,6 @@ ENTRY(\sym) | |||
913 | END(\sym) | 899 | END(\sym) |
914 | .endm | 900 | .endm |
915 | 901 | ||
916 | #ifdef CONFIG_TRACING | ||
917 | .macro trace_idtentry sym do_sym has_error_code:req | ||
918 | idtentry trace(\sym) trace(\do_sym) has_error_code=\has_error_code | ||
919 | idtentry \sym \do_sym has_error_code=\has_error_code | ||
920 | .endm | ||
921 | #else | ||
922 | .macro trace_idtentry sym do_sym has_error_code:req | ||
923 | idtentry \sym \do_sym has_error_code=\has_error_code | ||
924 | .endm | ||
925 | #endif | ||
926 | |||
927 | idtentry divide_error do_divide_error has_error_code=0 | 902 | idtentry divide_error do_divide_error has_error_code=0 |
928 | idtentry overflow do_overflow has_error_code=0 | 903 | idtentry overflow do_overflow has_error_code=0 |
929 | idtentry bounds do_bounds has_error_code=0 | 904 | idtentry bounds do_bounds has_error_code=0 |
@@ -986,7 +961,7 @@ ENTRY(do_softirq_own_stack) | |||
986 | ENDPROC(do_softirq_own_stack) | 961 | ENDPROC(do_softirq_own_stack) |
987 | 962 | ||
988 | #ifdef CONFIG_XEN | 963 | #ifdef CONFIG_XEN |
989 | idtentry xen_hypervisor_callback xen_do_hypervisor_callback has_error_code=0 | 964 | idtentry hypervisor_callback xen_do_hypervisor_callback has_error_code=0 |
990 | 965 | ||
991 | /* | 966 | /* |
992 | * A note on the "critical region" in our callback handler. | 967 | * A note on the "critical region" in our callback handler. |
@@ -1053,8 +1028,6 @@ ENTRY(xen_failsafe_callback) | |||
1053 | movq 8(%rsp), %r11 | 1028 | movq 8(%rsp), %r11 |
1054 | addq $0x30, %rsp | 1029 | addq $0x30, %rsp |
1055 | pushq $0 /* RIP */ | 1030 | pushq $0 /* RIP */ |
1056 | pushq %r11 | ||
1057 | pushq %rcx | ||
1058 | UNWIND_HINT_IRET_REGS offset=8 | 1031 | UNWIND_HINT_IRET_REGS offset=8 |
1059 | jmp general_protection | 1032 | jmp general_protection |
1060 | 1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */ | 1033 | 1: /* Segment mismatch => Category 1 (Bad segment). Retry the IRET. */ |
@@ -1085,13 +1058,12 @@ idtentry int3 do_int3 has_error_code=0 paranoid=1 shift_ist=DEBUG_STACK | |||
1085 | idtentry stack_segment do_stack_segment has_error_code=1 | 1058 | idtentry stack_segment do_stack_segment has_error_code=1 |
1086 | 1059 | ||
1087 | #ifdef CONFIG_XEN | 1060 | #ifdef CONFIG_XEN |
1088 | idtentry xen_debug do_debug has_error_code=0 | 1061 | idtentry xendebug do_debug has_error_code=0 |
1089 | idtentry xen_int3 do_int3 has_error_code=0 | 1062 | idtentry xenint3 do_int3 has_error_code=0 |
1090 | idtentry xen_stack_segment do_stack_segment has_error_code=1 | ||
1091 | #endif | 1063 | #endif |
1092 | 1064 | ||
1093 | idtentry general_protection do_general_protection has_error_code=1 | 1065 | idtentry general_protection do_general_protection has_error_code=1 |
1094 | trace_idtentry page_fault do_page_fault has_error_code=1 | 1066 | idtentry page_fault do_page_fault has_error_code=1 |
1095 | 1067 | ||
1096 | #ifdef CONFIG_KVM_GUEST | 1068 | #ifdef CONFIG_KVM_GUEST |
1097 | idtentry async_page_fault do_async_page_fault has_error_code=1 | 1069 | idtentry async_page_fault do_async_page_fault has_error_code=1 |
@@ -1251,21 +1223,10 @@ ENTRY(error_exit) | |||
1251 | END(error_exit) | 1223 | END(error_exit) |
1252 | 1224 | ||
1253 | /* Runs on exception stack */ | 1225 | /* Runs on exception stack */ |
1226 | /* XXX: broken on Xen PV */ | ||
1254 | ENTRY(nmi) | 1227 | ENTRY(nmi) |
1255 | UNWIND_HINT_IRET_REGS | 1228 | UNWIND_HINT_IRET_REGS |
1256 | /* | 1229 | /* |
1257 | * Fix up the exception frame if we're on Xen. | ||
1258 | * PARAVIRT_ADJUST_EXCEPTION_FRAME is guaranteed to push at most | ||
1259 | * one value to the stack on native, so it may clobber the rdx | ||
1260 | * scratch slot, but it won't clobber any of the important | ||
1261 | * slots past it. | ||
1262 | * | ||
1263 | * Xen is a different story, because the Xen frame itself overlaps | ||
1264 | * the "NMI executing" variable. | ||
1265 | */ | ||
1266 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
1267 | |||
1268 | /* | ||
1269 | * We allow breakpoints in NMIs. If a breakpoint occurs, then | 1230 | * We allow breakpoints in NMIs. If a breakpoint occurs, then |
1270 | * the iretq it performs will take us out of NMI context. | 1231 | * the iretq it performs will take us out of NMI context. |
1271 | * This means that we can have nested NMIs where the next | 1232 | * This means that we can have nested NMIs where the next |
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index 4b86d8da3ea3..e26c25ca7756 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S | |||
@@ -293,7 +293,6 @@ ENTRY(entry_INT80_compat) | |||
293 | /* | 293 | /* |
294 | * Interrupts are off on entry. | 294 | * Interrupts are off on entry. |
295 | */ | 295 | */ |
296 | PARAVIRT_ADJUST_EXCEPTION_FRAME | ||
297 | ASM_CLAC /* Do this early to minimize exposure */ | 296 | ASM_CLAC /* Do this early to minimize exposure */ |
298 | SWAPGS | 297 | SWAPGS |
299 | 298 | ||
diff --git a/arch/x86/entry/vdso/vma.c b/arch/x86/entry/vdso/vma.c index 726355ce8497..1911310959f8 100644 --- a/arch/x86/entry/vdso/vma.c +++ b/arch/x86/entry/vdso/vma.c | |||
@@ -351,7 +351,7 @@ static void vgetcpu_cpu_init(void *arg) | |||
351 | * and 8 bits for the node) | 351 | * and 8 bits for the node) |
352 | */ | 352 | */ |
353 | d.limit0 = cpu | ((node & 0xf) << 12); | 353 | d.limit0 = cpu | ((node & 0xf) << 12); |
354 | d.limit = node >> 4; | 354 | d.limit1 = node >> 4; |
355 | d.type = 5; /* RO data, expand down, accessed */ | 355 | d.type = 5; /* RO data, expand down, accessed */ |
356 | d.dpl = 3; /* Visible to user code */ | 356 | d.dpl = 3; /* Visible to user code */ |
357 | d.s = 1; /* Not a system segment */ | 357 | d.s = 1; /* Not a system segment */ |
diff --git a/arch/x86/include/asm/desc.h b/arch/x86/include/asm/desc.h index d0a21b12dd58..1a2ba368da39 100644 --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h | |||
@@ -5,6 +5,7 @@ | |||
5 | #include <asm/ldt.h> | 5 | #include <asm/ldt.h> |
6 | #include <asm/mmu.h> | 6 | #include <asm/mmu.h> |
7 | #include <asm/fixmap.h> | 7 | #include <asm/fixmap.h> |
8 | #include <asm/irq_vectors.h> | ||
8 | 9 | ||
9 | #include <linux/smp.h> | 10 | #include <linux/smp.h> |
10 | #include <linux/percpu.h> | 11 | #include <linux/percpu.h> |
@@ -22,7 +23,7 @@ static inline void fill_ldt(struct desc_struct *desc, const struct user_desc *in | |||
22 | desc->s = 1; | 23 | desc->s = 1; |
23 | desc->dpl = 0x3; | 24 | desc->dpl = 0x3; |
24 | desc->p = info->seg_not_present ^ 1; | 25 | desc->p = info->seg_not_present ^ 1; |
25 | desc->limit = (info->limit & 0xf0000) >> 16; | 26 | desc->limit1 = (info->limit & 0xf0000) >> 16; |
26 | desc->avl = info->useable; | 27 | desc->avl = info->useable; |
27 | desc->d = info->seg_32bit; | 28 | desc->d = info->seg_32bit; |
28 | desc->g = info->limit_in_pages; | 29 | desc->g = info->limit_in_pages; |
@@ -83,33 +84,25 @@ static inline phys_addr_t get_cpu_gdt_paddr(unsigned int cpu) | |||
83 | return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu)); | 84 | return per_cpu_ptr_to_phys(get_cpu_gdt_rw(cpu)); |
84 | } | 85 | } |
85 | 86 | ||
86 | #ifdef CONFIG_X86_64 | ||
87 | |||
88 | static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, | 87 | static inline void pack_gate(gate_desc *gate, unsigned type, unsigned long func, |
89 | unsigned dpl, unsigned ist, unsigned seg) | 88 | unsigned dpl, unsigned ist, unsigned seg) |
90 | { | 89 | { |
91 | gate->offset_low = PTR_LOW(func); | 90 | gate->offset_low = (u16) func; |
91 | gate->bits.p = 1; | ||
92 | gate->bits.dpl = dpl; | ||
93 | gate->bits.zero = 0; | ||
94 | gate->bits.type = type; | ||
95 | gate->offset_middle = (u16) (func >> 16); | ||
96 | #ifdef CONFIG_X86_64 | ||
92 | gate->segment = __KERNEL_CS; | 97 | gate->segment = __KERNEL_CS; |
93 | gate->ist = ist; | 98 | gate->bits.ist = ist; |
94 | gate->p = 1; | 99 | gate->reserved = 0; |
95 | gate->dpl = dpl; | 100 | gate->offset_high = (u32) (func >> 32); |
96 | gate->zero0 = 0; | ||
97 | gate->zero1 = 0; | ||
98 | gate->type = type; | ||
99 | gate->offset_middle = PTR_MIDDLE(func); | ||
100 | gate->offset_high = PTR_HIGH(func); | ||
101 | } | ||
102 | |||
103 | #else | 101 | #else |
104 | static inline void pack_gate(gate_desc *gate, unsigned char type, | 102 | gate->segment = seg; |
105 | unsigned long base, unsigned dpl, unsigned flags, | 103 | gate->bits.ist = 0; |
106 | unsigned short seg) | ||
107 | { | ||
108 | gate->a = (seg << 16) | (base & 0xffff); | ||
109 | gate->b = (base & 0xffff0000) | (((0x80 | type | (dpl << 5)) & 0xff) << 8); | ||
110 | } | ||
111 | |||
112 | #endif | 104 | #endif |
105 | } | ||
113 | 106 | ||
114 | static inline int desc_empty(const void *ptr) | 107 | static inline int desc_empty(const void *ptr) |
115 | { | 108 | { |
@@ -173,35 +166,22 @@ native_write_gdt_entry(struct desc_struct *gdt, int entry, const void *desc, int | |||
173 | memcpy(&gdt[entry], desc, size); | 166 | memcpy(&gdt[entry], desc, size); |
174 | } | 167 | } |
175 | 168 | ||
176 | static inline void pack_descriptor(struct desc_struct *desc, unsigned long base, | 169 | static inline void set_tssldt_descriptor(void *d, unsigned long addr, |
177 | unsigned long limit, unsigned char type, | 170 | unsigned type, unsigned size) |
178 | unsigned char flags) | ||
179 | { | ||
180 | desc->a = ((base & 0xffff) << 16) | (limit & 0xffff); | ||
181 | desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) | | ||
182 | (limit & 0x000f0000) | ((type & 0xff) << 8) | | ||
183 | ((flags & 0xf) << 20); | ||
184 | desc->p = 1; | ||
185 | } | ||
186 | |||
187 | |||
188 | static inline void set_tssldt_descriptor(void *d, unsigned long addr, unsigned type, unsigned size) | ||
189 | { | 171 | { |
190 | #ifdef CONFIG_X86_64 | 172 | struct ldttss_desc *desc = d; |
191 | struct ldttss_desc64 *desc = d; | ||
192 | 173 | ||
193 | memset(desc, 0, sizeof(*desc)); | 174 | memset(desc, 0, sizeof(*desc)); |
194 | 175 | ||
195 | desc->limit0 = size & 0xFFFF; | 176 | desc->limit0 = (u16) size; |
196 | desc->base0 = PTR_LOW(addr); | 177 | desc->base0 = (u16) addr; |
197 | desc->base1 = PTR_MIDDLE(addr) & 0xFF; | 178 | desc->base1 = (addr >> 16) & 0xFF; |
198 | desc->type = type; | 179 | desc->type = type; |
199 | desc->p = 1; | 180 | desc->p = 1; |
200 | desc->limit1 = (size >> 16) & 0xF; | 181 | desc->limit1 = (size >> 16) & 0xF; |
201 | desc->base2 = (PTR_MIDDLE(addr) >> 8) & 0xFF; | 182 | desc->base2 = (addr >> 24) & 0xFF; |
202 | desc->base3 = PTR_HIGH(addr); | 183 | #ifdef CONFIG_X86_64 |
203 | #else | 184 | desc->base3 = (u32) (addr >> 32); |
204 | pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0); | ||
205 | #endif | 185 | #endif |
206 | } | 186 | } |
207 | 187 | ||
@@ -401,147 +381,20 @@ static inline void set_desc_base(struct desc_struct *desc, unsigned long base) | |||
401 | 381 | ||
402 | static inline unsigned long get_desc_limit(const struct desc_struct *desc) | 382 | static inline unsigned long get_desc_limit(const struct desc_struct *desc) |
403 | { | 383 | { |
404 | return desc->limit0 | (desc->limit << 16); | 384 | return desc->limit0 | (desc->limit1 << 16); |
405 | } | 385 | } |
406 | 386 | ||
407 | static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) | 387 | static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit) |
408 | { | 388 | { |
409 | desc->limit0 = limit & 0xffff; | 389 | desc->limit0 = limit & 0xffff; |
410 | desc->limit = (limit >> 16) & 0xf; | 390 | desc->limit1 = (limit >> 16) & 0xf; |
411 | } | ||
412 | |||
413 | #ifdef CONFIG_X86_64 | ||
414 | static inline void set_nmi_gate(int gate, void *addr) | ||
415 | { | ||
416 | gate_desc s; | ||
417 | |||
418 | pack_gate(&s, GATE_INTERRUPT, (unsigned long)addr, 0, 0, __KERNEL_CS); | ||
419 | write_idt_entry(debug_idt_table, gate, &s); | ||
420 | } | 391 | } |
421 | #endif | ||
422 | 392 | ||
423 | #ifdef CONFIG_TRACING | 393 | void update_intr_gate(unsigned int n, const void *addr); |
424 | extern struct desc_ptr trace_idt_descr; | 394 | void alloc_intr_gate(unsigned int n, const void *addr); |
425 | extern gate_desc trace_idt_table[]; | ||
426 | static inline void write_trace_idt_entry(int entry, const gate_desc *gate) | ||
427 | { | ||
428 | write_idt_entry(trace_idt_table, entry, gate); | ||
429 | } | ||
430 | 395 | ||
431 | static inline void _trace_set_gate(int gate, unsigned type, void *addr, | ||
432 | unsigned dpl, unsigned ist, unsigned seg) | ||
433 | { | ||
434 | gate_desc s; | ||
435 | |||
436 | pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); | ||
437 | /* | ||
438 | * does not need to be atomic because it is only done once at | ||
439 | * setup time | ||
440 | */ | ||
441 | write_trace_idt_entry(gate, &s); | ||
442 | } | ||
443 | #else | ||
444 | static inline void write_trace_idt_entry(int entry, const gate_desc *gate) | ||
445 | { | ||
446 | } | ||
447 | |||
448 | #define _trace_set_gate(gate, type, addr, dpl, ist, seg) | ||
449 | #endif | ||
450 | |||
451 | static inline void _set_gate(int gate, unsigned type, void *addr, | ||
452 | unsigned dpl, unsigned ist, unsigned seg) | ||
453 | { | ||
454 | gate_desc s; | ||
455 | |||
456 | pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg); | ||
457 | /* | ||
458 | * does not need to be atomic because it is only done once at | ||
459 | * setup time | ||
460 | */ | ||
461 | write_idt_entry(idt_table, gate, &s); | ||
462 | write_trace_idt_entry(gate, &s); | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * This needs to use 'idt_table' rather than 'idt', and | ||
467 | * thus use the _nonmapped_ version of the IDT, as the | ||
468 | * Pentium F0 0F bugfix can have resulted in the mapped | ||
469 | * IDT being write-protected. | ||
470 | */ | ||
471 | #define set_intr_gate_notrace(n, addr) \ | ||
472 | do { \ | ||
473 | BUG_ON((unsigned)n > 0xFF); \ | ||
474 | _set_gate(n, GATE_INTERRUPT, (void *)addr, 0, 0, \ | ||
475 | __KERNEL_CS); \ | ||
476 | } while (0) | ||
477 | |||
478 | #define set_intr_gate(n, addr) \ | ||
479 | do { \ | ||
480 | set_intr_gate_notrace(n, addr); \ | ||
481 | _trace_set_gate(n, GATE_INTERRUPT, (void *)trace_##addr,\ | ||
482 | 0, 0, __KERNEL_CS); \ | ||
483 | } while (0) | ||
484 | |||
485 | extern int first_system_vector; | ||
486 | /* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ | ||
487 | extern unsigned long used_vectors[]; | 396 | extern unsigned long used_vectors[]; |
488 | 397 | ||
489 | static inline void alloc_system_vector(int vector) | ||
490 | { | ||
491 | if (!test_bit(vector, used_vectors)) { | ||
492 | set_bit(vector, used_vectors); | ||
493 | if (first_system_vector > vector) | ||
494 | first_system_vector = vector; | ||
495 | } else { | ||
496 | BUG(); | ||
497 | } | ||
498 | } | ||
499 | |||
500 | #define alloc_intr_gate(n, addr) \ | ||
501 | do { \ | ||
502 | alloc_system_vector(n); \ | ||
503 | set_intr_gate(n, addr); \ | ||
504 | } while (0) | ||
505 | |||
506 | /* | ||
507 | * This routine sets up an interrupt gate at directory privilege level 3. | ||
508 | */ | ||
509 | static inline void set_system_intr_gate(unsigned int n, void *addr) | ||
510 | { | ||
511 | BUG_ON((unsigned)n > 0xFF); | ||
512 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, 0, __KERNEL_CS); | ||
513 | } | ||
514 | |||
515 | static inline void set_system_trap_gate(unsigned int n, void *addr) | ||
516 | { | ||
517 | BUG_ON((unsigned)n > 0xFF); | ||
518 | _set_gate(n, GATE_TRAP, addr, 0x3, 0, __KERNEL_CS); | ||
519 | } | ||
520 | |||
521 | static inline void set_trap_gate(unsigned int n, void *addr) | ||
522 | { | ||
523 | BUG_ON((unsigned)n > 0xFF); | ||
524 | _set_gate(n, GATE_TRAP, addr, 0, 0, __KERNEL_CS); | ||
525 | } | ||
526 | |||
527 | static inline void set_task_gate(unsigned int n, unsigned int gdt_entry) | ||
528 | { | ||
529 | BUG_ON((unsigned)n > 0xFF); | ||
530 | _set_gate(n, GATE_TASK, (void *)0, 0, 0, (gdt_entry<<3)); | ||
531 | } | ||
532 | |||
533 | static inline void set_intr_gate_ist(int n, void *addr, unsigned ist) | ||
534 | { | ||
535 | BUG_ON((unsigned)n > 0xFF); | ||
536 | _set_gate(n, GATE_INTERRUPT, addr, 0, ist, __KERNEL_CS); | ||
537 | } | ||
538 | |||
539 | static inline void set_system_intr_gate_ist(int n, void *addr, unsigned ist) | ||
540 | { | ||
541 | BUG_ON((unsigned)n > 0xFF); | ||
542 | _set_gate(n, GATE_INTERRUPT, addr, 0x3, ist, __KERNEL_CS); | ||
543 | } | ||
544 | |||
545 | #ifdef CONFIG_X86_64 | 398 | #ifdef CONFIG_X86_64 |
546 | DECLARE_PER_CPU(u32, debug_idt_ctr); | 399 | DECLARE_PER_CPU(u32, debug_idt_ctr); |
547 | static inline bool is_debug_idt_enabled(void) | 400 | static inline bool is_debug_idt_enabled(void) |
@@ -567,31 +420,6 @@ static inline void load_debug_idt(void) | |||
567 | } | 420 | } |
568 | #endif | 421 | #endif |
569 | 422 | ||
570 | #ifdef CONFIG_TRACING | ||
571 | extern atomic_t trace_idt_ctr; | ||
572 | static inline bool is_trace_idt_enabled(void) | ||
573 | { | ||
574 | if (atomic_read(&trace_idt_ctr)) | ||
575 | return true; | ||
576 | |||
577 | return false; | ||
578 | } | ||
579 | |||
580 | static inline void load_trace_idt(void) | ||
581 | { | ||
582 | load_idt((const struct desc_ptr *)&trace_idt_descr); | ||
583 | } | ||
584 | #else | ||
585 | static inline bool is_trace_idt_enabled(void) | ||
586 | { | ||
587 | return false; | ||
588 | } | ||
589 | |||
590 | static inline void load_trace_idt(void) | ||
591 | { | ||
592 | } | ||
593 | #endif | ||
594 | |||
595 | /* | 423 | /* |
596 | * The load_current_idt() must be called with interrupts disabled | 424 | * The load_current_idt() must be called with interrupts disabled |
597 | * to avoid races. That way the IDT will always be set back to the expected | 425 | * to avoid races. That way the IDT will always be set back to the expected |
@@ -603,9 +431,25 @@ static inline void load_current_idt(void) | |||
603 | { | 431 | { |
604 | if (is_debug_idt_enabled()) | 432 | if (is_debug_idt_enabled()) |
605 | load_debug_idt(); | 433 | load_debug_idt(); |
606 | else if (is_trace_idt_enabled()) | ||
607 | load_trace_idt(); | ||
608 | else | 434 | else |
609 | load_idt((const struct desc_ptr *)&idt_descr); | 435 | load_idt((const struct desc_ptr *)&idt_descr); |
610 | } | 436 | } |
437 | |||
438 | extern void idt_setup_early_handler(void); | ||
439 | extern void idt_setup_early_traps(void); | ||
440 | extern void idt_setup_traps(void); | ||
441 | extern void idt_setup_apic_and_irq_gates(void); | ||
442 | |||
443 | #ifdef CONFIG_X86_64 | ||
444 | extern void idt_setup_early_pf(void); | ||
445 | extern void idt_setup_ist_traps(void); | ||
446 | extern void idt_setup_debugidt_traps(void); | ||
447 | #else | ||
448 | static inline void idt_setup_early_pf(void) { } | ||
449 | static inline void idt_setup_ist_traps(void) { } | ||
450 | static inline void idt_setup_debugidt_traps(void) { } | ||
451 | #endif | ||
452 | |||
453 | extern void idt_invalidate(void *addr); | ||
454 | |||
611 | #endif /* _ASM_X86_DESC_H */ | 455 | #endif /* _ASM_X86_DESC_H */ |
diff --git a/arch/x86/include/asm/desc_defs.h b/arch/x86/include/asm/desc_defs.h index 49265345d4d2..346d252029b7 100644 --- a/arch/x86/include/asm/desc_defs.h +++ b/arch/x86/include/asm/desc_defs.h | |||
@@ -11,34 +11,30 @@ | |||
11 | 11 | ||
12 | #include <linux/types.h> | 12 | #include <linux/types.h> |
13 | 13 | ||
14 | /* | ||
15 | * FIXME: Accessing the desc_struct through its fields is more elegant, | ||
16 | * and should be the one valid thing to do. However, a lot of open code | ||
17 | * still touches the a and b accessors, and doing this allow us to do it | ||
18 | * incrementally. We keep the signature as a struct, rather than a union, | ||
19 | * so we can get rid of it transparently in the future -- glommer | ||
20 | */ | ||
21 | /* 8 byte segment descriptor */ | 14 | /* 8 byte segment descriptor */ |
22 | struct desc_struct { | 15 | struct desc_struct { |
23 | union { | 16 | u16 limit0; |
24 | struct { | 17 | u16 base0; |
25 | unsigned int a; | 18 | u16 base1: 8, type: 4, s: 1, dpl: 2, p: 1; |
26 | unsigned int b; | 19 | u16 limit1: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8; |
27 | }; | ||
28 | struct { | ||
29 | u16 limit0; | ||
30 | u16 base0; | ||
31 | unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1; | ||
32 | unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8; | ||
33 | }; | ||
34 | }; | ||
35 | } __attribute__((packed)); | 20 | } __attribute__((packed)); |
36 | 21 | ||
37 | #define GDT_ENTRY_INIT(flags, base, limit) { { { \ | 22 | #define GDT_ENTRY_INIT(flags, base, limit) \ |
38 | .a = ((limit) & 0xffff) | (((base) & 0xffff) << 16), \ | 23 | { \ |
39 | .b = (((base) & 0xff0000) >> 16) | (((flags) & 0xf0ff) << 8) | \ | 24 | .limit0 = (u16) (limit), \ |
40 | ((limit) & 0xf0000) | ((base) & 0xff000000), \ | 25 | .limit1 = ((limit) >> 16) & 0x0F, \ |
41 | } } } | 26 | .base0 = (u16) (base), \ |
27 | .base1 = ((base) >> 16) & 0xFF, \ | ||
28 | .base2 = ((base) >> 24) & 0xFF, \ | ||
29 | .type = (flags & 0x0f), \ | ||
30 | .s = (flags >> 4) & 0x01, \ | ||
31 | .dpl = (flags >> 5) & 0x03, \ | ||
32 | .p = (flags >> 7) & 0x01, \ | ||
33 | .avl = (flags >> 12) & 0x01, \ | ||
34 | .l = (flags >> 13) & 0x01, \ | ||
35 | .d = (flags >> 14) & 0x01, \ | ||
36 | .g = (flags >> 15) & 0x01, \ | ||
37 | } | ||
42 | 38 | ||
43 | enum { | 39 | enum { |
44 | GATE_INTERRUPT = 0xE, | 40 | GATE_INTERRUPT = 0xE, |
@@ -47,49 +43,63 @@ enum { | |||
47 | GATE_TASK = 0x5, | 43 | GATE_TASK = 0x5, |
48 | }; | 44 | }; |
49 | 45 | ||
50 | /* 16byte gate */ | ||
51 | struct gate_struct64 { | ||
52 | u16 offset_low; | ||
53 | u16 segment; | ||
54 | unsigned ist : 3, zero0 : 5, type : 5, dpl : 2, p : 1; | ||
55 | u16 offset_middle; | ||
56 | u32 offset_high; | ||
57 | u32 zero1; | ||
58 | } __attribute__((packed)); | ||
59 | |||
60 | #define PTR_LOW(x) ((unsigned long long)(x) & 0xFFFF) | ||
61 | #define PTR_MIDDLE(x) (((unsigned long long)(x) >> 16) & 0xFFFF) | ||
62 | #define PTR_HIGH(x) ((unsigned long long)(x) >> 32) | ||
63 | |||
64 | enum { | 46 | enum { |
65 | DESC_TSS = 0x9, | 47 | DESC_TSS = 0x9, |
66 | DESC_LDT = 0x2, | 48 | DESC_LDT = 0x2, |
67 | DESCTYPE_S = 0x10, /* !system */ | 49 | DESCTYPE_S = 0x10, /* !system */ |
68 | }; | 50 | }; |
69 | 51 | ||
70 | /* LDT or TSS descriptor in the GDT. 16 bytes. */ | 52 | /* LDT or TSS descriptor in the GDT. */ |
71 | struct ldttss_desc64 { | 53 | struct ldttss_desc { |
72 | u16 limit0; | 54 | u16 limit0; |
73 | u16 base0; | 55 | u16 base0; |
74 | unsigned base1 : 8, type : 5, dpl : 2, p : 1; | 56 | |
75 | unsigned limit1 : 4, zero0 : 3, g : 1, base2 : 8; | 57 | u16 base1 : 8, type : 5, dpl : 2, p : 1; |
76 | u32 base3; | 58 | u16 limit1 : 4, zero0 : 3, g : 1, base2 : 8; |
77 | u32 zero1; | 59 | #ifdef CONFIG_X86_64 |
60 | u32 base3; | ||
61 | u32 zero1; | ||
62 | #endif | ||
78 | } __attribute__((packed)); | 63 | } __attribute__((packed)); |
79 | 64 | ||
65 | typedef struct ldttss_desc ldt_desc; | ||
66 | typedef struct ldttss_desc tss_desc; | ||
67 | |||
68 | struct idt_bits { | ||
69 | u16 ist : 3, | ||
70 | zero : 5, | ||
71 | type : 5, | ||
72 | dpl : 2, | ||
73 | p : 1; | ||
74 | } __attribute__((packed)); | ||
75 | |||
76 | struct gate_struct { | ||
77 | u16 offset_low; | ||
78 | u16 segment; | ||
79 | struct idt_bits bits; | ||
80 | u16 offset_middle; | ||
81 | #ifdef CONFIG_X86_64 | ||
82 | u32 offset_high; | ||
83 | u32 reserved; | ||
84 | #endif | ||
85 | } __attribute__((packed)); | ||
86 | |||
87 | typedef struct gate_struct gate_desc; | ||
88 | |||
89 | static inline unsigned long gate_offset(const gate_desc *g) | ||
90 | { | ||
80 | #ifdef CONFIG_X86_64 | 91 | #ifdef CONFIG_X86_64 |
81 | typedef struct gate_struct64 gate_desc; | 92 | return g->offset_low | ((unsigned long)g->offset_middle << 16) | |
82 | typedef struct ldttss_desc64 ldt_desc; | 93 | ((unsigned long) g->offset_high << 32); |
83 | typedef struct ldttss_desc64 tss_desc; | ||
84 | #define gate_offset(g) ((g).offset_low | ((unsigned long)(g).offset_middle << 16) | ((unsigned long)(g).offset_high << 32)) | ||
85 | #define gate_segment(g) ((g).segment) | ||
86 | #else | 94 | #else |
87 | typedef struct desc_struct gate_desc; | 95 | return g->offset_low | ((unsigned long)g->offset_middle << 16); |
88 | typedef struct desc_struct ldt_desc; | ||
89 | typedef struct desc_struct tss_desc; | ||
90 | #define gate_offset(g) (((g).b & 0xffff0000) | ((g).a & 0x0000ffff)) | ||
91 | #define gate_segment(g) ((g).a >> 16) | ||
92 | #endif | 96 | #endif |
97 | } | ||
98 | |||
99 | static inline unsigned long gate_segment(const gate_desc *g) | ||
100 | { | ||
101 | return g->segment; | ||
102 | } | ||
93 | 103 | ||
94 | struct desc_ptr { | 104 | struct desc_ptr { |
95 | unsigned short size; | 105 | unsigned short size; |
diff --git a/arch/x86/include/asm/entry_arch.h b/arch/x86/include/asm/entry_arch.h index 07b06955a05d..aa15d1f7e530 100644 --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h | |||
@@ -13,20 +13,14 @@ | |||
13 | BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) | 13 | BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) |
14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) | 14 | BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) |
15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) | 15 | BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) |
16 | BUILD_INTERRUPT3(irq_move_cleanup_interrupt, IRQ_MOVE_CLEANUP_VECTOR, | 16 | BUILD_INTERRUPT(irq_move_cleanup_interrupt, IRQ_MOVE_CLEANUP_VECTOR) |
17 | smp_irq_move_cleanup_interrupt) | 17 | BUILD_INTERRUPT(reboot_interrupt, REBOOT_VECTOR) |
18 | BUILD_INTERRUPT3(reboot_interrupt, REBOOT_VECTOR, smp_reboot_interrupt) | ||
19 | #endif | 18 | #endif |
20 | 19 | ||
21 | BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR) | ||
22 | |||
23 | #ifdef CONFIG_HAVE_KVM | 20 | #ifdef CONFIG_HAVE_KVM |
24 | BUILD_INTERRUPT3(kvm_posted_intr_ipi, POSTED_INTR_VECTOR, | 21 | BUILD_INTERRUPT(kvm_posted_intr_ipi, POSTED_INTR_VECTOR) |
25 | smp_kvm_posted_intr_ipi) | 22 | BUILD_INTERRUPT(kvm_posted_intr_wakeup_ipi, POSTED_INTR_WAKEUP_VECTOR) |
26 | BUILD_INTERRUPT3(kvm_posted_intr_wakeup_ipi, POSTED_INTR_WAKEUP_VECTOR, | 23 | BUILD_INTERRUPT(kvm_posted_intr_nested_ipi, POSTED_INTR_NESTED_VECTOR) |
27 | smp_kvm_posted_intr_wakeup_ipi) | ||
28 | BUILD_INTERRUPT3(kvm_posted_intr_nested_ipi, POSTED_INTR_NESTED_VECTOR, | ||
29 | smp_kvm_posted_intr_nested_ipi) | ||
30 | #endif | 24 | #endif |
31 | 25 | ||
32 | /* | 26 | /* |
@@ -41,6 +35,7 @@ BUILD_INTERRUPT3(kvm_posted_intr_nested_ipi, POSTED_INTR_NESTED_VECTOR, | |||
41 | BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR) | 35 | BUILD_INTERRUPT(apic_timer_interrupt,LOCAL_TIMER_VECTOR) |
42 | BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) | 36 | BUILD_INTERRUPT(error_interrupt,ERROR_APIC_VECTOR) |
43 | BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) | 37 | BUILD_INTERRUPT(spurious_interrupt,SPURIOUS_APIC_VECTOR) |
38 | BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR) | ||
44 | 39 | ||
45 | #ifdef CONFIG_IRQ_WORK | 40 | #ifdef CONFIG_IRQ_WORK |
46 | BUILD_INTERRUPT(irq_work_interrupt, IRQ_WORK_VECTOR) | 41 | BUILD_INTERRUPT(irq_work_interrupt, IRQ_WORK_VECTOR) |
diff --git a/arch/x86/include/asm/hw_irq.h b/arch/x86/include/asm/hw_irq.h index d6dbafbd4207..6dfe366a8804 100644 --- a/arch/x86/include/asm/hw_irq.h +++ b/arch/x86/include/asm/hw_irq.h | |||
@@ -46,26 +46,6 @@ extern asmlinkage void deferred_error_interrupt(void); | |||
46 | extern asmlinkage void call_function_interrupt(void); | 46 | extern asmlinkage void call_function_interrupt(void); |
47 | extern asmlinkage void call_function_single_interrupt(void); | 47 | extern asmlinkage void call_function_single_interrupt(void); |
48 | 48 | ||
49 | #ifdef CONFIG_TRACING | ||
50 | /* Interrupt handlers registered during init_IRQ */ | ||
51 | extern void trace_apic_timer_interrupt(void); | ||
52 | extern void trace_x86_platform_ipi(void); | ||
53 | extern void trace_error_interrupt(void); | ||
54 | extern void trace_irq_work_interrupt(void); | ||
55 | extern void trace_spurious_interrupt(void); | ||
56 | extern void trace_thermal_interrupt(void); | ||
57 | extern void trace_reschedule_interrupt(void); | ||
58 | extern void trace_threshold_interrupt(void); | ||
59 | extern void trace_deferred_error_interrupt(void); | ||
60 | extern void trace_call_function_interrupt(void); | ||
61 | extern void trace_call_function_single_interrupt(void); | ||
62 | #define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt | ||
63 | #define trace_reboot_interrupt reboot_interrupt | ||
64 | #define trace_kvm_posted_intr_ipi kvm_posted_intr_ipi | ||
65 | #define trace_kvm_posted_intr_wakeup_ipi kvm_posted_intr_wakeup_ipi | ||
66 | #define trace_kvm_posted_intr_nested_ipi kvm_posted_intr_nested_ipi | ||
67 | #endif /* CONFIG_TRACING */ | ||
68 | |||
69 | #ifdef CONFIG_X86_LOCAL_APIC | 49 | #ifdef CONFIG_X86_LOCAL_APIC |
70 | struct irq_data; | 50 | struct irq_data; |
71 | struct pci_dev; | 51 | struct pci_dev; |
diff --git a/arch/x86/include/asm/irq.h b/arch/x86/include/asm/irq.h index 668cca540025..9958ceea2fa3 100644 --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h | |||
@@ -42,10 +42,6 @@ extern bool handle_irq(struct irq_desc *desc, struct pt_regs *regs); | |||
42 | 42 | ||
43 | extern __visible unsigned int do_IRQ(struct pt_regs *regs); | 43 | extern __visible unsigned int do_IRQ(struct pt_regs *regs); |
44 | 44 | ||
45 | /* Interrupt vector management */ | ||
46 | extern DECLARE_BITMAP(used_vectors, NR_VECTORS); | ||
47 | extern int vector_used_by_percpu_irq(unsigned int vector); | ||
48 | |||
49 | extern void init_ISA_irqs(void); | 45 | extern void init_ISA_irqs(void); |
50 | 46 | ||
51 | #ifdef CONFIG_X86_LOCAL_APIC | 47 | #ifdef CONFIG_X86_LOCAL_APIC |
diff --git a/arch/x86/include/asm/irq_work.h b/arch/x86/include/asm/irq_work.h index f70604125286..ddbb8ea0f5a9 100644 --- a/arch/x86/include/asm/irq_work.h +++ b/arch/x86/include/asm/irq_work.h | |||
@@ -3,9 +3,17 @@ | |||
3 | 3 | ||
4 | #include <asm/cpufeature.h> | 4 | #include <asm/cpufeature.h> |
5 | 5 | ||
6 | #ifdef CONFIG_X86_LOCAL_APIC | ||
6 | static inline bool arch_irq_work_has_interrupt(void) | 7 | static inline bool arch_irq_work_has_interrupt(void) |
7 | { | 8 | { |
8 | return boot_cpu_has(X86_FEATURE_APIC); | 9 | return boot_cpu_has(X86_FEATURE_APIC); |
9 | } | 10 | } |
11 | extern void arch_irq_work_raise(void); | ||
12 | #else | ||
13 | static inline bool arch_irq_work_has_interrupt(void) | ||
14 | { | ||
15 | return false; | ||
16 | } | ||
17 | #endif | ||
10 | 18 | ||
11 | #endif /* _ASM_IRQ_WORK_H */ | 19 | #endif /* _ASM_IRQ_WORK_H */ |
diff --git a/arch/x86/include/asm/paravirt.h b/arch/x86/include/asm/paravirt.h index 9ccac1926587..c25dd22f7c70 100644 --- a/arch/x86/include/asm/paravirt.h +++ b/arch/x86/include/asm/paravirt.h | |||
@@ -960,11 +960,6 @@ extern void default_banner(void); | |||
960 | #define GET_CR2_INTO_RAX \ | 960 | #define GET_CR2_INTO_RAX \ |
961 | call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2) | 961 | call PARA_INDIRECT(pv_mmu_ops+PV_MMU_read_cr2) |
962 | 962 | ||
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 | |||
968 | #define USERGS_SYSRET64 \ | 963 | #define USERGS_SYSRET64 \ |
969 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \ | 964 | PARA_SITE(PARA_PATCH(pv_cpu_ops, PV_CPU_usergs_sysret64), \ |
970 | CLBR_NONE, \ | 965 | CLBR_NONE, \ |
diff --git a/arch/x86/include/asm/paravirt_types.h b/arch/x86/include/asm/paravirt_types.h index 9ffc36bfe4cd..6b64fc6367f2 100644 --- a/arch/x86/include/asm/paravirt_types.h +++ b/arch/x86/include/asm/paravirt_types.h | |||
@@ -196,9 +196,6 @@ struct pv_irq_ops { | |||
196 | void (*safe_halt)(void); | 196 | void (*safe_halt)(void); |
197 | void (*halt)(void); | 197 | void (*halt)(void); |
198 | 198 | ||
199 | #ifdef CONFIG_X86_64 | ||
200 | void (*adjust_exception_frame)(void); | ||
201 | #endif | ||
202 | } __no_randomize_layout; | 199 | } __no_randomize_layout; |
203 | 200 | ||
204 | struct pv_mmu_ops { | 201 | struct pv_mmu_ops { |
diff --git a/arch/x86/include/asm/proto.h b/arch/x86/include/asm/proto.h index 8d3964fc5f91..b408b1886195 100644 --- a/arch/x86/include/asm/proto.h +++ b/arch/x86/include/asm/proto.h | |||
@@ -24,6 +24,9 @@ void entry_SYSENTER_compat(void); | |||
24 | void __end_entry_SYSENTER_compat(void); | 24 | void __end_entry_SYSENTER_compat(void); |
25 | void entry_SYSCALL_compat(void); | 25 | void entry_SYSCALL_compat(void); |
26 | void entry_INT80_compat(void); | 26 | void entry_INT80_compat(void); |
27 | #if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV) | ||
28 | void xen_entry_INT80_compat(void); | ||
29 | #endif | ||
27 | #endif | 30 | #endif |
28 | 31 | ||
29 | void x86_configure_nx(void); | 32 | void x86_configure_nx(void); |
diff --git a/arch/x86/include/asm/segment.h b/arch/x86/include/asm/segment.h index 1549caa098f0..066aaf813141 100644 --- a/arch/x86/include/asm/segment.h +++ b/arch/x86/include/asm/segment.h | |||
@@ -238,9 +238,7 @@ | |||
238 | #ifndef __ASSEMBLY__ | 238 | #ifndef __ASSEMBLY__ |
239 | 239 | ||
240 | extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE]; | 240 | extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE]; |
241 | #ifdef CONFIG_TRACING | 241 | extern void early_ignore_irq(void); |
242 | # define trace_early_idt_handler_array early_idt_handler_array | ||
243 | #endif | ||
244 | 242 | ||
245 | /* | 243 | /* |
246 | * Load a segment. Fall back on loading the zero segment if something goes | 244 | * Load a segment. Fall back on loading the zero segment if something goes |
diff --git a/arch/x86/include/asm/trace/common.h b/arch/x86/include/asm/trace/common.h new file mode 100644 index 000000000000..57c8da027d99 --- /dev/null +++ b/arch/x86/include/asm/trace/common.h | |||
@@ -0,0 +1,16 @@ | |||
1 | #ifndef _ASM_TRACE_COMMON_H | ||
2 | #define _ASM_TRACE_COMMON_H | ||
3 | |||
4 | #ifdef CONFIG_TRACING | ||
5 | DECLARE_STATIC_KEY_FALSE(trace_pagefault_key); | ||
6 | #define trace_pagefault_enabled() \ | ||
7 | static_branch_unlikely(&trace_pagefault_key) | ||
8 | DECLARE_STATIC_KEY_FALSE(trace_resched_ipi_key); | ||
9 | #define trace_resched_ipi_enabled() \ | ||
10 | static_branch_unlikely(&trace_resched_ipi_key) | ||
11 | #else | ||
12 | static inline bool trace_pagefault_enabled(void) { return false; } | ||
13 | static inline bool trace_resched_ipi_enabled(void) { return false; } | ||
14 | #endif | ||
15 | |||
16 | #endif | ||
diff --git a/arch/x86/include/asm/trace/exceptions.h b/arch/x86/include/asm/trace/exceptions.h index 2422b14c50a7..5665bf205b8d 100644 --- a/arch/x86/include/asm/trace/exceptions.h +++ b/arch/x86/include/asm/trace/exceptions.h | |||
@@ -5,9 +5,10 @@ | |||
5 | #define _TRACE_PAGE_FAULT_H | 5 | #define _TRACE_PAGE_FAULT_H |
6 | 6 | ||
7 | #include <linux/tracepoint.h> | 7 | #include <linux/tracepoint.h> |
8 | #include <asm/trace/common.h> | ||
8 | 9 | ||
9 | extern int trace_irq_vector_regfunc(void); | 10 | extern int trace_pagefault_reg(void); |
10 | extern void trace_irq_vector_unregfunc(void); | 11 | extern void trace_pagefault_unreg(void); |
11 | 12 | ||
12 | DECLARE_EVENT_CLASS(x86_exceptions, | 13 | DECLARE_EVENT_CLASS(x86_exceptions, |
13 | 14 | ||
@@ -37,8 +38,7 @@ DEFINE_EVENT_FN(x86_exceptions, name, \ | |||
37 | TP_PROTO(unsigned long address, struct pt_regs *regs, \ | 38 | TP_PROTO(unsigned long address, struct pt_regs *regs, \ |
38 | unsigned long error_code), \ | 39 | unsigned long error_code), \ |
39 | TP_ARGS(address, regs, error_code), \ | 40 | TP_ARGS(address, regs, error_code), \ |
40 | trace_irq_vector_regfunc, \ | 41 | trace_pagefault_reg, trace_pagefault_unreg); |
41 | trace_irq_vector_unregfunc); | ||
42 | 42 | ||
43 | DEFINE_PAGE_FAULT_EVENT(page_fault_user); | 43 | DEFINE_PAGE_FAULT_EVENT(page_fault_user); |
44 | DEFINE_PAGE_FAULT_EVENT(page_fault_kernel); | 44 | DEFINE_PAGE_FAULT_EVENT(page_fault_kernel); |
diff --git a/arch/x86/include/asm/trace/irq_vectors.h b/arch/x86/include/asm/trace/irq_vectors.h index 32dd6a9e343c..1599d394c8c1 100644 --- a/arch/x86/include/asm/trace/irq_vectors.h +++ b/arch/x86/include/asm/trace/irq_vectors.h | |||
@@ -5,9 +5,12 @@ | |||
5 | #define _TRACE_IRQ_VECTORS_H | 5 | #define _TRACE_IRQ_VECTORS_H |
6 | 6 | ||
7 | #include <linux/tracepoint.h> | 7 | #include <linux/tracepoint.h> |
8 | #include <asm/trace/common.h> | ||
8 | 9 | ||
9 | extern int trace_irq_vector_regfunc(void); | 10 | #ifdef CONFIG_X86_LOCAL_APIC |
10 | extern void trace_irq_vector_unregfunc(void); | 11 | |
12 | extern int trace_resched_ipi_reg(void); | ||
13 | extern void trace_resched_ipi_unreg(void); | ||
11 | 14 | ||
12 | DECLARE_EVENT_CLASS(x86_irq_vector, | 15 | DECLARE_EVENT_CLASS(x86_irq_vector, |
13 | 16 | ||
@@ -28,15 +31,22 @@ DECLARE_EVENT_CLASS(x86_irq_vector, | |||
28 | #define DEFINE_IRQ_VECTOR_EVENT(name) \ | 31 | #define DEFINE_IRQ_VECTOR_EVENT(name) \ |
29 | DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \ | 32 | DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \ |
30 | TP_PROTO(int vector), \ | 33 | TP_PROTO(int vector), \ |
34 | TP_ARGS(vector), NULL, NULL); \ | ||
35 | DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ | ||
36 | TP_PROTO(int vector), \ | ||
37 | TP_ARGS(vector), NULL, NULL); | ||
38 | |||
39 | #define DEFINE_RESCHED_IPI_EVENT(name) \ | ||
40 | DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \ | ||
41 | TP_PROTO(int vector), \ | ||
31 | TP_ARGS(vector), \ | 42 | TP_ARGS(vector), \ |
32 | trace_irq_vector_regfunc, \ | 43 | trace_resched_ipi_reg, \ |
33 | trace_irq_vector_unregfunc); \ | 44 | trace_resched_ipi_unreg); \ |
34 | DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ | 45 | DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ |
35 | TP_PROTO(int vector), \ | 46 | TP_PROTO(int vector), \ |
36 | TP_ARGS(vector), \ | 47 | TP_ARGS(vector), \ |
37 | trace_irq_vector_regfunc, \ | 48 | trace_resched_ipi_reg, \ |
38 | trace_irq_vector_unregfunc); | 49 | trace_resched_ipi_unreg); |
39 | |||
40 | 50 | ||
41 | /* | 51 | /* |
42 | * local_timer - called when entering/exiting a local timer interrupt | 52 | * local_timer - called when entering/exiting a local timer interrupt |
@@ -45,11 +55,6 @@ DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \ | |||
45 | DEFINE_IRQ_VECTOR_EVENT(local_timer); | 55 | DEFINE_IRQ_VECTOR_EVENT(local_timer); |
46 | 56 | ||
47 | /* | 57 | /* |
48 | * reschedule - called when entering/exiting a reschedule vector handler | ||
49 | */ | ||
50 | DEFINE_IRQ_VECTOR_EVENT(reschedule); | ||
51 | |||
52 | /* | ||
53 | * spurious_apic - called when entering/exiting a spurious apic vector handler | 58 | * spurious_apic - called when entering/exiting a spurious apic vector handler |
54 | */ | 59 | */ |
55 | DEFINE_IRQ_VECTOR_EVENT(spurious_apic); | 60 | DEFINE_IRQ_VECTOR_EVENT(spurious_apic); |
@@ -65,6 +70,7 @@ DEFINE_IRQ_VECTOR_EVENT(error_apic); | |||
65 | */ | 70 | */ |
66 | DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi); | 71 | DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi); |
67 | 72 | ||
73 | #ifdef CONFIG_IRQ_WORK | ||
68 | /* | 74 | /* |
69 | * irq_work - called when entering/exiting a irq work interrupt | 75 | * irq_work - called when entering/exiting a irq work interrupt |
70 | * vector handler | 76 | * vector handler |
@@ -81,6 +87,18 @@ DEFINE_IRQ_VECTOR_EVENT(irq_work); | |||
81 | * 4) goto 1 | 87 | * 4) goto 1 |
82 | */ | 88 | */ |
83 | TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0); | 89 | TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0); |
90 | #endif | ||
91 | |||
92 | /* | ||
93 | * The ifdef is required because that tracepoint macro hell emits tracepoint | ||
94 | * code in files which include this header even if the tracepoint is not | ||
95 | * enabled. Brilliant stuff that. | ||
96 | */ | ||
97 | #ifdef CONFIG_SMP | ||
98 | /* | ||
99 | * reschedule - called when entering/exiting a reschedule vector handler | ||
100 | */ | ||
101 | DEFINE_RESCHED_IPI_EVENT(reschedule); | ||
84 | 102 | ||
85 | /* | 103 | /* |
86 | * call_function - called when entering/exiting a call function interrupt | 104 | * call_function - called when entering/exiting a call function interrupt |
@@ -93,24 +111,33 @@ DEFINE_IRQ_VECTOR_EVENT(call_function); | |||
93 | * single interrupt vector handler | 111 | * single interrupt vector handler |
94 | */ | 112 | */ |
95 | DEFINE_IRQ_VECTOR_EVENT(call_function_single); | 113 | DEFINE_IRQ_VECTOR_EVENT(call_function_single); |
114 | #endif | ||
96 | 115 | ||
116 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
97 | /* | 117 | /* |
98 | * threshold_apic - called when entering/exiting a threshold apic interrupt | 118 | * threshold_apic - called when entering/exiting a threshold apic interrupt |
99 | * vector handler | 119 | * vector handler |
100 | */ | 120 | */ |
101 | DEFINE_IRQ_VECTOR_EVENT(threshold_apic); | 121 | DEFINE_IRQ_VECTOR_EVENT(threshold_apic); |
122 | #endif | ||
102 | 123 | ||
124 | #ifdef CONFIG_X86_MCE_AMD | ||
103 | /* | 125 | /* |
104 | * deferred_error_apic - called when entering/exiting a deferred apic interrupt | 126 | * deferred_error_apic - called when entering/exiting a deferred apic interrupt |
105 | * vector handler | 127 | * vector handler |
106 | */ | 128 | */ |
107 | DEFINE_IRQ_VECTOR_EVENT(deferred_error_apic); | 129 | DEFINE_IRQ_VECTOR_EVENT(deferred_error_apic); |
130 | #endif | ||
108 | 131 | ||
132 | #ifdef CONFIG_X86_THERMAL_VECTOR | ||
109 | /* | 133 | /* |
110 | * thermal_apic - called when entering/exiting a thermal apic interrupt | 134 | * thermal_apic - called when entering/exiting a thermal apic interrupt |
111 | * vector handler | 135 | * vector handler |
112 | */ | 136 | */ |
113 | DEFINE_IRQ_VECTOR_EVENT(thermal_apic); | 137 | DEFINE_IRQ_VECTOR_EVENT(thermal_apic); |
138 | #endif | ||
139 | |||
140 | #endif /* CONFIG_X86_LOCAL_APIC */ | ||
114 | 141 | ||
115 | #undef TRACE_INCLUDE_PATH | 142 | #undef TRACE_INCLUDE_PATH |
116 | #define TRACE_INCLUDE_PATH . | 143 | #define TRACE_INCLUDE_PATH . |
diff --git a/arch/x86/include/asm/traps.h b/arch/x86/include/asm/traps.h index 01fd0a7f48cd..5545f6459bf5 100644 --- a/arch/x86/include/asm/traps.h +++ b/arch/x86/include/asm/traps.h | |||
@@ -13,9 +13,6 @@ asmlinkage void divide_error(void); | |||
13 | asmlinkage void debug(void); | 13 | asmlinkage void debug(void); |
14 | asmlinkage void nmi(void); | 14 | asmlinkage void nmi(void); |
15 | asmlinkage void int3(void); | 15 | asmlinkage void int3(void); |
16 | asmlinkage void xen_debug(void); | ||
17 | asmlinkage void xen_int3(void); | ||
18 | asmlinkage void xen_stack_segment(void); | ||
19 | asmlinkage void overflow(void); | 16 | asmlinkage void overflow(void); |
20 | asmlinkage void bounds(void); | 17 | asmlinkage void bounds(void); |
21 | asmlinkage void invalid_op(void); | 18 | asmlinkage void invalid_op(void); |
@@ -38,22 +35,29 @@ asmlinkage void machine_check(void); | |||
38 | #endif /* CONFIG_X86_MCE */ | 35 | #endif /* CONFIG_X86_MCE */ |
39 | asmlinkage void simd_coprocessor_error(void); | 36 | asmlinkage void simd_coprocessor_error(void); |
40 | 37 | ||
41 | #ifdef CONFIG_TRACING | 38 | #if defined(CONFIG_X86_64) && defined(CONFIG_XEN_PV) |
42 | asmlinkage void trace_page_fault(void); | 39 | asmlinkage void xen_divide_error(void); |
43 | #define trace_stack_segment stack_segment | 40 | asmlinkage void xen_xendebug(void); |
44 | #define trace_divide_error divide_error | 41 | asmlinkage void xen_xenint3(void); |
45 | #define trace_bounds bounds | 42 | asmlinkage void xen_nmi(void); |
46 | #define trace_invalid_op invalid_op | 43 | asmlinkage void xen_overflow(void); |
47 | #define trace_device_not_available device_not_available | 44 | asmlinkage void xen_bounds(void); |
48 | #define trace_coprocessor_segment_overrun coprocessor_segment_overrun | 45 | asmlinkage void xen_invalid_op(void); |
49 | #define trace_invalid_TSS invalid_TSS | 46 | asmlinkage void xen_device_not_available(void); |
50 | #define trace_segment_not_present segment_not_present | 47 | asmlinkage void xen_double_fault(void); |
51 | #define trace_general_protection general_protection | 48 | asmlinkage void xen_coprocessor_segment_overrun(void); |
52 | #define trace_spurious_interrupt_bug spurious_interrupt_bug | 49 | asmlinkage void xen_invalid_TSS(void); |
53 | #define trace_coprocessor_error coprocessor_error | 50 | asmlinkage void xen_segment_not_present(void); |
54 | #define trace_alignment_check alignment_check | 51 | asmlinkage void xen_stack_segment(void); |
55 | #define trace_simd_coprocessor_error simd_coprocessor_error | 52 | asmlinkage void xen_general_protection(void); |
56 | #define trace_async_page_fault async_page_fault | 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); | ||
57 | #endif | 61 | #endif |
58 | 62 | ||
59 | dotraplinkage void do_divide_error(struct pt_regs *, long); | 63 | dotraplinkage void do_divide_error(struct pt_regs *, long); |
@@ -74,14 +78,6 @@ asmlinkage struct pt_regs *sync_regs(struct pt_regs *); | |||
74 | #endif | 78 | #endif |
75 | dotraplinkage void do_general_protection(struct pt_regs *, long); | 79 | dotraplinkage void do_general_protection(struct pt_regs *, long); |
76 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); | 80 | dotraplinkage void do_page_fault(struct pt_regs *, unsigned long); |
77 | #ifdef CONFIG_TRACING | ||
78 | dotraplinkage void trace_do_page_fault(struct pt_regs *, unsigned long); | ||
79 | #else | ||
80 | static inline void trace_do_page_fault(struct pt_regs *regs, unsigned long error) | ||
81 | { | ||
82 | do_page_fault(regs, error); | ||
83 | } | ||
84 | #endif | ||
85 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); | 81 | dotraplinkage void do_spurious_interrupt_bug(struct pt_regs *, long); |
86 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); | 82 | dotraplinkage void do_coprocessor_error(struct pt_regs *, long); |
87 | dotraplinkage void do_alignment_check(struct pt_regs *, long); | 83 | dotraplinkage void do_alignment_check(struct pt_regs *, long); |
diff --git a/arch/x86/include/asm/xen/hypercall.h b/arch/x86/include/asm/xen/hypercall.h index 11071fcd630e..9606688caa4b 100644 --- a/arch/x86/include/asm/xen/hypercall.h +++ b/arch/x86/include/asm/xen/hypercall.h | |||
@@ -552,6 +552,8 @@ static inline void | |||
552 | MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr, | 552 | MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr, |
553 | struct desc_struct desc) | 553 | struct desc_struct desc) |
554 | { | 554 | { |
555 | u32 *p = (u32 *) &desc; | ||
556 | |||
555 | mcl->op = __HYPERVISOR_update_descriptor; | 557 | mcl->op = __HYPERVISOR_update_descriptor; |
556 | if (sizeof(maddr) == sizeof(long)) { | 558 | if (sizeof(maddr) == sizeof(long)) { |
557 | mcl->args[0] = maddr; | 559 | mcl->args[0] = maddr; |
@@ -559,8 +561,8 @@ MULTI_update_descriptor(struct multicall_entry *mcl, u64 maddr, | |||
559 | } else { | 561 | } else { |
560 | mcl->args[0] = maddr; | 562 | mcl->args[0] = maddr; |
561 | mcl->args[1] = maddr >> 32; | 563 | mcl->args[1] = maddr >> 32; |
562 | mcl->args[2] = desc.a; | 564 | mcl->args[2] = *p++; |
563 | mcl->args[3] = desc.b; | 565 | mcl->args[3] = *p; |
564 | } | 566 | } |
565 | 567 | ||
566 | trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4); | 568 | trace_xen_mc_entry(mcl, sizeof(maddr) == sizeof(long) ? 2 : 4); |
diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 287eac7d207f..fd0a7895b63f 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile | |||
@@ -42,7 +42,7 @@ CFLAGS_irq.o := -I$(src)/../include/asm/trace | |||
42 | 42 | ||
43 | obj-y := process_$(BITS).o signal.o | 43 | obj-y := process_$(BITS).o signal.o |
44 | obj-$(CONFIG_COMPAT) += signal_compat.o | 44 | obj-$(CONFIG_COMPAT) += signal_compat.o |
45 | obj-y += traps.o irq.o irq_$(BITS).o dumpstack_$(BITS).o | 45 | obj-y += traps.o idt.o irq.o irq_$(BITS).o dumpstack_$(BITS).o |
46 | obj-y += time.o ioport.o dumpstack.o nmi.o | 46 | obj-y += time.o ioport.o dumpstack.o nmi.o |
47 | obj-$(CONFIG_MODIFY_LDT_SYSCALL) += ldt.o | 47 | obj-$(CONFIG_MODIFY_LDT_SYSCALL) += ldt.o |
48 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o | 48 | obj-y += setup.o x86_init.o i8259.o irqinit.o jump_label.o |
@@ -111,6 +111,7 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= paravirt-spinlocks.o | |||
111 | obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o | 111 | obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o |
112 | obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o | 112 | obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o |
113 | 113 | ||
114 | obj-$(CONFIG_EISA) += eisa.o | ||
114 | obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o | 115 | obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o |
115 | 116 | ||
116 | obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o | 117 | obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o |
diff --git a/arch/x86/kernel/apic/apic.c b/arch/x86/kernel/apic/apic.c index 98b3dd8cf2bf..7834f73efbf1 100644 --- a/arch/x86/kernel/apic/apic.c +++ b/arch/x86/kernel/apic/apic.c | |||
@@ -177,8 +177,6 @@ static int disable_apic_timer __initdata; | |||
177 | int local_apic_timer_c2_ok; | 177 | int local_apic_timer_c2_ok; |
178 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); | 178 | EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); |
179 | 179 | ||
180 | int first_system_vector = FIRST_SYSTEM_VECTOR; | ||
181 | |||
182 | /* | 180 | /* |
183 | * Debug level, exported for io_apic.c | 181 | * Debug level, exported for io_apic.c |
184 | */ | 182 | */ |
@@ -599,9 +597,13 @@ static const struct x86_cpu_id deadline_match[] = { | |||
599 | 597 | ||
600 | static void apic_check_deadline_errata(void) | 598 | static void apic_check_deadline_errata(void) |
601 | { | 599 | { |
602 | const struct x86_cpu_id *m = x86_match_cpu(deadline_match); | 600 | const struct x86_cpu_id *m; |
603 | u32 rev; | 601 | u32 rev; |
604 | 602 | ||
603 | if (!boot_cpu_has(X86_FEATURE_TSC_DEADLINE_TIMER)) | ||
604 | return; | ||
605 | |||
606 | m = x86_match_cpu(deadline_match); | ||
605 | if (!m) | 607 | if (!m) |
606 | return; | 608 | return; |
607 | 609 | ||
@@ -990,8 +992,7 @@ void setup_secondary_APIC_clock(void) | |||
990 | */ | 992 | */ |
991 | static void local_apic_timer_interrupt(void) | 993 | static void local_apic_timer_interrupt(void) |
992 | { | 994 | { |
993 | int cpu = smp_processor_id(); | 995 | struct clock_event_device *evt = this_cpu_ptr(&lapic_events); |
994 | struct clock_event_device *evt = &per_cpu(lapic_events, cpu); | ||
995 | 996 | ||
996 | /* | 997 | /* |
997 | * Normally we should not be here till LAPIC has been initialized but | 998 | * Normally we should not be here till LAPIC has been initialized but |
@@ -1005,7 +1006,8 @@ static void local_apic_timer_interrupt(void) | |||
1005 | * spurious. | 1006 | * spurious. |
1006 | */ | 1007 | */ |
1007 | if (!evt->event_handler) { | 1008 | if (!evt->event_handler) { |
1008 | pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu); | 1009 | pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", |
1010 | smp_processor_id()); | ||
1009 | /* Switch it off */ | 1011 | /* Switch it off */ |
1010 | lapic_timer_shutdown(evt); | 1012 | lapic_timer_shutdown(evt); |
1011 | return; | 1013 | return; |
@@ -1040,25 +1042,6 @@ __visible void __irq_entry smp_apic_timer_interrupt(struct pt_regs *regs) | |||
1040 | * interrupt lock, which is the WrongThing (tm) to do. | 1042 | * interrupt lock, which is the WrongThing (tm) to do. |
1041 | */ | 1043 | */ |
1042 | entering_ack_irq(); | 1044 | entering_ack_irq(); |
1043 | local_apic_timer_interrupt(); | ||
1044 | exiting_irq(); | ||
1045 | |||
1046 | set_irq_regs(old_regs); | ||
1047 | } | ||
1048 | |||
1049 | __visible void __irq_entry smp_trace_apic_timer_interrupt(struct pt_regs *regs) | ||
1050 | { | ||
1051 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
1052 | |||
1053 | /* | ||
1054 | * NOTE! We'd better ACK the irq immediately, | ||
1055 | * because timer handling can be slow. | ||
1056 | * | ||
1057 | * update_process_times() expects us to have done irq_enter(). | ||
1058 | * Besides, if we don't timer interrupts ignore the global | ||
1059 | * interrupt lock, which is the WrongThing (tm) to do. | ||
1060 | */ | ||
1061 | entering_ack_irq(); | ||
1062 | trace_local_timer_entry(LOCAL_TIMER_VECTOR); | 1045 | trace_local_timer_entry(LOCAL_TIMER_VECTOR); |
1063 | local_apic_timer_interrupt(); | 1046 | local_apic_timer_interrupt(); |
1064 | trace_local_timer_exit(LOCAL_TIMER_VECTOR); | 1047 | trace_local_timer_exit(LOCAL_TIMER_VECTOR); |
@@ -1920,10 +1903,14 @@ void __init register_lapic_address(unsigned long address) | |||
1920 | /* | 1903 | /* |
1921 | * This interrupt should _never_ happen with our APIC/SMP architecture | 1904 | * This interrupt should _never_ happen with our APIC/SMP architecture |
1922 | */ | 1905 | */ |
1923 | static void __smp_spurious_interrupt(u8 vector) | 1906 | __visible void __irq_entry smp_spurious_interrupt(struct pt_regs *regs) |
1924 | { | 1907 | { |
1908 | u8 vector = ~regs->orig_ax; | ||
1925 | u32 v; | 1909 | u32 v; |
1926 | 1910 | ||
1911 | entering_irq(); | ||
1912 | trace_spurious_apic_entry(vector); | ||
1913 | |||
1927 | /* | 1914 | /* |
1928 | * Check if this really is a spurious interrupt and ACK it | 1915 | * Check if this really is a spurious interrupt and ACK it |
1929 | * if it is a vectored one. Just in case... | 1916 | * if it is a vectored one. Just in case... |
@@ -1938,22 +1925,7 @@ static void __smp_spurious_interrupt(u8 vector) | |||
1938 | /* see sw-dev-man vol 3, chapter 7.4.13.5 */ | 1925 | /* see sw-dev-man vol 3, chapter 7.4.13.5 */ |
1939 | pr_info("spurious APIC interrupt through vector %02x on CPU#%d, " | 1926 | pr_info("spurious APIC interrupt through vector %02x on CPU#%d, " |
1940 | "should never happen.\n", vector, smp_processor_id()); | 1927 | "should never happen.\n", vector, smp_processor_id()); |
1941 | } | ||
1942 | 1928 | ||
1943 | __visible void __irq_entry smp_spurious_interrupt(struct pt_regs *regs) | ||
1944 | { | ||
1945 | entering_irq(); | ||
1946 | __smp_spurious_interrupt(~regs->orig_ax); | ||
1947 | exiting_irq(); | ||
1948 | } | ||
1949 | |||
1950 | __visible void __irq_entry smp_trace_spurious_interrupt(struct pt_regs *regs) | ||
1951 | { | ||
1952 | u8 vector = ~regs->orig_ax; | ||
1953 | |||
1954 | entering_irq(); | ||
1955 | trace_spurious_apic_entry(vector); | ||
1956 | __smp_spurious_interrupt(vector); | ||
1957 | trace_spurious_apic_exit(vector); | 1929 | trace_spurious_apic_exit(vector); |
1958 | exiting_irq(); | 1930 | exiting_irq(); |
1959 | } | 1931 | } |
@@ -1961,10 +1933,8 @@ __visible void __irq_entry smp_trace_spurious_interrupt(struct pt_regs *regs) | |||
1961 | /* | 1933 | /* |
1962 | * This interrupt should never happen with our APIC/SMP architecture | 1934 | * This interrupt should never happen with our APIC/SMP architecture |
1963 | */ | 1935 | */ |
1964 | static void __smp_error_interrupt(struct pt_regs *regs) | 1936 | __visible void __irq_entry smp_error_interrupt(struct pt_regs *regs) |
1965 | { | 1937 | { |
1966 | u32 v; | ||
1967 | u32 i = 0; | ||
1968 | static const char * const error_interrupt_reason[] = { | 1938 | static const char * const error_interrupt_reason[] = { |
1969 | "Send CS error", /* APIC Error Bit 0 */ | 1939 | "Send CS error", /* APIC Error Bit 0 */ |
1970 | "Receive CS error", /* APIC Error Bit 1 */ | 1940 | "Receive CS error", /* APIC Error Bit 1 */ |
@@ -1975,6 +1945,10 @@ static void __smp_error_interrupt(struct pt_regs *regs) | |||
1975 | "Received illegal vector", /* APIC Error Bit 6 */ | 1945 | "Received illegal vector", /* APIC Error Bit 6 */ |
1976 | "Illegal register address", /* APIC Error Bit 7 */ | 1946 | "Illegal register address", /* APIC Error Bit 7 */ |
1977 | }; | 1947 | }; |
1948 | u32 v, i = 0; | ||
1949 | |||
1950 | entering_irq(); | ||
1951 | trace_error_apic_entry(ERROR_APIC_VECTOR); | ||
1978 | 1952 | ||
1979 | /* First tickle the hardware, only then report what went on. -- REW */ | 1953 | /* First tickle the hardware, only then report what went on. -- REW */ |
1980 | if (lapic_get_maxlvt() > 3) /* Due to the Pentium erratum 3AP. */ | 1954 | if (lapic_get_maxlvt() > 3) /* Due to the Pentium erratum 3AP. */ |
@@ -1996,20 +1970,6 @@ static void __smp_error_interrupt(struct pt_regs *regs) | |||
1996 | 1970 | ||
1997 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); | 1971 | apic_printk(APIC_DEBUG, KERN_CONT "\n"); |
1998 | 1972 | ||
1999 | } | ||
2000 | |||
2001 | __visible void __irq_entry smp_error_interrupt(struct pt_regs *regs) | ||
2002 | { | ||
2003 | entering_irq(); | ||
2004 | __smp_error_interrupt(regs); | ||
2005 | exiting_irq(); | ||
2006 | } | ||
2007 | |||
2008 | __visible void __irq_entry smp_trace_error_interrupt(struct pt_regs *regs) | ||
2009 | { | ||
2010 | entering_irq(); | ||
2011 | trace_error_apic_entry(ERROR_APIC_VECTOR); | ||
2012 | __smp_error_interrupt(regs); | ||
2013 | trace_error_apic_exit(ERROR_APIC_VECTOR); | 1973 | trace_error_apic_exit(ERROR_APIC_VECTOR); |
2014 | exiting_irq(); | 1974 | exiting_irq(); |
2015 | } | 1975 | } |
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c index 237e9c2341c7..70e48aa6af98 100644 --- a/arch/x86/kernel/apic/io_apic.c +++ b/arch/x86/kernel/apic/io_apic.c | |||
@@ -1243,7 +1243,7 @@ static void io_apic_print_entries(unsigned int apic, unsigned int nr_entries) | |||
1243 | entry.vector, entry.irr, entry.delivery_status); | 1243 | entry.vector, entry.irr, entry.delivery_status); |
1244 | if (ir_entry->format) | 1244 | if (ir_entry->format) |
1245 | printk(KERN_DEBUG "%s, remapped, I(%04X), Z(%X)\n", | 1245 | printk(KERN_DEBUG "%s, remapped, I(%04X), Z(%X)\n", |
1246 | buf, (ir_entry->index << 15) | ir_entry->index, | 1246 | buf, (ir_entry->index2 << 15) | ir_entry->index, |
1247 | ir_entry->zero); | 1247 | ir_entry->zero); |
1248 | else | 1248 | else |
1249 | printk(KERN_DEBUG "%s, %s, D(%02X), M(%1d)\n", | 1249 | printk(KERN_DEBUG "%s, %s, D(%02X), M(%1d)\n", |
diff --git a/arch/x86/kernel/apic/vector.c b/arch/x86/kernel/apic/vector.c index b3af457ed667..88c214e75a6b 100644 --- a/arch/x86/kernel/apic/vector.c +++ b/arch/x86/kernel/apic/vector.c | |||
@@ -166,7 +166,7 @@ static int __assign_irq_vector(int irq, struct apic_chip_data *d, | |||
166 | offset = current_offset; | 166 | offset = current_offset; |
167 | next: | 167 | next: |
168 | vector += 16; | 168 | vector += 16; |
169 | if (vector >= first_system_vector) { | 169 | if (vector >= FIRST_SYSTEM_VECTOR) { |
170 | offset = (offset + 1) % 16; | 170 | offset = (offset + 1) % 16; |
171 | vector = FIRST_EXTERNAL_VECTOR + offset; | 171 | vector = FIRST_EXTERNAL_VECTOR + offset; |
172 | } | 172 | } |
diff --git a/arch/x86/kernel/asm-offsets_64.c b/arch/x86/kernel/asm-offsets_64.c index 99332f550c48..cf42206926af 100644 --- a/arch/x86/kernel/asm-offsets_64.c +++ b/arch/x86/kernel/asm-offsets_64.c | |||
@@ -20,7 +20,6 @@ static char syscalls_ia32[] = { | |||
20 | int main(void) | 20 | int main(void) |
21 | { | 21 | { |
22 | #ifdef CONFIG_PARAVIRT | 22 | #ifdef CONFIG_PARAVIRT |
23 | OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame); | ||
24 | OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64); | 23 | OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64); |
25 | OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs); | 24 | OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs); |
26 | BLANK(); | 25 | BLANK(); |
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c index b95cd94ca97b..efba8e3da3e2 100644 --- a/arch/x86/kernel/cpu/common.c +++ b/arch/x86/kernel/cpu/common.c | |||
@@ -1329,15 +1329,6 @@ static __init int setup_disablecpuid(char *arg) | |||
1329 | __setup("clearcpuid=", setup_disablecpuid); | 1329 | __setup("clearcpuid=", setup_disablecpuid); |
1330 | 1330 | ||
1331 | #ifdef CONFIG_X86_64 | 1331 | #ifdef CONFIG_X86_64 |
1332 | struct desc_ptr idt_descr __ro_after_init = { | ||
1333 | .size = NR_VECTORS * 16 - 1, | ||
1334 | .address = (unsigned long) idt_table, | ||
1335 | }; | ||
1336 | const struct desc_ptr debug_idt_descr = { | ||
1337 | .size = NR_VECTORS * 16 - 1, | ||
1338 | .address = (unsigned long) debug_idt_table, | ||
1339 | }; | ||
1340 | |||
1341 | DEFINE_PER_CPU_FIRST(union irq_stack_union, | 1332 | DEFINE_PER_CPU_FIRST(union irq_stack_union, |
1342 | irq_stack_union) __aligned(PAGE_SIZE) __visible; | 1333 | irq_stack_union) __aligned(PAGE_SIZE) __visible; |
1343 | 1334 | ||
diff --git a/arch/x86/kernel/cpu/mcheck/mce_amd.c b/arch/x86/kernel/cpu/mcheck/mce_amd.c index 5ce1a5689162..40e28ed77fbf 100644 --- a/arch/x86/kernel/cpu/mcheck/mce_amd.c +++ b/arch/x86/kernel/cpu/mcheck/mce_amd.c | |||
@@ -771,24 +771,12 @@ static void __log_error(unsigned int bank, u64 status, u64 addr, u64 misc) | |||
771 | mce_log(&m); | 771 | mce_log(&m); |
772 | } | 772 | } |
773 | 773 | ||
774 | static inline void __smp_deferred_error_interrupt(void) | ||
775 | { | ||
776 | inc_irq_stat(irq_deferred_error_count); | ||
777 | deferred_error_int_vector(); | ||
778 | } | ||
779 | |||
780 | asmlinkage __visible void __irq_entry smp_deferred_error_interrupt(void) | 774 | asmlinkage __visible void __irq_entry smp_deferred_error_interrupt(void) |
781 | { | 775 | { |
782 | entering_irq(); | 776 | entering_irq(); |
783 | __smp_deferred_error_interrupt(); | ||
784 | exiting_ack_irq(); | ||
785 | } | ||
786 | |||
787 | asmlinkage __visible void __irq_entry smp_trace_deferred_error_interrupt(void) | ||
788 | { | ||
789 | entering_irq(); | ||
790 | trace_deferred_error_apic_entry(DEFERRED_ERROR_VECTOR); | 777 | trace_deferred_error_apic_entry(DEFERRED_ERROR_VECTOR); |
791 | __smp_deferred_error_interrupt(); | 778 | inc_irq_stat(irq_deferred_error_count); |
779 | deferred_error_int_vector(); | ||
792 | trace_deferred_error_apic_exit(DEFERRED_ERROR_VECTOR); | 780 | trace_deferred_error_apic_exit(DEFERRED_ERROR_VECTOR); |
793 | exiting_ack_irq(); | 781 | exiting_ack_irq(); |
794 | } | 782 | } |
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c index f7370abd33c6..2da67b70ba98 100644 --- a/arch/x86/kernel/cpu/mcheck/therm_throt.c +++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c | |||
@@ -390,26 +390,12 @@ static void unexpected_thermal_interrupt(void) | |||
390 | 390 | ||
391 | static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt; | 391 | static void (*smp_thermal_vector)(void) = unexpected_thermal_interrupt; |
392 | 392 | ||
393 | static inline void __smp_thermal_interrupt(void) | 393 | asmlinkage __visible void __irq_entry smp_thermal_interrupt(struct pt_regs *r) |
394 | { | ||
395 | inc_irq_stat(irq_thermal_count); | ||
396 | smp_thermal_vector(); | ||
397 | } | ||
398 | |||
399 | asmlinkage __visible void __irq_entry | ||
400 | smp_thermal_interrupt(struct pt_regs *regs) | ||
401 | { | ||
402 | entering_irq(); | ||
403 | __smp_thermal_interrupt(); | ||
404 | exiting_ack_irq(); | ||
405 | } | ||
406 | |||
407 | asmlinkage __visible void __irq_entry | ||
408 | smp_trace_thermal_interrupt(struct pt_regs *regs) | ||
409 | { | 394 | { |
410 | entering_irq(); | 395 | entering_irq(); |
411 | trace_thermal_apic_entry(THERMAL_APIC_VECTOR); | 396 | trace_thermal_apic_entry(THERMAL_APIC_VECTOR); |
412 | __smp_thermal_interrupt(); | 397 | inc_irq_stat(irq_thermal_count); |
398 | smp_thermal_vector(); | ||
413 | trace_thermal_apic_exit(THERMAL_APIC_VECTOR); | 399 | trace_thermal_apic_exit(THERMAL_APIC_VECTOR); |
414 | exiting_ack_irq(); | 400 | exiting_ack_irq(); |
415 | } | 401 | } |
diff --git a/arch/x86/kernel/cpu/mcheck/threshold.c b/arch/x86/kernel/cpu/mcheck/threshold.c index bb0e75eed10a..5e7249e42f8f 100644 --- a/arch/x86/kernel/cpu/mcheck/threshold.c +++ b/arch/x86/kernel/cpu/mcheck/threshold.c | |||
@@ -17,24 +17,12 @@ static void default_threshold_interrupt(void) | |||
17 | 17 | ||
18 | void (*mce_threshold_vector)(void) = default_threshold_interrupt; | 18 | void (*mce_threshold_vector)(void) = default_threshold_interrupt; |
19 | 19 | ||
20 | static inline void __smp_threshold_interrupt(void) | ||
21 | { | ||
22 | inc_irq_stat(irq_threshold_count); | ||
23 | mce_threshold_vector(); | ||
24 | } | ||
25 | |||
26 | asmlinkage __visible void __irq_entry smp_threshold_interrupt(void) | 20 | asmlinkage __visible void __irq_entry smp_threshold_interrupt(void) |
27 | { | 21 | { |
28 | entering_irq(); | 22 | entering_irq(); |
29 | __smp_threshold_interrupt(); | ||
30 | exiting_ack_irq(); | ||
31 | } | ||
32 | |||
33 | asmlinkage __visible void __irq_entry smp_trace_threshold_interrupt(void) | ||
34 | { | ||
35 | entering_irq(); | ||
36 | trace_threshold_apic_entry(THRESHOLD_APIC_VECTOR); | 23 | trace_threshold_apic_entry(THRESHOLD_APIC_VECTOR); |
37 | __smp_threshold_interrupt(); | 24 | inc_irq_stat(irq_threshold_count); |
25 | mce_threshold_vector(); | ||
38 | trace_threshold_apic_exit(THRESHOLD_APIC_VECTOR); | 26 | trace_threshold_apic_exit(THRESHOLD_APIC_VECTOR); |
39 | exiting_ack_irq(); | 27 | exiting_ack_irq(); |
40 | } | 28 | } |
diff --git a/arch/x86/kernel/cpu/mshyperv.c b/arch/x86/kernel/cpu/mshyperv.c index 70e717fccdd6..9fc32651c911 100644 --- a/arch/x86/kernel/cpu/mshyperv.c +++ b/arch/x86/kernel/cpu/mshyperv.c | |||
@@ -59,13 +59,8 @@ void hyperv_vector_handler(struct pt_regs *regs) | |||
59 | void hv_setup_vmbus_irq(void (*handler)(void)) | 59 | void hv_setup_vmbus_irq(void (*handler)(void)) |
60 | { | 60 | { |
61 | vmbus_handler = handler; | 61 | vmbus_handler = handler; |
62 | /* | 62 | /* Setup the IDT for hypervisor callback */ |
63 | * Setup the IDT for hypervisor callback. Prevent reallocation | 63 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, hyperv_callback_vector); |
64 | * at module reload. | ||
65 | */ | ||
66 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) | ||
67 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, | ||
68 | hyperv_callback_vector); | ||
69 | } | 64 | } |
70 | 65 | ||
71 | void hv_remove_vmbus_irq(void) | 66 | void hv_remove_vmbus_irq(void) |
diff --git a/arch/x86/kernel/eisa.c b/arch/x86/kernel/eisa.c new file mode 100644 index 000000000000..f260e452e4f8 --- /dev/null +++ b/arch/x86/kernel/eisa.c | |||
@@ -0,0 +1,19 @@ | |||
1 | /* | ||
2 | * EISA specific code | ||
3 | * | ||
4 | * This file is licensed under the GPL V2 | ||
5 | */ | ||
6 | #include <linux/ioport.h> | ||
7 | #include <linux/eisa.h> | ||
8 | #include <linux/io.h> | ||
9 | |||
10 | static __init int eisa_bus_probe(void) | ||
11 | { | ||
12 | void __iomem *p = ioremap(0x0FFFD9, 4); | ||
13 | |||
14 | if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24)) | ||
15 | EISA_bus = 1; | ||
16 | iounmap(p); | ||
17 | return 0; | ||
18 | } | ||
19 | subsys_initcall(eisa_bus_probe); | ||
diff --git a/arch/x86/kernel/head32.c b/arch/x86/kernel/head32.c index 538ec012b371..cf2ce063f65a 100644 --- a/arch/x86/kernel/head32.c +++ b/arch/x86/kernel/head32.c | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/memblock.h> | 11 | #include <linux/memblock.h> |
12 | 12 | ||
13 | #include <asm/desc.h> | ||
13 | #include <asm/setup.h> | 14 | #include <asm/setup.h> |
14 | #include <asm/sections.h> | 15 | #include <asm/sections.h> |
15 | #include <asm/e820/api.h> | 16 | #include <asm/e820/api.h> |
@@ -30,6 +31,9 @@ static void __init i386_default_early_setup(void) | |||
30 | asmlinkage __visible void __init i386_start_kernel(void) | 31 | asmlinkage __visible void __init i386_start_kernel(void) |
31 | { | 32 | { |
32 | cr4_init_shadow(); | 33 | cr4_init_shadow(); |
34 | |||
35 | idt_setup_early_handler(); | ||
36 | |||
33 | sanitize_boot_params(&boot_params); | 37 | sanitize_boot_params(&boot_params); |
34 | 38 | ||
35 | x86_early_init_platform_quirks(); | 39 | x86_early_init_platform_quirks(); |
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c index 6a193b93fd95..bab4fa579450 100644 --- a/arch/x86/kernel/head64.c +++ b/arch/x86/kernel/head64.c | |||
@@ -311,8 +311,6 @@ static void __init copy_bootdata(char *real_mode_data) | |||
311 | 311 | ||
312 | asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) | 312 | asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) |
313 | { | 313 | { |
314 | int i; | ||
315 | |||
316 | /* | 314 | /* |
317 | * Build-time sanity checks on the kernel image and module | 315 | * Build-time sanity checks on the kernel image and module |
318 | * area mappings. (these are purely build-time and produce no code) | 316 | * area mappings. (these are purely build-time and produce no code) |
@@ -345,9 +343,7 @@ asmlinkage __visible void __init x86_64_start_kernel(char * real_mode_data) | |||
345 | 343 | ||
346 | kasan_early_init(); | 344 | kasan_early_init(); |
347 | 345 | ||
348 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) | 346 | idt_setup_early_handler(); |
349 | set_intr_gate(i, early_idt_handler_array[i]); | ||
350 | load_idt((const struct desc_ptr *)&idt_descr); | ||
351 | 347 | ||
352 | copy_bootdata(__va(real_mode_data)); | 348 | copy_bootdata(__va(real_mode_data)); |
353 | 349 | ||
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S index 29da9599fec0..9ed3074d0d27 100644 --- a/arch/x86/kernel/head_32.S +++ b/arch/x86/kernel/head_32.S | |||
@@ -345,7 +345,6 @@ ENTRY(startup_32_smp) | |||
345 | movl %eax,%cr0 | 345 | movl %eax,%cr0 |
346 | 346 | ||
347 | lgdt early_gdt_descr | 347 | lgdt early_gdt_descr |
348 | lidt idt_descr | ||
349 | ljmp $(__KERNEL_CS),$1f | 348 | ljmp $(__KERNEL_CS),$1f |
350 | 1: movl $(__KERNEL_DS),%eax # reload all the segment registers | 349 | 1: movl $(__KERNEL_DS),%eax # reload all the segment registers |
351 | movl %eax,%ss # after changing gdt. | 350 | movl %eax,%ss # after changing gdt. |
@@ -378,37 +377,6 @@ ENDPROC(startup_32_smp) | |||
378 | */ | 377 | */ |
379 | __INIT | 378 | __INIT |
380 | setup_once: | 379 | setup_once: |
381 | /* | ||
382 | * Set up a idt with 256 interrupt gates that push zero if there | ||
383 | * is no error code and then jump to early_idt_handler_common. | ||
384 | * It doesn't actually load the idt - that needs to be done on | ||
385 | * each CPU. Interrupts are enabled elsewhere, when we can be | ||
386 | * relatively sure everything is ok. | ||
387 | */ | ||
388 | |||
389 | movl $idt_table,%edi | ||
390 | movl $early_idt_handler_array,%eax | ||
391 | movl $NUM_EXCEPTION_VECTORS,%ecx | ||
392 | 1: | ||
393 | movl %eax,(%edi) | ||
394 | movl %eax,4(%edi) | ||
395 | /* interrupt gate, dpl=0, present */ | ||
396 | movl $(0x8E000000 + __KERNEL_CS),2(%edi) | ||
397 | addl $EARLY_IDT_HANDLER_SIZE,%eax | ||
398 | addl $8,%edi | ||
399 | loop 1b | ||
400 | |||
401 | movl $256 - NUM_EXCEPTION_VECTORS,%ecx | ||
402 | movl $ignore_int,%edx | ||
403 | movl $(__KERNEL_CS << 16),%eax | ||
404 | movw %dx,%ax /* selector = 0x0010 = cs */ | ||
405 | movw $0x8E00,%dx /* interrupt gate - dpl=0, present */ | ||
406 | 2: | ||
407 | movl %eax,(%edi) | ||
408 | movl %edx,4(%edi) | ||
409 | addl $8,%edi | ||
410 | loop 2b | ||
411 | |||
412 | #ifdef CONFIG_CC_STACKPROTECTOR | 380 | #ifdef CONFIG_CC_STACKPROTECTOR |
413 | /* | 381 | /* |
414 | * Configure the stack canary. The linker can't handle this by | 382 | * Configure the stack canary. The linker can't handle this by |
@@ -497,8 +465,7 @@ early_idt_handler_common: | |||
497 | ENDPROC(early_idt_handler_common) | 465 | ENDPROC(early_idt_handler_common) |
498 | 466 | ||
499 | /* This is the default interrupt "handler" :-) */ | 467 | /* This is the default interrupt "handler" :-) */ |
500 | ALIGN | 468 | ENTRY(early_ignore_irq) |
501 | ignore_int: | ||
502 | cld | 469 | cld |
503 | #ifdef CONFIG_PRINTK | 470 | #ifdef CONFIG_PRINTK |
504 | pushl %eax | 471 | pushl %eax |
@@ -533,7 +500,8 @@ ignore_int: | |||
533 | hlt_loop: | 500 | hlt_loop: |
534 | hlt | 501 | hlt |
535 | jmp hlt_loop | 502 | jmp hlt_loop |
536 | ENDPROC(ignore_int) | 503 | ENDPROC(early_ignore_irq) |
504 | |||
537 | __INITDATA | 505 | __INITDATA |
538 | .align 4 | 506 | .align 4 |
539 | GLOBAL(early_recursion_flag) | 507 | GLOBAL(early_recursion_flag) |
@@ -622,7 +590,6 @@ int_msg: | |||
622 | 590 | ||
623 | .data | 591 | .data |
624 | .globl boot_gdt_descr | 592 | .globl boot_gdt_descr |
625 | .globl idt_descr | ||
626 | 593 | ||
627 | ALIGN | 594 | ALIGN |
628 | # early boot GDT descriptor (must use 1:1 address mapping) | 595 | # early boot GDT descriptor (must use 1:1 address mapping) |
@@ -631,11 +598,6 @@ boot_gdt_descr: | |||
631 | .word __BOOT_DS+7 | 598 | .word __BOOT_DS+7 |
632 | .long boot_gdt - __PAGE_OFFSET | 599 | .long boot_gdt - __PAGE_OFFSET |
633 | 600 | ||
634 | .word 0 # 32-bit align idt_desc.address | ||
635 | idt_descr: | ||
636 | .word IDT_ENTRIES*8-1 # idt contains 256 entries | ||
637 | .long idt_table | ||
638 | |||
639 | # boot GDT descriptor (later on used by CPU#0): | 601 | # boot GDT descriptor (later on used by CPU#0): |
640 | .word 0 # 32 bit align gdt_desc.address | 602 | .word 0 # 32 bit align gdt_desc.address |
641 | ENTRY(early_gdt_descr) | 603 | ENTRY(early_gdt_descr) |
diff --git a/arch/x86/kernel/idt.c b/arch/x86/kernel/idt.c new file mode 100644 index 000000000000..6107ee1cb8d5 --- /dev/null +++ b/arch/x86/kernel/idt.c | |||
@@ -0,0 +1,371 @@ | |||
1 | /* | ||
2 | * Interrupt descriptor table related code | ||
3 | * | ||
4 | * This file is licensed under the GPL V2 | ||
5 | */ | ||
6 | #include <linux/interrupt.h> | ||
7 | |||
8 | #include <asm/traps.h> | ||
9 | #include <asm/proto.h> | ||
10 | #include <asm/desc.h> | ||
11 | |||
12 | struct idt_data { | ||
13 | unsigned int vector; | ||
14 | unsigned int segment; | ||
15 | struct idt_bits bits; | ||
16 | const void *addr; | ||
17 | }; | ||
18 | |||
19 | #define DPL0 0x0 | ||
20 | #define DPL3 0x3 | ||
21 | |||
22 | #define DEFAULT_STACK 0 | ||
23 | |||
24 | #define G(_vector, _addr, _ist, _type, _dpl, _segment) \ | ||
25 | { \ | ||
26 | .vector = _vector, \ | ||
27 | .bits.ist = _ist, \ | ||
28 | .bits.type = _type, \ | ||
29 | .bits.dpl = _dpl, \ | ||
30 | .bits.p = 1, \ | ||
31 | .addr = _addr, \ | ||
32 | .segment = _segment, \ | ||
33 | } | ||
34 | |||
35 | /* Interrupt gate */ | ||
36 | #define INTG(_vector, _addr) \ | ||
37 | G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL0, __KERNEL_CS) | ||
38 | |||
39 | /* System interrupt gate */ | ||
40 | #define SYSG(_vector, _addr) \ | ||
41 | G(_vector, _addr, DEFAULT_STACK, GATE_INTERRUPT, DPL3, __KERNEL_CS) | ||
42 | |||
43 | /* Interrupt gate with interrupt stack */ | ||
44 | #define ISTG(_vector, _addr, _ist) \ | ||
45 | G(_vector, _addr, _ist, GATE_INTERRUPT, DPL0, __KERNEL_CS) | ||
46 | |||
47 | /* System interrupt gate with interrupt stack */ | ||
48 | #define SISTG(_vector, _addr, _ist) \ | ||
49 | G(_vector, _addr, _ist, GATE_INTERRUPT, DPL3, __KERNEL_CS) | ||
50 | |||
51 | /* Task gate */ | ||
52 | #define TSKG(_vector, _gdt) \ | ||
53 | G(_vector, NULL, DEFAULT_STACK, GATE_TASK, DPL0, _gdt << 3) | ||
54 | |||
55 | /* | ||
56 | * Early traps running on the DEFAULT_STACK because the other interrupt | ||
57 | * stacks work only after cpu_init(). | ||
58 | */ | ||
59 | static const __initdata struct idt_data early_idts[] = { | ||
60 | INTG(X86_TRAP_DB, debug), | ||
61 | SYSG(X86_TRAP_BP, int3), | ||
62 | #ifdef CONFIG_X86_32 | ||
63 | INTG(X86_TRAP_PF, page_fault), | ||
64 | #endif | ||
65 | }; | ||
66 | |||
67 | /* | ||
68 | * The default IDT entries which are set up in trap_init() before | ||
69 | * cpu_init() is invoked. Interrupt stacks cannot be used at that point and | ||
70 | * the traps which use them are reinitialized with IST after cpu_init() has | ||
71 | * set up TSS. | ||
72 | */ | ||
73 | static const __initdata struct idt_data def_idts[] = { | ||
74 | INTG(X86_TRAP_DE, divide_error), | ||
75 | INTG(X86_TRAP_NMI, nmi), | ||
76 | INTG(X86_TRAP_BR, bounds), | ||
77 | INTG(X86_TRAP_UD, invalid_op), | ||
78 | INTG(X86_TRAP_NM, device_not_available), | ||
79 | INTG(X86_TRAP_OLD_MF, coprocessor_segment_overrun), | ||
80 | INTG(X86_TRAP_TS, invalid_TSS), | ||
81 | INTG(X86_TRAP_NP, segment_not_present), | ||
82 | INTG(X86_TRAP_SS, stack_segment), | ||
83 | INTG(X86_TRAP_GP, general_protection), | ||
84 | INTG(X86_TRAP_SPURIOUS, spurious_interrupt_bug), | ||
85 | INTG(X86_TRAP_MF, coprocessor_error), | ||
86 | INTG(X86_TRAP_AC, alignment_check), | ||
87 | INTG(X86_TRAP_XF, simd_coprocessor_error), | ||
88 | |||
89 | #ifdef CONFIG_X86_32 | ||
90 | TSKG(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS), | ||
91 | #else | ||
92 | INTG(X86_TRAP_DF, double_fault), | ||
93 | #endif | ||
94 | INTG(X86_TRAP_DB, debug), | ||
95 | INTG(X86_TRAP_NMI, nmi), | ||
96 | INTG(X86_TRAP_BP, int3), | ||
97 | |||
98 | #ifdef CONFIG_X86_MCE | ||
99 | INTG(X86_TRAP_MC, &machine_check), | ||
100 | #endif | ||
101 | |||
102 | SYSG(X86_TRAP_OF, overflow), | ||
103 | #if defined(CONFIG_IA32_EMULATION) | ||
104 | SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat), | ||
105 | #elif defined(CONFIG_X86_32) | ||
106 | SYSG(IA32_SYSCALL_VECTOR, entry_INT80_32), | ||
107 | #endif | ||
108 | }; | ||
109 | |||
110 | /* | ||
111 | * The APIC and SMP idt entries | ||
112 | */ | ||
113 | static const __initdata struct idt_data apic_idts[] = { | ||
114 | #ifdef CONFIG_SMP | ||
115 | INTG(RESCHEDULE_VECTOR, reschedule_interrupt), | ||
116 | INTG(CALL_FUNCTION_VECTOR, call_function_interrupt), | ||
117 | INTG(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt), | ||
118 | INTG(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt), | ||
119 | INTG(REBOOT_VECTOR, reboot_interrupt), | ||
120 | #endif | ||
121 | |||
122 | #ifdef CONFIG_X86_THERMAL_VECTOR | ||
123 | INTG(THERMAL_APIC_VECTOR, thermal_interrupt), | ||
124 | #endif | ||
125 | |||
126 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
127 | INTG(THRESHOLD_APIC_VECTOR, threshold_interrupt), | ||
128 | #endif | ||
129 | |||
130 | #ifdef CONFIG_X86_MCE_AMD | ||
131 | INTG(DEFERRED_ERROR_VECTOR, deferred_error_interrupt), | ||
132 | #endif | ||
133 | |||
134 | #ifdef CONFIG_X86_LOCAL_APIC | ||
135 | INTG(LOCAL_TIMER_VECTOR, apic_timer_interrupt), | ||
136 | INTG(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi), | ||
137 | # ifdef CONFIG_HAVE_KVM | ||
138 | INTG(POSTED_INTR_VECTOR, kvm_posted_intr_ipi), | ||
139 | INTG(POSTED_INTR_WAKEUP_VECTOR, kvm_posted_intr_wakeup_ipi), | ||
140 | INTG(POSTED_INTR_NESTED_VECTOR, kvm_posted_intr_nested_ipi), | ||
141 | # endif | ||
142 | # ifdef CONFIG_IRQ_WORK | ||
143 | INTG(IRQ_WORK_VECTOR, irq_work_interrupt), | ||
144 | # endif | ||
145 | INTG(SPURIOUS_APIC_VECTOR, spurious_interrupt), | ||
146 | INTG(ERROR_APIC_VECTOR, error_interrupt), | ||
147 | #endif | ||
148 | }; | ||
149 | |||
150 | #ifdef CONFIG_X86_64 | ||
151 | /* | ||
152 | * Early traps running on the DEFAULT_STACK because the other interrupt | ||
153 | * stacks work only after cpu_init(). | ||
154 | */ | ||
155 | static const __initdata struct idt_data early_pf_idts[] = { | ||
156 | INTG(X86_TRAP_PF, page_fault), | ||
157 | }; | ||
158 | |||
159 | /* | ||
160 | * Override for the debug_idt. Same as the default, but with interrupt | ||
161 | * stack set to DEFAULT_STACK (0). Required for NMI trap handling. | ||
162 | */ | ||
163 | static const __initdata struct idt_data dbg_idts[] = { | ||
164 | INTG(X86_TRAP_DB, debug), | ||
165 | INTG(X86_TRAP_BP, int3), | ||
166 | }; | ||
167 | #endif | ||
168 | |||
169 | /* Must be page-aligned because the real IDT is used in a fixmap. */ | ||
170 | gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss; | ||
171 | |||
172 | struct desc_ptr idt_descr __ro_after_init = { | ||
173 | .size = (IDT_ENTRIES * 2 * sizeof(unsigned long)) - 1, | ||
174 | .address = (unsigned long) idt_table, | ||
175 | }; | ||
176 | |||
177 | #ifdef CONFIG_X86_64 | ||
178 | /* No need to be aligned, but done to keep all IDTs defined the same way. */ | ||
179 | gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss; | ||
180 | |||
181 | /* | ||
182 | * The exceptions which use Interrupt stacks. They are setup after | ||
183 | * cpu_init() when the TSS has been initialized. | ||
184 | */ | ||
185 | static const __initdata struct idt_data ist_idts[] = { | ||
186 | ISTG(X86_TRAP_DB, debug, DEBUG_STACK), | ||
187 | ISTG(X86_TRAP_NMI, nmi, NMI_STACK), | ||
188 | SISTG(X86_TRAP_BP, int3, DEBUG_STACK), | ||
189 | ISTG(X86_TRAP_DF, double_fault, DOUBLEFAULT_STACK), | ||
190 | #ifdef CONFIG_X86_MCE | ||
191 | ISTG(X86_TRAP_MC, &machine_check, MCE_STACK), | ||
192 | #endif | ||
193 | }; | ||
194 | |||
195 | /* | ||
196 | * Override for the debug_idt. Same as the default, but with interrupt | ||
197 | * stack set to DEFAULT_STACK (0). Required for NMI trap handling. | ||
198 | */ | ||
199 | const struct desc_ptr debug_idt_descr = { | ||
200 | .size = IDT_ENTRIES * 16 - 1, | ||
201 | .address = (unsigned long) debug_idt_table, | ||
202 | }; | ||
203 | #endif | ||
204 | |||
205 | static inline void idt_init_desc(gate_desc *gate, const struct idt_data *d) | ||
206 | { | ||
207 | unsigned long addr = (unsigned long) d->addr; | ||
208 | |||
209 | gate->offset_low = (u16) addr; | ||
210 | gate->segment = (u16) d->segment; | ||
211 | gate->bits = d->bits; | ||
212 | gate->offset_middle = (u16) (addr >> 16); | ||
213 | #ifdef CONFIG_X86_64 | ||
214 | gate->offset_high = (u32) (addr >> 32); | ||
215 | gate->reserved = 0; | ||
216 | #endif | ||
217 | } | ||
218 | |||
219 | static void | ||
220 | idt_setup_from_table(gate_desc *idt, const struct idt_data *t, int size, bool sys) | ||
221 | { | ||
222 | gate_desc desc; | ||
223 | |||
224 | for (; size > 0; t++, size--) { | ||
225 | idt_init_desc(&desc, t); | ||
226 | write_idt_entry(idt, t->vector, &desc); | ||
227 | if (sys) | ||
228 | set_bit(t->vector, used_vectors); | ||
229 | } | ||
230 | } | ||
231 | |||
232 | static void set_intr_gate(unsigned int n, const void *addr) | ||
233 | { | ||
234 | struct idt_data data; | ||
235 | |||
236 | BUG_ON(n > 0xFF); | ||
237 | |||
238 | memset(&data, 0, sizeof(data)); | ||
239 | data.vector = n; | ||
240 | data.addr = addr; | ||
241 | data.segment = __KERNEL_CS; | ||
242 | data.bits.type = GATE_INTERRUPT; | ||
243 | data.bits.p = 1; | ||
244 | |||
245 | idt_setup_from_table(idt_table, &data, 1, false); | ||
246 | } | ||
247 | |||
248 | /** | ||
249 | * idt_setup_early_traps - Initialize the idt table with early traps | ||
250 | * | ||
251 | * On X8664 these traps do not use interrupt stacks as they can't work | ||
252 | * before cpu_init() is invoked and sets up TSS. The IST variants are | ||
253 | * installed after that. | ||
254 | */ | ||
255 | void __init idt_setup_early_traps(void) | ||
256 | { | ||
257 | idt_setup_from_table(idt_table, early_idts, ARRAY_SIZE(early_idts), | ||
258 | true); | ||
259 | load_idt(&idt_descr); | ||
260 | } | ||
261 | |||
262 | /** | ||
263 | * idt_setup_traps - Initialize the idt table with default traps | ||
264 | */ | ||
265 | void __init idt_setup_traps(void) | ||
266 | { | ||
267 | idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts), true); | ||
268 | } | ||
269 | |||
270 | #ifdef CONFIG_X86_64 | ||
271 | /** | ||
272 | * idt_setup_early_pf - Initialize the idt table with early pagefault handler | ||
273 | * | ||
274 | * On X8664 this does not use interrupt stacks as they can't work before | ||
275 | * cpu_init() is invoked and sets up TSS. The IST variant is installed | ||
276 | * after that. | ||
277 | * | ||
278 | * FIXME: Why is 32bit and 64bit installing the PF handler at different | ||
279 | * places in the early setup code? | ||
280 | */ | ||
281 | void __init idt_setup_early_pf(void) | ||
282 | { | ||
283 | idt_setup_from_table(idt_table, early_pf_idts, | ||
284 | ARRAY_SIZE(early_pf_idts), true); | ||
285 | } | ||
286 | |||
287 | /** | ||
288 | * idt_setup_ist_traps - Initialize the idt table with traps using IST | ||
289 | */ | ||
290 | void __init idt_setup_ist_traps(void) | ||
291 | { | ||
292 | idt_setup_from_table(idt_table, ist_idts, ARRAY_SIZE(ist_idts), true); | ||
293 | } | ||
294 | |||
295 | /** | ||
296 | * idt_setup_debugidt_traps - Initialize the debug idt table with debug traps | ||
297 | */ | ||
298 | void __init idt_setup_debugidt_traps(void) | ||
299 | { | ||
300 | memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16); | ||
301 | |||
302 | idt_setup_from_table(debug_idt_table, dbg_idts, ARRAY_SIZE(dbg_idts), false); | ||
303 | } | ||
304 | #endif | ||
305 | |||
306 | /** | ||
307 | * idt_setup_apic_and_irq_gates - Setup APIC/SMP and normal interrupt gates | ||
308 | */ | ||
309 | void __init idt_setup_apic_and_irq_gates(void) | ||
310 | { | ||
311 | int i = FIRST_EXTERNAL_VECTOR; | ||
312 | void *entry; | ||
313 | |||
314 | idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts), true); | ||
315 | |||
316 | for_each_clear_bit_from(i, used_vectors, FIRST_SYSTEM_VECTOR) { | ||
317 | entry = irq_entries_start + 8 * (i - FIRST_EXTERNAL_VECTOR); | ||
318 | set_intr_gate(i, entry); | ||
319 | } | ||
320 | |||
321 | for_each_clear_bit_from(i, used_vectors, NR_VECTORS) { | ||
322 | #ifdef CONFIG_X86_LOCAL_APIC | ||
323 | set_bit(i, used_vectors); | ||
324 | set_intr_gate(i, spurious_interrupt); | ||
325 | #else | ||
326 | entry = irq_entries_start + 8 * (i - FIRST_EXTERNAL_VECTOR); | ||
327 | set_intr_gate(i, entry); | ||
328 | #endif | ||
329 | } | ||
330 | } | ||
331 | |||
332 | /** | ||
333 | * idt_setup_early_handler - Initializes the idt table with early handlers | ||
334 | */ | ||
335 | void __init idt_setup_early_handler(void) | ||
336 | { | ||
337 | int i; | ||
338 | |||
339 | for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) | ||
340 | set_intr_gate(i, early_idt_handler_array[i]); | ||
341 | #ifdef CONFIG_X86_32 | ||
342 | for ( ; i < NR_VECTORS; i++) | ||
343 | set_intr_gate(i, early_ignore_irq); | ||
344 | #endif | ||
345 | load_idt(&idt_descr); | ||
346 | } | ||
347 | |||
348 | /** | ||
349 | * idt_invalidate - Invalidate interrupt descriptor table | ||
350 | * @addr: The virtual address of the 'invalid' IDT | ||
351 | */ | ||
352 | void idt_invalidate(void *addr) | ||
353 | { | ||
354 | struct desc_ptr idt = { .address = (unsigned long) addr, .size = 0 }; | ||
355 | |||
356 | load_idt(&idt); | ||
357 | } | ||
358 | |||
359 | void __init update_intr_gate(unsigned int n, const void *addr) | ||
360 | { | ||
361 | if (WARN_ON_ONCE(!test_bit(n, used_vectors))) | ||
362 | return; | ||
363 | set_intr_gate(n, addr); | ||
364 | } | ||
365 | |||
366 | void alloc_intr_gate(unsigned int n, const void *addr) | ||
367 | { | ||
368 | BUG_ON(n < FIRST_SYSTEM_VECTOR); | ||
369 | if (!test_and_set_bit(n, used_vectors)) | ||
370 | set_intr_gate(n, addr); | ||
371 | } | ||
diff --git a/arch/x86/kernel/irq.c b/arch/x86/kernel/irq.c index 4ed0aba8dbc8..52089c043160 100644 --- a/arch/x86/kernel/irq.c +++ b/arch/x86/kernel/irq.c | |||
@@ -29,9 +29,6 @@ EXPORT_PER_CPU_SYMBOL(irq_regs); | |||
29 | 29 | ||
30 | atomic_t irq_err_count; | 30 | atomic_t irq_err_count; |
31 | 31 | ||
32 | /* Function pointer for generic interrupt vector handling */ | ||
33 | void (*x86_platform_ipi_callback)(void) = NULL; | ||
34 | |||
35 | /* | 32 | /* |
36 | * 'what should we do if we get a hw irq event on an illegal vector'. | 33 | * 'what should we do if we get a hw irq event on an illegal vector'. |
37 | * each architecture has to answer this themselves. | 34 | * each architecture has to answer this themselves. |
@@ -87,13 +84,13 @@ int arch_show_interrupts(struct seq_file *p, int prec) | |||
87 | for_each_online_cpu(j) | 84 | for_each_online_cpu(j) |
88 | seq_printf(p, "%10u ", irq_stats(j)->icr_read_retry_count); | 85 | seq_printf(p, "%10u ", irq_stats(j)->icr_read_retry_count); |
89 | seq_puts(p, " APIC ICR read retries\n"); | 86 | seq_puts(p, " APIC ICR read retries\n"); |
90 | #endif | ||
91 | if (x86_platform_ipi_callback) { | 87 | if (x86_platform_ipi_callback) { |
92 | seq_printf(p, "%*s: ", prec, "PLT"); | 88 | seq_printf(p, "%*s: ", prec, "PLT"); |
93 | for_each_online_cpu(j) | 89 | for_each_online_cpu(j) |
94 | seq_printf(p, "%10u ", irq_stats(j)->x86_platform_ipis); | 90 | seq_printf(p, "%10u ", irq_stats(j)->x86_platform_ipis); |
95 | seq_puts(p, " Platform interrupts\n"); | 91 | seq_puts(p, " Platform interrupts\n"); |
96 | } | 92 | } |
93 | #endif | ||
97 | #ifdef CONFIG_SMP | 94 | #ifdef CONFIG_SMP |
98 | seq_printf(p, "%*s: ", prec, "RES"); | 95 | seq_printf(p, "%*s: ", prec, "RES"); |
99 | for_each_online_cpu(j) | 96 | for_each_online_cpu(j) |
@@ -183,9 +180,9 @@ u64 arch_irq_stat_cpu(unsigned int cpu) | |||
183 | sum += irq_stats(cpu)->apic_perf_irqs; | 180 | sum += irq_stats(cpu)->apic_perf_irqs; |
184 | sum += irq_stats(cpu)->apic_irq_work_irqs; | 181 | sum += irq_stats(cpu)->apic_irq_work_irqs; |
185 | sum += irq_stats(cpu)->icr_read_retry_count; | 182 | sum += irq_stats(cpu)->icr_read_retry_count; |
186 | #endif | ||
187 | if (x86_platform_ipi_callback) | 183 | if (x86_platform_ipi_callback) |
188 | sum += irq_stats(cpu)->x86_platform_ipis; | 184 | sum += irq_stats(cpu)->x86_platform_ipis; |
185 | #endif | ||
189 | #ifdef CONFIG_SMP | 186 | #ifdef CONFIG_SMP |
190 | sum += irq_stats(cpu)->irq_resched_count; | 187 | sum += irq_stats(cpu)->irq_resched_count; |
191 | sum += irq_stats(cpu)->irq_call_count; | 188 | sum += irq_stats(cpu)->irq_call_count; |
@@ -259,26 +256,26 @@ __visible unsigned int __irq_entry do_IRQ(struct pt_regs *regs) | |||
259 | return 1; | 256 | return 1; |
260 | } | 257 | } |
261 | 258 | ||
259 | #ifdef CONFIG_X86_LOCAL_APIC | ||
260 | /* Function pointer for generic interrupt vector handling */ | ||
261 | void (*x86_platform_ipi_callback)(void) = NULL; | ||
262 | /* | 262 | /* |
263 | * Handler for X86_PLATFORM_IPI_VECTOR. | 263 | * Handler for X86_PLATFORM_IPI_VECTOR. |
264 | */ | 264 | */ |
265 | void __smp_x86_platform_ipi(void) | ||
266 | { | ||
267 | inc_irq_stat(x86_platform_ipis); | ||
268 | |||
269 | if (x86_platform_ipi_callback) | ||
270 | x86_platform_ipi_callback(); | ||
271 | } | ||
272 | |||
273 | __visible void __irq_entry smp_x86_platform_ipi(struct pt_regs *regs) | 265 | __visible void __irq_entry smp_x86_platform_ipi(struct pt_regs *regs) |
274 | { | 266 | { |
275 | struct pt_regs *old_regs = set_irq_regs(regs); | 267 | struct pt_regs *old_regs = set_irq_regs(regs); |
276 | 268 | ||
277 | entering_ack_irq(); | 269 | entering_ack_irq(); |
278 | __smp_x86_platform_ipi(); | 270 | trace_x86_platform_ipi_entry(X86_PLATFORM_IPI_VECTOR); |
271 | inc_irq_stat(x86_platform_ipis); | ||
272 | if (x86_platform_ipi_callback) | ||
273 | x86_platform_ipi_callback(); | ||
274 | trace_x86_platform_ipi_exit(X86_PLATFORM_IPI_VECTOR); | ||
279 | exiting_irq(); | 275 | exiting_irq(); |
280 | set_irq_regs(old_regs); | 276 | set_irq_regs(old_regs); |
281 | } | 277 | } |
278 | #endif | ||
282 | 279 | ||
283 | #ifdef CONFIG_HAVE_KVM | 280 | #ifdef CONFIG_HAVE_KVM |
284 | static void dummy_handler(void) {} | 281 | static void dummy_handler(void) {} |
@@ -334,19 +331,6 @@ __visible void smp_kvm_posted_intr_nested_ipi(struct pt_regs *regs) | |||
334 | } | 331 | } |
335 | #endif | 332 | #endif |
336 | 333 | ||
337 | __visible void __irq_entry smp_trace_x86_platform_ipi(struct pt_regs *regs) | ||
338 | { | ||
339 | struct pt_regs *old_regs = set_irq_regs(regs); | ||
340 | |||
341 | entering_ack_irq(); | ||
342 | trace_x86_platform_ipi_entry(X86_PLATFORM_IPI_VECTOR); | ||
343 | __smp_x86_platform_ipi(); | ||
344 | trace_x86_platform_ipi_exit(X86_PLATFORM_IPI_VECTOR); | ||
345 | exiting_irq(); | ||
346 | set_irq_regs(old_regs); | ||
347 | } | ||
348 | |||
349 | EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq); | ||
350 | 334 | ||
351 | #ifdef CONFIG_HOTPLUG_CPU | 335 | #ifdef CONFIG_HOTPLUG_CPU |
352 | 336 | ||
@@ -431,7 +415,7 @@ int check_irq_vectors_for_cpu_disable(void) | |||
431 | * this w/o holding vector_lock. | 415 | * this w/o holding vector_lock. |
432 | */ | 416 | */ |
433 | for (vector = FIRST_EXTERNAL_VECTOR; | 417 | for (vector = FIRST_EXTERNAL_VECTOR; |
434 | vector < first_system_vector; vector++) { | 418 | vector < FIRST_SYSTEM_VECTOR; vector++) { |
435 | if (!test_bit(vector, used_vectors) && | 419 | if (!test_bit(vector, used_vectors) && |
436 | IS_ERR_OR_NULL(per_cpu(vector_irq, cpu)[vector])) { | 420 | IS_ERR_OR_NULL(per_cpu(vector_irq, cpu)[vector])) { |
437 | if (++count == this_count) | 421 | if (++count == this_count) |
diff --git a/arch/x86/kernel/irq_work.c b/arch/x86/kernel/irq_work.c index 275487872be2..70dee056f92b 100644 --- a/arch/x86/kernel/irq_work.c +++ b/arch/x86/kernel/irq_work.c | |||
@@ -11,35 +11,23 @@ | |||
11 | #include <asm/trace/irq_vectors.h> | 11 | #include <asm/trace/irq_vectors.h> |
12 | #include <linux/interrupt.h> | 12 | #include <linux/interrupt.h> |
13 | 13 | ||
14 | static inline void __smp_irq_work_interrupt(void) | 14 | #ifdef CONFIG_X86_LOCAL_APIC |
15 | { | ||
16 | inc_irq_stat(apic_irq_work_irqs); | ||
17 | irq_work_run(); | ||
18 | } | ||
19 | |||
20 | __visible void __irq_entry smp_irq_work_interrupt(struct pt_regs *regs) | 15 | __visible void __irq_entry smp_irq_work_interrupt(struct pt_regs *regs) |
21 | { | 16 | { |
22 | ipi_entering_ack_irq(); | 17 | ipi_entering_ack_irq(); |
23 | __smp_irq_work_interrupt(); | ||
24 | exiting_irq(); | ||
25 | } | ||
26 | |||
27 | __visible void __irq_entry smp_trace_irq_work_interrupt(struct pt_regs *regs) | ||
28 | { | ||
29 | ipi_entering_ack_irq(); | ||
30 | trace_irq_work_entry(IRQ_WORK_VECTOR); | 18 | trace_irq_work_entry(IRQ_WORK_VECTOR); |
31 | __smp_irq_work_interrupt(); | 19 | inc_irq_stat(apic_irq_work_irqs); |
20 | irq_work_run(); | ||
32 | trace_irq_work_exit(IRQ_WORK_VECTOR); | 21 | trace_irq_work_exit(IRQ_WORK_VECTOR); |
33 | exiting_irq(); | 22 | exiting_irq(); |
34 | } | 23 | } |
35 | 24 | ||
36 | void arch_irq_work_raise(void) | 25 | void arch_irq_work_raise(void) |
37 | { | 26 | { |
38 | #ifdef CONFIG_X86_LOCAL_APIC | ||
39 | if (!arch_irq_work_has_interrupt()) | 27 | if (!arch_irq_work_has_interrupt()) |
40 | return; | 28 | return; |
41 | 29 | ||
42 | apic->send_IPI_self(IRQ_WORK_VECTOR); | 30 | apic->send_IPI_self(IRQ_WORK_VECTOR); |
43 | apic_wait_icr_idle(); | 31 | apic_wait_icr_idle(); |
44 | #endif | ||
45 | } | 32 | } |
33 | #endif | ||
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c index c7fd18526c3e..1add9e08e83e 100644 --- a/arch/x86/kernel/irqinit.c +++ b/arch/x86/kernel/irqinit.c | |||
@@ -55,18 +55,6 @@ DEFINE_PER_CPU(vector_irq_t, vector_irq) = { | |||
55 | [0 ... NR_VECTORS - 1] = VECTOR_UNUSED, | 55 | [0 ... NR_VECTORS - 1] = VECTOR_UNUSED, |
56 | }; | 56 | }; |
57 | 57 | ||
58 | int vector_used_by_percpu_irq(unsigned int vector) | ||
59 | { | ||
60 | int cpu; | ||
61 | |||
62 | for_each_online_cpu(cpu) { | ||
63 | if (!IS_ERR_OR_NULL(per_cpu(vector_irq, cpu)[vector])) | ||
64 | return 1; | ||
65 | } | ||
66 | |||
67 | return 0; | ||
68 | } | ||
69 | |||
70 | void __init init_ISA_irqs(void) | 58 | void __init init_ISA_irqs(void) |
71 | { | 59 | { |
72 | struct irq_chip *chip = legacy_pic->chip; | 60 | struct irq_chip *chip = legacy_pic->chip; |
@@ -99,100 +87,12 @@ void __init init_IRQ(void) | |||
99 | x86_init.irqs.intr_init(); | 87 | x86_init.irqs.intr_init(); |
100 | } | 88 | } |
101 | 89 | ||
102 | static void __init smp_intr_init(void) | ||
103 | { | ||
104 | #ifdef CONFIG_SMP | ||
105 | /* | ||
106 | * The reschedule interrupt is a CPU-to-CPU reschedule-helper | ||
107 | * IPI, driven by wakeup. | ||
108 | */ | ||
109 | alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt); | ||
110 | |||
111 | /* IPI for generic function call */ | ||
112 | alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt); | ||
113 | |||
114 | /* IPI for generic single function call */ | ||
115 | alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR, | ||
116 | call_function_single_interrupt); | ||
117 | |||
118 | /* Low priority IPI to cleanup after moving an irq */ | ||
119 | set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt); | ||
120 | set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors); | ||
121 | |||
122 | /* IPI used for rebooting/stopping */ | ||
123 | alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt); | ||
124 | #endif /* CONFIG_SMP */ | ||
125 | } | ||
126 | |||
127 | static void __init apic_intr_init(void) | ||
128 | { | ||
129 | smp_intr_init(); | ||
130 | |||
131 | #ifdef CONFIG_X86_THERMAL_VECTOR | ||
132 | alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt); | ||
133 | #endif | ||
134 | #ifdef CONFIG_X86_MCE_THRESHOLD | ||
135 | alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); | ||
136 | #endif | ||
137 | |||
138 | #ifdef CONFIG_X86_MCE_AMD | ||
139 | alloc_intr_gate(DEFERRED_ERROR_VECTOR, deferred_error_interrupt); | ||
140 | #endif | ||
141 | |||
142 | #ifdef CONFIG_X86_LOCAL_APIC | ||
143 | /* self generated IPI for local APIC timer */ | ||
144 | alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); | ||
145 | |||
146 | /* IPI for X86 platform specific use */ | ||
147 | alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi); | ||
148 | #ifdef CONFIG_HAVE_KVM | ||
149 | /* IPI for KVM to deliver posted interrupt */ | ||
150 | alloc_intr_gate(POSTED_INTR_VECTOR, kvm_posted_intr_ipi); | ||
151 | /* IPI for KVM to deliver interrupt to wake up tasks */ | ||
152 | alloc_intr_gate(POSTED_INTR_WAKEUP_VECTOR, kvm_posted_intr_wakeup_ipi); | ||
153 | /* IPI for KVM to deliver nested posted interrupt */ | ||
154 | alloc_intr_gate(POSTED_INTR_NESTED_VECTOR, kvm_posted_intr_nested_ipi); | ||
155 | #endif | ||
156 | |||
157 | /* IPI vectors for APIC spurious and error interrupts */ | ||
158 | alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt); | ||
159 | alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt); | ||
160 | |||
161 | /* IRQ work interrupts: */ | ||
162 | # ifdef CONFIG_IRQ_WORK | ||
163 | alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt); | ||
164 | # endif | ||
165 | |||
166 | #endif | ||
167 | } | ||
168 | |||
169 | void __init native_init_IRQ(void) | 90 | void __init native_init_IRQ(void) |
170 | { | 91 | { |
171 | int i; | ||
172 | |||
173 | /* Execute any quirks before the call gates are initialised: */ | 92 | /* Execute any quirks before the call gates are initialised: */ |
174 | x86_init.irqs.pre_vector_init(); | 93 | x86_init.irqs.pre_vector_init(); |
175 | 94 | ||
176 | apic_intr_init(); | 95 | idt_setup_apic_and_irq_gates(); |
177 | |||
178 | /* | ||
179 | * Cover the whole vector space, no vector can escape | ||
180 | * us. (some of these will be overridden and become | ||
181 | * 'special' SMP interrupts) | ||
182 | */ | ||
183 | i = FIRST_EXTERNAL_VECTOR; | ||
184 | #ifndef CONFIG_X86_LOCAL_APIC | ||
185 | #define first_system_vector NR_VECTORS | ||
186 | #endif | ||
187 | for_each_clear_bit_from(i, used_vectors, first_system_vector) { | ||
188 | /* IA32_SYSCALL_VECTOR could be used in trap_init already. */ | ||
189 | set_intr_gate(i, irq_entries_start + | ||
190 | 8 * (i - FIRST_EXTERNAL_VECTOR)); | ||
191 | } | ||
192 | #ifdef CONFIG_X86_LOCAL_APIC | ||
193 | for_each_clear_bit_from(i, used_vectors, NR_VECTORS) | ||
194 | set_intr_gate(i, spurious_interrupt); | ||
195 | #endif | ||
196 | 96 | ||
197 | if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) | 97 | if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) |
198 | setup_irq(2, &irq2); | 98 | setup_irq(2, &irq2); |
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c index d04e30e3c0ff..874827b0d7ca 100644 --- a/arch/x86/kernel/kvm.c +++ b/arch/x86/kernel/kvm.c | |||
@@ -263,7 +263,7 @@ do_async_page_fault(struct pt_regs *regs, unsigned long error_code) | |||
263 | 263 | ||
264 | switch (kvm_read_and_reset_pf_reason()) { | 264 | switch (kvm_read_and_reset_pf_reason()) { |
265 | default: | 265 | default: |
266 | trace_do_page_fault(regs, error_code); | 266 | do_page_fault(regs, error_code); |
267 | break; | 267 | break; |
268 | case KVM_PV_REASON_PAGE_NOT_PRESENT: | 268 | case KVM_PV_REASON_PAGE_NOT_PRESENT: |
269 | /* page is swapped out by the host. */ | 269 | /* page is swapped out by the host. */ |
@@ -455,7 +455,7 @@ static int kvm_cpu_down_prepare(unsigned int cpu) | |||
455 | 455 | ||
456 | static void __init kvm_apf_trap_init(void) | 456 | static void __init kvm_apf_trap_init(void) |
457 | { | 457 | { |
458 | set_intr_gate(14, async_page_fault); | 458 | update_intr_gate(X86_TRAP_PF, async_page_fault); |
459 | } | 459 | } |
460 | 460 | ||
461 | void __init kvm_guest_init(void) | 461 | void __init kvm_guest_init(void) |
diff --git a/arch/x86/kernel/machine_kexec_32.c b/arch/x86/kernel/machine_kexec_32.c index 8c53c5d7a1bc..00bc751c861c 100644 --- a/arch/x86/kernel/machine_kexec_32.c +++ b/arch/x86/kernel/machine_kexec_32.c | |||
@@ -26,18 +26,6 @@ | |||
26 | #include <asm/set_memory.h> | 26 | #include <asm/set_memory.h> |
27 | #include <asm/debugreg.h> | 27 | #include <asm/debugreg.h> |
28 | 28 | ||
29 | static void set_idt(void *newidt, __u16 limit) | ||
30 | { | ||
31 | struct desc_ptr curidt; | ||
32 | |||
33 | /* ia32 supports unaliged loads & stores */ | ||
34 | curidt.size = limit; | ||
35 | curidt.address = (unsigned long)newidt; | ||
36 | |||
37 | load_idt(&curidt); | ||
38 | } | ||
39 | |||
40 | |||
41 | static void set_gdt(void *newgdt, __u16 limit) | 29 | static void set_gdt(void *newgdt, __u16 limit) |
42 | { | 30 | { |
43 | struct desc_ptr curgdt; | 31 | struct desc_ptr curgdt; |
@@ -245,7 +233,7 @@ void machine_kexec(struct kimage *image) | |||
245 | * If you want to load them you must set up your own idt & gdt. | 233 | * If you want to load them you must set up your own idt & gdt. |
246 | */ | 234 | */ |
247 | set_gdt(phys_to_virt(0), 0); | 235 | set_gdt(phys_to_virt(0), 0); |
248 | set_idt(phys_to_virt(0), 0); | 236 | idt_invalidate(phys_to_virt(0)); |
249 | 237 | ||
250 | /* now call it */ | 238 | /* now call it */ |
251 | image->start = relocate_kernel_ptr((unsigned long)image->head, | 239 | image->start = relocate_kernel_ptr((unsigned long)image->head, |
diff --git a/arch/x86/kernel/paravirt.c b/arch/x86/kernel/paravirt.c index bc0a849589bb..a14df9eecfed 100644 --- a/arch/x86/kernel/paravirt.c +++ b/arch/x86/kernel/paravirt.c | |||
@@ -319,9 +319,6 @@ __visible struct pv_irq_ops pv_irq_ops = { | |||
319 | .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable), | 319 | .irq_enable = __PV_IS_CALLEE_SAVE(native_irq_enable), |
320 | .safe_halt = native_safe_halt, | 320 | .safe_halt = native_safe_halt, |
321 | .halt = native_halt, | 321 | .halt = native_halt, |
322 | #ifdef CONFIG_X86_64 | ||
323 | .adjust_exception_frame = paravirt_nop, | ||
324 | #endif | ||
325 | }; | 322 | }; |
326 | 323 | ||
327 | __visible struct pv_cpu_ops pv_cpu_ops = { | 324 | __visible struct pv_cpu_ops pv_cpu_ops = { |
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c index a56bf6051f4e..54984b142641 100644 --- a/arch/x86/kernel/reboot.c +++ b/arch/x86/kernel/reboot.c | |||
@@ -38,8 +38,6 @@ | |||
38 | void (*pm_power_off)(void); | 38 | void (*pm_power_off)(void); |
39 | EXPORT_SYMBOL(pm_power_off); | 39 | EXPORT_SYMBOL(pm_power_off); |
40 | 40 | ||
41 | static const struct desc_ptr no_idt = {}; | ||
42 | |||
43 | /* | 41 | /* |
44 | * This is set if we need to go through the 'emergency' path. | 42 | * This is set if we need to go through the 'emergency' path. |
45 | * When machine_emergency_restart() is called, we may be on | 43 | * When machine_emergency_restart() is called, we may be on |
@@ -638,7 +636,7 @@ static void native_machine_emergency_restart(void) | |||
638 | break; | 636 | break; |
639 | 637 | ||
640 | case BOOT_TRIPLE: | 638 | case BOOT_TRIPLE: |
641 | load_idt(&no_idt); | 639 | idt_invalidate(NULL); |
642 | __asm__ __volatile__("int3"); | 640 | __asm__ __volatile__("int3"); |
643 | 641 | ||
644 | /* We're probably dead after this, but... */ | 642 | /* We're probably dead after this, but... */ |
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 022ebddb3734..9cc16a841745 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c | |||
@@ -900,7 +900,7 @@ void __init setup_arch(char **cmdline_p) | |||
900 | */ | 900 | */ |
901 | olpc_ofw_detect(); | 901 | olpc_ofw_detect(); |
902 | 902 | ||
903 | early_trap_init(); | 903 | idt_setup_early_traps(); |
904 | early_cpu_init(); | 904 | early_cpu_init(); |
905 | early_ioremap_init(); | 905 | early_ioremap_init(); |
906 | 906 | ||
@@ -1171,7 +1171,7 @@ void __init setup_arch(char **cmdline_p) | |||
1171 | 1171 | ||
1172 | init_mem_mapping(); | 1172 | init_mem_mapping(); |
1173 | 1173 | ||
1174 | early_trap_pf_init(); | 1174 | idt_setup_early_pf(); |
1175 | 1175 | ||
1176 | /* | 1176 | /* |
1177 | * Update mmu_cr4_features (and, indirectly, trampoline_cr4_features) | 1177 | * Update mmu_cr4_features (and, indirectly, trampoline_cr4_features) |
diff --git a/arch/x86/kernel/setup_percpu.c b/arch/x86/kernel/setup_percpu.c index 10edd1e69a68..6e8fcb6f7e1e 100644 --- a/arch/x86/kernel/setup_percpu.c +++ b/arch/x86/kernel/setup_percpu.c | |||
@@ -155,13 +155,10 @@ static void __init pcpup_populate_pte(unsigned long addr) | |||
155 | static inline void setup_percpu_segment(int cpu) | 155 | static inline void setup_percpu_segment(int cpu) |
156 | { | 156 | { |
157 | #ifdef CONFIG_X86_32 | 157 | #ifdef CONFIG_X86_32 |
158 | struct desc_struct gdt; | 158 | struct desc_struct d = GDT_ENTRY_INIT(0x8092, per_cpu_offset(cpu), |
159 | 0xFFFFF); | ||
159 | 160 | ||
160 | pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF, | 161 | write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_PERCPU, &d, DESCTYPE_S); |
161 | 0x2 | DESCTYPE_S, 0x8); | ||
162 | gdt.s = 1; | ||
163 | write_gdt_entry(get_cpu_gdt_rw(cpu), | ||
164 | GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S); | ||
165 | #endif | 162 | #endif |
166 | } | 163 | } |
167 | 164 | ||
diff --git a/arch/x86/kernel/smp.c b/arch/x86/kernel/smp.c index d798c0da451c..5c574dff4c1a 100644 --- a/arch/x86/kernel/smp.c +++ b/arch/x86/kernel/smp.c | |||
@@ -254,84 +254,45 @@ finish: | |||
254 | } | 254 | } |
255 | 255 | ||
256 | /* | 256 | /* |
257 | * Reschedule call back. | 257 | * Reschedule call back. KVM uses this interrupt to force a cpu out of |
258 | * guest mode | ||
258 | */ | 259 | */ |
259 | static inline void __smp_reschedule_interrupt(void) | ||
260 | { | ||
261 | inc_irq_stat(irq_resched_count); | ||
262 | scheduler_ipi(); | ||
263 | } | ||
264 | |||
265 | __visible void __irq_entry smp_reschedule_interrupt(struct pt_regs *regs) | 260 | __visible void __irq_entry smp_reschedule_interrupt(struct pt_regs *regs) |
266 | { | 261 | { |
267 | ack_APIC_irq(); | 262 | ack_APIC_irq(); |
268 | __smp_reschedule_interrupt(); | 263 | inc_irq_stat(irq_resched_count); |
269 | /* | ||
270 | * KVM uses this interrupt to force a cpu out of guest mode | ||
271 | */ | ||
272 | } | ||
273 | |||
274 | __visible void __irq_entry smp_trace_reschedule_interrupt(struct pt_regs *regs) | ||
275 | { | ||
276 | /* | ||
277 | * Need to call irq_enter() before calling the trace point. | ||
278 | * __smp_reschedule_interrupt() calls irq_enter/exit() too (in | ||
279 | * scheduler_ipi(). This is OK, since those functions are allowed | ||
280 | * to nest. | ||
281 | */ | ||
282 | ipi_entering_ack_irq(); | ||
283 | trace_reschedule_entry(RESCHEDULE_VECTOR); | ||
284 | __smp_reschedule_interrupt(); | ||
285 | trace_reschedule_exit(RESCHEDULE_VECTOR); | ||
286 | exiting_irq(); | ||
287 | /* | ||
288 | * KVM uses this interrupt to force a cpu out of guest mode | ||
289 | */ | ||
290 | } | ||
291 | 264 | ||
292 | static inline void __smp_call_function_interrupt(void) | 265 | if (trace_resched_ipi_enabled()) { |
293 | { | 266 | /* |
294 | generic_smp_call_function_interrupt(); | 267 | * scheduler_ipi() might call irq_enter() as well, but |
295 | inc_irq_stat(irq_call_count); | 268 | * nested calls are fine. |
269 | */ | ||
270 | irq_enter(); | ||
271 | trace_reschedule_entry(RESCHEDULE_VECTOR); | ||
272 | scheduler_ipi(); | ||
273 | trace_reschedule_exit(RESCHEDULE_VECTOR); | ||
274 | irq_exit(); | ||
275 | return; | ||
276 | } | ||
277 | scheduler_ipi(); | ||
296 | } | 278 | } |
297 | 279 | ||
298 | __visible void __irq_entry smp_call_function_interrupt(struct pt_regs *regs) | 280 | __visible void __irq_entry smp_call_function_interrupt(struct pt_regs *regs) |
299 | { | 281 | { |
300 | ipi_entering_ack_irq(); | 282 | ipi_entering_ack_irq(); |
301 | __smp_call_function_interrupt(); | ||
302 | exiting_irq(); | ||
303 | } | ||
304 | |||
305 | __visible void __irq_entry | ||
306 | smp_trace_call_function_interrupt(struct pt_regs *regs) | ||
307 | { | ||
308 | ipi_entering_ack_irq(); | ||
309 | trace_call_function_entry(CALL_FUNCTION_VECTOR); | 283 | trace_call_function_entry(CALL_FUNCTION_VECTOR); |
310 | __smp_call_function_interrupt(); | ||
311 | trace_call_function_exit(CALL_FUNCTION_VECTOR); | ||
312 | exiting_irq(); | ||
313 | } | ||
314 | |||
315 | static inline void __smp_call_function_single_interrupt(void) | ||
316 | { | ||
317 | generic_smp_call_function_single_interrupt(); | ||
318 | inc_irq_stat(irq_call_count); | 284 | inc_irq_stat(irq_call_count); |
319 | } | 285 | generic_smp_call_function_interrupt(); |
320 | 286 | trace_call_function_exit(CALL_FUNCTION_VECTOR); | |
321 | __visible void __irq_entry | ||
322 | smp_call_function_single_interrupt(struct pt_regs *regs) | ||
323 | { | ||
324 | ipi_entering_ack_irq(); | ||
325 | __smp_call_function_single_interrupt(); | ||
326 | exiting_irq(); | 287 | exiting_irq(); |
327 | } | 288 | } |
328 | 289 | ||
329 | __visible void __irq_entry | 290 | __visible void __irq_entry smp_call_function_single_interrupt(struct pt_regs *r) |
330 | smp_trace_call_function_single_interrupt(struct pt_regs *regs) | ||
331 | { | 291 | { |
332 | ipi_entering_ack_irq(); | 292 | ipi_entering_ack_irq(); |
333 | trace_call_function_single_entry(CALL_FUNCTION_SINGLE_VECTOR); | 293 | trace_call_function_single_entry(CALL_FUNCTION_SINGLE_VECTOR); |
334 | __smp_call_function_single_interrupt(); | 294 | inc_irq_stat(irq_call_count); |
295 | generic_smp_call_function_single_interrupt(); | ||
335 | trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR); | 296 | trace_call_function_single_exit(CALL_FUNCTION_SINGLE_VECTOR); |
336 | exiting_irq(); | 297 | exiting_irq(); |
337 | } | 298 | } |
diff --git a/arch/x86/kernel/tls.c b/arch/x86/kernel/tls.c index dcd699baea1b..a106b9719c58 100644 --- a/arch/x86/kernel/tls.c +++ b/arch/x86/kernel/tls.c | |||
@@ -93,7 +93,7 @@ static void set_tls_desc(struct task_struct *p, int idx, | |||
93 | 93 | ||
94 | while (n-- > 0) { | 94 | while (n-- > 0) { |
95 | if (LDT_empty(info) || LDT_zero(info)) { | 95 | if (LDT_empty(info) || LDT_zero(info)) { |
96 | desc->a = desc->b = 0; | 96 | memset(desc, 0, sizeof(*desc)); |
97 | } else { | 97 | } else { |
98 | fill_ldt(desc, info); | 98 | fill_ldt(desc, info); |
99 | 99 | ||
diff --git a/arch/x86/kernel/tracepoint.c b/arch/x86/kernel/tracepoint.c index 15515132bf0d..c6636d1f60b9 100644 --- a/arch/x86/kernel/tracepoint.c +++ b/arch/x86/kernel/tracepoint.c | |||
@@ -4,57 +4,38 @@ | |||
4 | * Copyright (C) 2013 Seiji Aguchi <seiji.aguchi@hds.com> | 4 | * Copyright (C) 2013 Seiji Aguchi <seiji.aguchi@hds.com> |
5 | * | 5 | * |
6 | */ | 6 | */ |
7 | #include <asm/hw_irq.h> | 7 | #include <linux/jump_label.h> |
8 | #include <asm/desc.h> | ||
9 | #include <linux/atomic.h> | 8 | #include <linux/atomic.h> |
10 | 9 | ||
11 | atomic_t trace_idt_ctr = ATOMIC_INIT(0); | 10 | #include <asm/hw_irq.h> |
12 | struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1, | 11 | #include <asm/desc.h> |
13 | (unsigned long) trace_idt_table }; | ||
14 | |||
15 | /* No need to be aligned, but done to keep all IDTs defined the same way. */ | ||
16 | gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss; | ||
17 | 12 | ||
18 | static int trace_irq_vector_refcount; | 13 | DEFINE_STATIC_KEY_FALSE(trace_pagefault_key); |
19 | static DEFINE_MUTEX(irq_vector_mutex); | ||
20 | 14 | ||
21 | static void set_trace_idt_ctr(int val) | 15 | int trace_pagefault_reg(void) |
22 | { | 16 | { |
23 | atomic_set(&trace_idt_ctr, val); | 17 | static_branch_inc(&trace_pagefault_key); |
24 | /* Ensure the trace_idt_ctr is set before sending IPI */ | 18 | return 0; |
25 | wmb(); | ||
26 | } | 19 | } |
27 | 20 | ||
28 | static void switch_idt(void *arg) | 21 | void trace_pagefault_unreg(void) |
29 | { | 22 | { |
30 | unsigned long flags; | 23 | static_branch_dec(&trace_pagefault_key); |
31 | |||
32 | local_irq_save(flags); | ||
33 | load_current_idt(); | ||
34 | local_irq_restore(flags); | ||
35 | } | 24 | } |
36 | 25 | ||
37 | int trace_irq_vector_regfunc(void) | 26 | #ifdef CONFIG_SMP |
27 | |||
28 | DEFINE_STATIC_KEY_FALSE(trace_resched_ipi_key); | ||
29 | |||
30 | int trace_resched_ipi_reg(void) | ||
38 | { | 31 | { |
39 | mutex_lock(&irq_vector_mutex); | 32 | static_branch_inc(&trace_resched_ipi_key); |
40 | if (!trace_irq_vector_refcount) { | ||
41 | set_trace_idt_ctr(1); | ||
42 | smp_call_function(switch_idt, NULL, 0); | ||
43 | switch_idt(NULL); | ||
44 | } | ||
45 | trace_irq_vector_refcount++; | ||
46 | mutex_unlock(&irq_vector_mutex); | ||
47 | return 0; | 33 | return 0; |
48 | } | 34 | } |
49 | 35 | ||
50 | void trace_irq_vector_unregfunc(void) | 36 | void trace_resched_ipi_unreg(void) |
51 | { | 37 | { |
52 | mutex_lock(&irq_vector_mutex); | 38 | static_branch_dec(&trace_resched_ipi_key); |
53 | trace_irq_vector_refcount--; | ||
54 | if (!trace_irq_vector_refcount) { | ||
55 | set_trace_idt_ctr(0); | ||
56 | smp_call_function(switch_idt, NULL, 0); | ||
57 | switch_idt(NULL); | ||
58 | } | ||
59 | mutex_unlock(&irq_vector_mutex); | ||
60 | } | 39 | } |
40 | |||
41 | #endif | ||
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index bf54309b85da..34ea3651362e 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -38,11 +38,6 @@ | |||
38 | #include <linux/smp.h> | 38 | #include <linux/smp.h> |
39 | #include <linux/io.h> | 39 | #include <linux/io.h> |
40 | 40 | ||
41 | #ifdef CONFIG_EISA | ||
42 | #include <linux/ioport.h> | ||
43 | #include <linux/eisa.h> | ||
44 | #endif | ||
45 | |||
46 | #if defined(CONFIG_EDAC) | 41 | #if defined(CONFIG_EDAC) |
47 | #include <linux/edac.h> | 42 | #include <linux/edac.h> |
48 | #endif | 43 | #endif |
@@ -70,20 +65,13 @@ | |||
70 | #include <asm/x86_init.h> | 65 | #include <asm/x86_init.h> |
71 | #include <asm/pgalloc.h> | 66 | #include <asm/pgalloc.h> |
72 | #include <asm/proto.h> | 67 | #include <asm/proto.h> |
73 | |||
74 | /* No need to be aligned, but done to keep all IDTs defined the same way. */ | ||
75 | gate_desc debug_idt_table[NR_VECTORS] __page_aligned_bss; | ||
76 | #else | 68 | #else |
77 | #include <asm/processor-flags.h> | 69 | #include <asm/processor-flags.h> |
78 | #include <asm/setup.h> | 70 | #include <asm/setup.h> |
79 | #include <asm/proto.h> | 71 | #include <asm/proto.h> |
80 | #endif | 72 | #endif |
81 | 73 | ||
82 | /* Must be page-aligned because the real IDT is used in a fixmap. */ | ||
83 | gate_desc idt_table[NR_VECTORS] __page_aligned_bss; | ||
84 | |||
85 | DECLARE_BITMAP(used_vectors, NR_VECTORS); | 74 | DECLARE_BITMAP(used_vectors, NR_VECTORS); |
86 | EXPORT_SYMBOL_GPL(used_vectors); | ||
87 | 75 | ||
88 | static inline void cond_local_irq_enable(struct pt_regs *regs) | 76 | static inline void cond_local_irq_enable(struct pt_regs *regs) |
89 | { | 77 | { |
@@ -935,87 +923,9 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code) | |||
935 | } | 923 | } |
936 | #endif | 924 | #endif |
937 | 925 | ||
938 | /* Set of traps needed for early debugging. */ | ||
939 | void __init early_trap_init(void) | ||
940 | { | ||
941 | /* | ||
942 | * Don't use IST to set DEBUG_STACK as it doesn't work until TSS | ||
943 | * is ready in cpu_init() <-- trap_init(). Before trap_init(), | ||
944 | * CPU runs at ring 0 so it is impossible to hit an invalid | ||
945 | * stack. Using the original stack works well enough at this | ||
946 | * early stage. DEBUG_STACK will be equipped after cpu_init() in | ||
947 | * trap_init(). | ||
948 | * | ||
949 | * We don't need to set trace_idt_table like set_intr_gate(), | ||
950 | * since we don't have trace_debug and it will be reset to | ||
951 | * 'debug' in trap_init() by set_intr_gate_ist(). | ||
952 | */ | ||
953 | set_intr_gate_notrace(X86_TRAP_DB, debug); | ||
954 | /* int3 can be called from all */ | ||
955 | set_system_intr_gate(X86_TRAP_BP, &int3); | ||
956 | #ifdef CONFIG_X86_32 | ||
957 | set_intr_gate(X86_TRAP_PF, page_fault); | ||
958 | #endif | ||
959 | load_idt(&idt_descr); | ||
960 | } | ||
961 | |||
962 | void __init early_trap_pf_init(void) | ||
963 | { | ||
964 | #ifdef CONFIG_X86_64 | ||
965 | set_intr_gate(X86_TRAP_PF, page_fault); | ||
966 | #endif | ||
967 | } | ||
968 | |||
969 | void __init trap_init(void) | 926 | void __init trap_init(void) |
970 | { | 927 | { |
971 | int i; | 928 | idt_setup_traps(); |
972 | |||
973 | #ifdef CONFIG_EISA | ||
974 | void __iomem *p = early_ioremap(0x0FFFD9, 4); | ||
975 | |||
976 | if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24)) | ||
977 | EISA_bus = 1; | ||
978 | early_iounmap(p, 4); | ||
979 | #endif | ||
980 | |||
981 | set_intr_gate(X86_TRAP_DE, divide_error); | ||
982 | set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK); | ||
983 | /* int4 can be called from all */ | ||
984 | set_system_intr_gate(X86_TRAP_OF, &overflow); | ||
985 | set_intr_gate(X86_TRAP_BR, bounds); | ||
986 | set_intr_gate(X86_TRAP_UD, invalid_op); | ||
987 | set_intr_gate(X86_TRAP_NM, device_not_available); | ||
988 | #ifdef CONFIG_X86_32 | ||
989 | set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS); | ||
990 | #else | ||
991 | set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK); | ||
992 | #endif | ||
993 | set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun); | ||
994 | set_intr_gate(X86_TRAP_TS, invalid_TSS); | ||
995 | set_intr_gate(X86_TRAP_NP, segment_not_present); | ||
996 | set_intr_gate(X86_TRAP_SS, stack_segment); | ||
997 | set_intr_gate(X86_TRAP_GP, general_protection); | ||
998 | set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug); | ||
999 | set_intr_gate(X86_TRAP_MF, coprocessor_error); | ||
1000 | set_intr_gate(X86_TRAP_AC, alignment_check); | ||
1001 | #ifdef CONFIG_X86_MCE | ||
1002 | set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK); | ||
1003 | #endif | ||
1004 | set_intr_gate(X86_TRAP_XF, simd_coprocessor_error); | ||
1005 | |||
1006 | /* Reserve all the builtin and the syscall vector: */ | ||
1007 | for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++) | ||
1008 | set_bit(i, used_vectors); | ||
1009 | |||
1010 | #ifdef CONFIG_IA32_EMULATION | ||
1011 | set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_compat); | ||
1012 | set_bit(IA32_SYSCALL_VECTOR, used_vectors); | ||
1013 | #endif | ||
1014 | |||
1015 | #ifdef CONFIG_X86_32 | ||
1016 | set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32); | ||
1017 | set_bit(IA32_SYSCALL_VECTOR, used_vectors); | ||
1018 | #endif | ||
1019 | 929 | ||
1020 | /* | 930 | /* |
1021 | * Set the IDT descriptor to a fixed read-only location, so that the | 931 | * Set the IDT descriptor to a fixed read-only location, so that the |
@@ -1030,20 +940,9 @@ void __init trap_init(void) | |||
1030 | */ | 940 | */ |
1031 | cpu_init(); | 941 | cpu_init(); |
1032 | 942 | ||
1033 | /* | 943 | idt_setup_ist_traps(); |
1034 | * X86_TRAP_DB and X86_TRAP_BP have been set | ||
1035 | * in early_trap_init(). However, ITS works only after | ||
1036 | * cpu_init() loads TSS. See comments in early_trap_init(). | ||
1037 | */ | ||
1038 | set_intr_gate_ist(X86_TRAP_DB, &debug, DEBUG_STACK); | ||
1039 | /* int3 can be called from all */ | ||
1040 | set_system_intr_gate_ist(X86_TRAP_BP, &int3, DEBUG_STACK); | ||
1041 | 944 | ||
1042 | x86_init.irqs.trap_init(); | 945 | x86_init.irqs.trap_init(); |
1043 | 946 | ||
1044 | #ifdef CONFIG_X86_64 | 947 | idt_setup_debugidt_traps(); |
1045 | memcpy(&debug_idt_table, &idt_table, IDT_ENTRIES * 16); | ||
1046 | set_nmi_gate(X86_TRAP_DB, &debug); | ||
1047 | set_nmi_gate(X86_TRAP_BP, &int3); | ||
1048 | #endif | ||
1049 | } | 948 | } |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index d40900914a72..70b90c0810d0 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -8779,7 +8779,7 @@ static void vmx_handle_external_intr(struct kvm_vcpu *vcpu) | |||
8779 | 8779 | ||
8780 | vector = exit_intr_info & INTR_INFO_VECTOR_MASK; | 8780 | vector = exit_intr_info & INTR_INFO_VECTOR_MASK; |
8781 | desc = (gate_desc *)vmx->host_idt_base + vector; | 8781 | desc = (gate_desc *)vmx->host_idt_base + vector; |
8782 | entry = gate_offset(*desc); | 8782 | entry = gate_offset(desc); |
8783 | asm volatile( | 8783 | asm volatile( |
8784 | #ifdef CONFIG_X86_64 | 8784 | #ifdef CONFIG_X86_64 |
8785 | "mov %%" _ASM_SP ", %[sp]\n\t" | 8785 | "mov %%" _ASM_SP ", %[sp]\n\t" |
diff --git a/arch/x86/math-emu/fpu_entry.c b/arch/x86/math-emu/fpu_entry.c index 0203baefb5c0..d4a7df2205b8 100644 --- a/arch/x86/math-emu/fpu_entry.c +++ b/arch/x86/math-emu/fpu_entry.c | |||
@@ -147,7 +147,7 @@ void math_emulate(struct math_emu_info *info) | |||
147 | } | 147 | } |
148 | 148 | ||
149 | code_descriptor = FPU_get_ldt_descriptor(FPU_CS); | 149 | code_descriptor = FPU_get_ldt_descriptor(FPU_CS); |
150 | if (SEG_D_SIZE(code_descriptor)) { | 150 | if (code_descriptor.d) { |
151 | /* The above test may be wrong, the book is not clear */ | 151 | /* The above test may be wrong, the book is not clear */ |
152 | /* Segmented 32 bit protected mode */ | 152 | /* Segmented 32 bit protected mode */ |
153 | addr_modes.default_mode = SEG32; | 153 | addr_modes.default_mode = SEG32; |
@@ -155,11 +155,10 @@ void math_emulate(struct math_emu_info *info) | |||
155 | /* 16 bit protected mode */ | 155 | /* 16 bit protected mode */ |
156 | addr_modes.default_mode = PM16; | 156 | addr_modes.default_mode = PM16; |
157 | } | 157 | } |
158 | FPU_EIP += code_base = SEG_BASE_ADDR(code_descriptor); | 158 | FPU_EIP += code_base = seg_get_base(&code_descriptor); |
159 | code_limit = code_base | 159 | code_limit = seg_get_limit(&code_descriptor) + 1; |
160 | + (SEG_LIMIT(code_descriptor) + | 160 | code_limit *= seg_get_granularity(&code_descriptor); |
161 | 1) * SEG_GRANULARITY(code_descriptor) | 161 | code_limit += code_base - 1; |
162 | - 1; | ||
163 | if (code_limit < code_base) | 162 | if (code_limit < code_base) |
164 | code_limit = 0xffffffff; | 163 | code_limit = 0xffffffff; |
165 | } | 164 | } |
diff --git a/arch/x86/math-emu/fpu_system.h b/arch/x86/math-emu/fpu_system.h index a179254a5122..699f329f1d40 100644 --- a/arch/x86/math-emu/fpu_system.h +++ b/arch/x86/math-emu/fpu_system.h | |||
@@ -34,17 +34,43 @@ static inline struct desc_struct FPU_get_ldt_descriptor(unsigned seg) | |||
34 | return ret; | 34 | return ret; |
35 | } | 35 | } |
36 | 36 | ||
37 | #define SEG_D_SIZE(x) ((x).b & (3 << 21)) | 37 | #define SEG_TYPE_WRITABLE (1U << 1) |
38 | #define SEG_G_BIT(x) ((x).b & (1 << 23)) | 38 | #define SEG_TYPE_EXPANDS_DOWN (1U << 2) |
39 | #define SEG_GRANULARITY(x) (((x).b & (1 << 23)) ? 4096 : 1) | 39 | #define SEG_TYPE_EXECUTE (1U << 3) |
40 | #define SEG_286_MODE(x) ((x).b & ( 0xff000000 | 0xf0000 | (1 << 23))) | 40 | #define SEG_TYPE_EXPAND_MASK (SEG_TYPE_EXPANDS_DOWN | SEG_TYPE_EXECUTE) |
41 | #define SEG_BASE_ADDR(s) (((s).b & 0xff000000) \ | 41 | #define SEG_TYPE_EXECUTE_MASK (SEG_TYPE_WRITABLE | SEG_TYPE_EXECUTE) |
42 | | (((s).b & 0xff) << 16) | ((s).a >> 16)) | 42 | |
43 | #define SEG_LIMIT(s) (((s).b & 0xff0000) | ((s).a & 0xffff)) | 43 | static inline unsigned long seg_get_base(struct desc_struct *d) |
44 | #define SEG_EXECUTE_ONLY(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 11)) | 44 | { |
45 | #define SEG_WRITE_PERM(s) (((s).b & ((1 << 11) | (1 << 9))) == (1 << 9)) | 45 | unsigned long base = (unsigned long)d->base2 << 24; |
46 | #define SEG_EXPAND_DOWN(s) (((s).b & ((1 << 11) | (1 << 10))) \ | 46 | |
47 | == (1 << 10)) | 47 | return base | ((unsigned long)d->base1 << 16) | d->base0; |
48 | } | ||
49 | |||
50 | static inline unsigned long seg_get_limit(struct desc_struct *d) | ||
51 | { | ||
52 | return ((unsigned long)d->limit1 << 16) | d->limit0; | ||
53 | } | ||
54 | |||
55 | static inline unsigned long seg_get_granularity(struct desc_struct *d) | ||
56 | { | ||
57 | return d->g ? 4096 : 1; | ||
58 | } | ||
59 | |||
60 | static inline bool seg_expands_down(struct desc_struct *d) | ||
61 | { | ||
62 | return (d->type & SEG_TYPE_EXPAND_MASK) == SEG_TYPE_EXPANDS_DOWN; | ||
63 | } | ||
64 | |||
65 | static inline bool seg_execute_only(struct desc_struct *d) | ||
66 | { | ||
67 | return (d->type & SEG_TYPE_EXECUTE_MASK) == SEG_TYPE_EXECUTE; | ||
68 | } | ||
69 | |||
70 | static inline bool seg_writable(struct desc_struct *d) | ||
71 | { | ||
72 | return (d->type & SEG_TYPE_EXECUTE_MASK) == SEG_TYPE_WRITABLE; | ||
73 | } | ||
48 | 74 | ||
49 | #define I387 (¤t->thread.fpu.state) | 75 | #define I387 (¤t->thread.fpu.state) |
50 | #define FPU_info (I387->soft.info) | 76 | #define FPU_info (I387->soft.info) |
diff --git a/arch/x86/math-emu/get_address.c b/arch/x86/math-emu/get_address.c index b8ef9f9d2ffc..c48967c6a0e2 100644 --- a/arch/x86/math-emu/get_address.c +++ b/arch/x86/math-emu/get_address.c | |||
@@ -159,17 +159,18 @@ static long pm_address(u_char FPU_modrm, u_char segment, | |||
159 | } | 159 | } |
160 | 160 | ||
161 | descriptor = FPU_get_ldt_descriptor(addr->selector); | 161 | descriptor = FPU_get_ldt_descriptor(addr->selector); |
162 | base_address = SEG_BASE_ADDR(descriptor); | 162 | base_address = seg_get_base(&descriptor); |
163 | address = base_address + offset; | 163 | address = base_address + offset; |
164 | limit = base_address | 164 | limit = seg_get_limit(&descriptor) + 1; |
165 | + (SEG_LIMIT(descriptor) + 1) * SEG_GRANULARITY(descriptor) - 1; | 165 | limit *= seg_get_granularity(&descriptor); |
166 | limit += base_address - 1; | ||
166 | if (limit < base_address) | 167 | if (limit < base_address) |
167 | limit = 0xffffffff; | 168 | limit = 0xffffffff; |
168 | 169 | ||
169 | if (SEG_EXPAND_DOWN(descriptor)) { | 170 | if (seg_expands_down(&descriptor)) { |
170 | if (SEG_G_BIT(descriptor)) | 171 | if (descriptor.g) { |
171 | seg_top = 0xffffffff; | 172 | seg_top = 0xffffffff; |
172 | else { | 173 | } else { |
173 | seg_top = base_address + (1 << 20); | 174 | seg_top = base_address + (1 << 20); |
174 | if (seg_top < base_address) | 175 | if (seg_top < base_address) |
175 | seg_top = 0xffffffff; | 176 | seg_top = 0xffffffff; |
@@ -182,8 +183,8 @@ static long pm_address(u_char FPU_modrm, u_char segment, | |||
182 | (address > limit) || (address < base_address) ? 0 : | 183 | (address > limit) || (address < base_address) ? 0 : |
183 | ((limit - address) >= 254 ? 255 : limit - address + 1); | 184 | ((limit - address) >= 254 ? 255 : limit - address + 1); |
184 | } | 185 | } |
185 | if (SEG_EXECUTE_ONLY(descriptor) || | 186 | if (seg_execute_only(&descriptor) || |
186 | (!SEG_WRITE_PERM(descriptor) && (FPU_modrm & FPU_WRITE_BIT))) { | 187 | (!seg_writable(&descriptor) && (FPU_modrm & FPU_WRITE_BIT))) { |
187 | access_limit = 0; | 188 | access_limit = 0; |
188 | } | 189 | } |
189 | return address; | 190 | return address; |
diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c index 0cdf14cf3270..b836a7274e12 100644 --- a/arch/x86/mm/fault.c +++ b/arch/x86/mm/fault.c | |||
@@ -1258,10 +1258,6 @@ static inline bool smap_violation(int error_code, struct pt_regs *regs) | |||
1258 | * This routine handles page faults. It determines the address, | 1258 | * This routine handles page faults. It determines the address, |
1259 | * and the problem, and then passes it off to one of the appropriate | 1259 | * and the problem, and then passes it off to one of the appropriate |
1260 | * routines. | 1260 | * routines. |
1261 | * | ||
1262 | * This function must have noinline because both callers | ||
1263 | * {,trace_}do_page_fault() have notrace on. Having this an actual function | ||
1264 | * guarantees there's a function trace entry. | ||
1265 | */ | 1261 | */ |
1266 | static noinline void | 1262 | static noinline void |
1267 | __do_page_fault(struct pt_regs *regs, unsigned long error_code, | 1263 | __do_page_fault(struct pt_regs *regs, unsigned long error_code, |
@@ -1494,27 +1490,6 @@ good_area: | |||
1494 | } | 1490 | } |
1495 | NOKPROBE_SYMBOL(__do_page_fault); | 1491 | NOKPROBE_SYMBOL(__do_page_fault); |
1496 | 1492 | ||
1497 | dotraplinkage void notrace | ||
1498 | do_page_fault(struct pt_regs *regs, unsigned long error_code) | ||
1499 | { | ||
1500 | unsigned long address = read_cr2(); /* Get the faulting address */ | ||
1501 | enum ctx_state prev_state; | ||
1502 | |||
1503 | /* | ||
1504 | * We must have this function tagged with __kprobes, notrace and call | ||
1505 | * read_cr2() before calling anything else. To avoid calling any kind | ||
1506 | * of tracing machinery before we've observed the CR2 value. | ||
1507 | * | ||
1508 | * exception_{enter,exit}() contain all sorts of tracepoints. | ||
1509 | */ | ||
1510 | |||
1511 | prev_state = exception_enter(); | ||
1512 | __do_page_fault(regs, error_code, address); | ||
1513 | exception_exit(prev_state); | ||
1514 | } | ||
1515 | NOKPROBE_SYMBOL(do_page_fault); | ||
1516 | |||
1517 | #ifdef CONFIG_TRACING | ||
1518 | static nokprobe_inline void | 1493 | static nokprobe_inline void |
1519 | trace_page_fault_entries(unsigned long address, struct pt_regs *regs, | 1494 | trace_page_fault_entries(unsigned long address, struct pt_regs *regs, |
1520 | unsigned long error_code) | 1495 | unsigned long error_code) |
@@ -1525,22 +1500,24 @@ trace_page_fault_entries(unsigned long address, struct pt_regs *regs, | |||
1525 | trace_page_fault_kernel(address, regs, error_code); | 1500 | trace_page_fault_kernel(address, regs, error_code); |
1526 | } | 1501 | } |
1527 | 1502 | ||
1503 | /* | ||
1504 | * We must have this function blacklisted from kprobes, tagged with notrace | ||
1505 | * and call read_cr2() before calling anything else. To avoid calling any | ||
1506 | * kind of tracing machinery before we've observed the CR2 value. | ||
1507 | * | ||
1508 | * exception_{enter,exit}() contains all sorts of tracepoints. | ||
1509 | */ | ||
1528 | dotraplinkage void notrace | 1510 | dotraplinkage void notrace |
1529 | trace_do_page_fault(struct pt_regs *regs, unsigned long error_code) | 1511 | do_page_fault(struct pt_regs *regs, unsigned long error_code) |
1530 | { | 1512 | { |
1531 | /* | 1513 | unsigned long address = read_cr2(); /* Get the faulting address */ |
1532 | * The exception_enter and tracepoint processing could | ||
1533 | * trigger another page faults (user space callchain | ||
1534 | * reading) and destroy the original cr2 value, so read | ||
1535 | * the faulting address now. | ||
1536 | */ | ||
1537 | unsigned long address = read_cr2(); | ||
1538 | enum ctx_state prev_state; | 1514 | enum ctx_state prev_state; |
1539 | 1515 | ||
1540 | prev_state = exception_enter(); | 1516 | prev_state = exception_enter(); |
1541 | trace_page_fault_entries(address, regs, error_code); | 1517 | if (trace_pagefault_enabled()) |
1518 | trace_page_fault_entries(address, regs, error_code); | ||
1519 | |||
1542 | __do_page_fault(regs, error_code, address); | 1520 | __do_page_fault(regs, error_code, address); |
1543 | exception_exit(prev_state); | 1521 | exception_exit(prev_state); |
1544 | } | 1522 | } |
1545 | NOKPROBE_SYMBOL(trace_do_page_fault); | 1523 | NOKPROBE_SYMBOL(do_page_fault); |
1546 | #endif /* CONFIG_TRACING */ | ||
diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index 6c279c8f0a0e..ae2a2e2d6362 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c | |||
@@ -501,7 +501,7 @@ static void __init xen_load_gdt_boot(const struct desc_ptr *dtr) | |||
501 | static inline bool desc_equal(const struct desc_struct *d1, | 501 | static inline bool desc_equal(const struct desc_struct *d1, |
502 | const struct desc_struct *d2) | 502 | const struct desc_struct *d2) |
503 | { | 503 | { |
504 | return d1->a == d2->a && d1->b == d2->b; | 504 | return !memcmp(d1, d2, sizeof(*d1)); |
505 | } | 505 | } |
506 | 506 | ||
507 | static void load_TLS_descriptor(struct thread_struct *t, | 507 | static void load_TLS_descriptor(struct thread_struct *t, |
@@ -586,59 +586,91 @@ static void xen_write_ldt_entry(struct desc_struct *dt, int entrynum, | |||
586 | preempt_enable(); | 586 | preempt_enable(); |
587 | } | 587 | } |
588 | 588 | ||
589 | #ifdef CONFIG_X86_64 | ||
590 | struct trap_array_entry { | ||
591 | void (*orig)(void); | ||
592 | void (*xen)(void); | ||
593 | bool ist_okay; | ||
594 | }; | ||
595 | |||
596 | static struct trap_array_entry trap_array[] = { | ||
597 | { debug, xen_xendebug, true }, | ||
598 | { int3, xen_xenint3, true }, | ||
599 | { double_fault, xen_double_fault, true }, | ||
600 | #ifdef CONFIG_X86_MCE | ||
601 | { machine_check, xen_machine_check, true }, | ||
602 | #endif | ||
603 | { nmi, xen_nmi, true }, | ||
604 | { overflow, xen_overflow, false }, | ||
605 | #ifdef CONFIG_IA32_EMULATION | ||
606 | { entry_INT80_compat, xen_entry_INT80_compat, false }, | ||
607 | #endif | ||
608 | { page_fault, xen_page_fault, false }, | ||
609 | { divide_error, xen_divide_error, false }, | ||
610 | { bounds, xen_bounds, false }, | ||
611 | { invalid_op, xen_invalid_op, false }, | ||
612 | { device_not_available, xen_device_not_available, false }, | ||
613 | { coprocessor_segment_overrun, xen_coprocessor_segment_overrun, false }, | ||
614 | { invalid_TSS, xen_invalid_TSS, false }, | ||
615 | { segment_not_present, xen_segment_not_present, false }, | ||
616 | { stack_segment, xen_stack_segment, false }, | ||
617 | { general_protection, xen_general_protection, false }, | ||
618 | { spurious_interrupt_bug, xen_spurious_interrupt_bug, false }, | ||
619 | { coprocessor_error, xen_coprocessor_error, false }, | ||
620 | { alignment_check, xen_alignment_check, false }, | ||
621 | { simd_coprocessor_error, xen_simd_coprocessor_error, false }, | ||
622 | }; | ||
623 | |||
624 | static bool get_trap_addr(void **addr, unsigned int ist) | ||
625 | { | ||
626 | unsigned int nr; | ||
627 | bool ist_okay = false; | ||
628 | |||
629 | /* | ||
630 | * Replace trap handler addresses by Xen specific ones. | ||
631 | * Check for known traps using IST and whitelist them. | ||
632 | * The debugger ones are the only ones we care about. | ||
633 | * Xen will handle faults like double_fault, * so we should never see | ||
634 | * them. Warn if there's an unexpected IST-using fault handler. | ||
635 | */ | ||
636 | for (nr = 0; nr < ARRAY_SIZE(trap_array); nr++) { | ||
637 | struct trap_array_entry *entry = trap_array + nr; | ||
638 | |||
639 | if (*addr == entry->orig) { | ||
640 | *addr = entry->xen; | ||
641 | ist_okay = entry->ist_okay; | ||
642 | break; | ||
643 | } | ||
644 | } | ||
645 | |||
646 | if (WARN_ON(ist != 0 && !ist_okay)) | ||
647 | return false; | ||
648 | |||
649 | return true; | ||
650 | } | ||
651 | #endif | ||
652 | |||
589 | static int cvt_gate_to_trap(int vector, const gate_desc *val, | 653 | static int cvt_gate_to_trap(int vector, const gate_desc *val, |
590 | struct trap_info *info) | 654 | struct trap_info *info) |
591 | { | 655 | { |
592 | unsigned long addr; | 656 | unsigned long addr; |
593 | 657 | ||
594 | if (val->type != GATE_TRAP && val->type != GATE_INTERRUPT) | 658 | if (val->bits.type != GATE_TRAP && val->bits.type != GATE_INTERRUPT) |
595 | return 0; | 659 | return 0; |
596 | 660 | ||
597 | info->vector = vector; | 661 | info->vector = vector; |
598 | 662 | ||
599 | addr = gate_offset(*val); | 663 | addr = gate_offset(val); |
600 | #ifdef CONFIG_X86_64 | 664 | #ifdef CONFIG_X86_64 |
601 | /* | 665 | if (!get_trap_addr((void **)&addr, val->bits.ist)) |
602 | * Look for known traps using IST, and substitute them | ||
603 | * appropriately. The debugger ones are the only ones we care | ||
604 | * about. Xen will handle faults like double_fault, | ||
605 | * so we should never see them. Warn if | ||
606 | * there's an unexpected IST-using fault handler. | ||
607 | */ | ||
608 | if (addr == (unsigned long)debug) | ||
609 | addr = (unsigned long)xen_debug; | ||
610 | else if (addr == (unsigned long)int3) | ||
611 | addr = (unsigned long)xen_int3; | ||
612 | else if (addr == (unsigned long)stack_segment) | ||
613 | addr = (unsigned long)xen_stack_segment; | ||
614 | else if (addr == (unsigned long)double_fault) { | ||
615 | /* Don't need to handle these */ | ||
616 | return 0; | 666 | return 0; |
617 | #ifdef CONFIG_X86_MCE | ||
618 | } else if (addr == (unsigned long)machine_check) { | ||
619 | /* | ||
620 | * when xen hypervisor inject vMCE to guest, | ||
621 | * use native mce handler to handle it | ||
622 | */ | ||
623 | ; | ||
624 | #endif | ||
625 | } else if (addr == (unsigned long)nmi) | ||
626 | /* | ||
627 | * Use the native version as well. | ||
628 | */ | ||
629 | ; | ||
630 | else { | ||
631 | /* Some other trap using IST? */ | ||
632 | if (WARN_ON(val->ist != 0)) | ||
633 | return 0; | ||
634 | } | ||
635 | #endif /* CONFIG_X86_64 */ | 667 | #endif /* CONFIG_X86_64 */ |
636 | info->address = addr; | 668 | info->address = addr; |
637 | 669 | ||
638 | info->cs = gate_segment(*val); | 670 | info->cs = gate_segment(val); |
639 | info->flags = val->dpl; | 671 | info->flags = val->bits.dpl; |
640 | /* interrupt gates clear IF */ | 672 | /* interrupt gates clear IF */ |
641 | if (val->type == GATE_INTERRUPT) | 673 | if (val->bits.type == GATE_INTERRUPT) |
642 | info->flags |= 1 << 2; | 674 | info->flags |= 1 << 2; |
643 | 675 | ||
644 | return 1; | 676 | return 1; |
diff --git a/arch/x86/xen/irq.c b/arch/x86/xen/irq.c index 33e92955e09d..d4eff5676cfa 100644 --- a/arch/x86/xen/irq.c +++ b/arch/x86/xen/irq.c | |||
@@ -123,9 +123,6 @@ static const struct pv_irq_ops xen_irq_ops __initconst = { | |||
123 | 123 | ||
124 | .safe_halt = xen_safe_halt, | 124 | .safe_halt = xen_safe_halt, |
125 | .halt = xen_halt, | 125 | .halt = xen_halt, |
126 | #ifdef CONFIG_X86_64 | ||
127 | .adjust_exception_frame = xen_adjust_exception_frame, | ||
128 | #endif | ||
129 | }; | 126 | }; |
130 | 127 | ||
131 | void __init xen_init_irq_ops(void) | 128 | void __init xen_init_irq_ops(void) |
diff --git a/arch/x86/xen/xen-asm_64.S b/arch/x86/xen/xen-asm_64.S index 3a3b6a211584..dae2cc33afb5 100644 --- a/arch/x86/xen/xen-asm_64.S +++ b/arch/x86/xen/xen-asm_64.S | |||
@@ -16,11 +16,42 @@ | |||
16 | 16 | ||
17 | #include <linux/linkage.h> | 17 | #include <linux/linkage.h> |
18 | 18 | ||
19 | ENTRY(xen_adjust_exception_frame) | 19 | .macro xen_pv_trap name |
20 | mov 8+0(%rsp), %rcx | 20 | ENTRY(xen_\name) |
21 | mov 8+8(%rsp), %r11 | 21 | pop %rcx |
22 | ret $16 | 22 | pop %r11 |
23 | ENDPROC(xen_adjust_exception_frame) | 23 | jmp \name |
24 | END(xen_\name) | ||
25 | .endm | ||
26 | |||
27 | xen_pv_trap divide_error | ||
28 | xen_pv_trap debug | ||
29 | xen_pv_trap xendebug | ||
30 | xen_pv_trap int3 | ||
31 | xen_pv_trap xenint3 | ||
32 | xen_pv_trap nmi | ||
33 | xen_pv_trap overflow | ||
34 | xen_pv_trap bounds | ||
35 | xen_pv_trap invalid_op | ||
36 | xen_pv_trap device_not_available | ||
37 | xen_pv_trap double_fault | ||
38 | xen_pv_trap coprocessor_segment_overrun | ||
39 | xen_pv_trap invalid_TSS | ||
40 | xen_pv_trap segment_not_present | ||
41 | xen_pv_trap stack_segment | ||
42 | xen_pv_trap general_protection | ||
43 | xen_pv_trap page_fault | ||
44 | xen_pv_trap spurious_interrupt_bug | ||
45 | xen_pv_trap coprocessor_error | ||
46 | xen_pv_trap alignment_check | ||
47 | #ifdef CONFIG_X86_MCE | ||
48 | xen_pv_trap machine_check | ||
49 | #endif /* CONFIG_X86_MCE */ | ||
50 | xen_pv_trap simd_coprocessor_error | ||
51 | #ifdef CONFIG_IA32_EMULATION | ||
52 | xen_pv_trap entry_INT80_compat | ||
53 | #endif | ||
54 | xen_pv_trap hypervisor_callback | ||
24 | 55 | ||
25 | hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 | 56 | hypercall_iret = hypercall_page + __HYPERVISOR_iret * 32 |
26 | /* | 57 | /* |
diff --git a/arch/x86/xen/xen-ops.h b/arch/x86/xen/xen-ops.h index 70301ac0d414..c8a6d224f7ed 100644 --- a/arch/x86/xen/xen-ops.h +++ b/arch/x86/xen/xen-ops.h | |||
@@ -138,7 +138,6 @@ __visible void xen_restore_fl_direct(unsigned long); | |||
138 | __visible void xen_iret(void); | 138 | __visible void xen_iret(void); |
139 | __visible void xen_sysret32(void); | 139 | __visible void xen_sysret32(void); |
140 | __visible void xen_sysret64(void); | 140 | __visible void xen_sysret64(void); |
141 | __visible void xen_adjust_exception_frame(void); | ||
142 | 141 | ||
143 | extern int xen_panic_handler_init(void); | 142 | extern int xen_panic_handler_init(void); |
144 | 143 | ||
diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 2d43118077e4..1ab4bd11f5f3 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c | |||
@@ -1653,10 +1653,8 @@ void xen_callback_vector(void) | |||
1653 | return; | 1653 | return; |
1654 | } | 1654 | } |
1655 | pr_info("Xen HVM callback vector for event delivery is enabled\n"); | 1655 | pr_info("Xen HVM callback vector for event delivery is enabled\n"); |
1656 | /* in the restore case the vector has already been allocated */ | 1656 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, |
1657 | if (!test_bit(HYPERVISOR_CALLBACK_VECTOR, used_vectors)) | 1657 | xen_hvm_callback_vector); |
1658 | alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR, | ||
1659 | xen_hvm_callback_vector); | ||
1660 | } | 1658 | } |
1661 | } | 1659 | } |
1662 | #else | 1660 | #else |