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 |
