Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1720440 > unrolled thread
| Started by | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| First post | 2017-08-26 00:00 +0200 |
| Last post | 2017-08-26 00:20 +0200 |
| Articles | 20 on this page of 40 — 2 participants |
Back to article view | Back to linux.kernel
[patch V2 00/44] x86: Cleanup IDT code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 23/44] x86/percpu: Use static initializer for GDT entry Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 33/44] x86/idt: Move early IDT setup out of 32bit asm Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 44/44] x86/idt: Hide set_intr_gate() Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 38/44] x86/idt: Move regular trap init to tables Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 02/44] x86/irq: Unexport used_vectors Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 21/44] x86/tracing: Build tracepoints only when they are used Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 04/44] x86/irq: Remove duplicated used_vectors definition Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 39/44] x86/idt: Move APIC gate initialization to tables Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 11/44] x86/apic: Remove the duplicated tracing versions of interrupts Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:00 +0200
[patch V2 29/44] x86/idt: Move 32bit idt_descr to C code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 16/44] x86/idt: Remove tracing idt completely Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 05/44] x86/boot: Move EISA setup to a proper place Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 17/44] x86/idt: Cleanup the i386 low level entry macros Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 26/44] x86/gdt: Use bitfields for initialization Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 06/44] x86/tracing: Introduce a static key for exception tracing Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 18/44] x86/tracing: Disentangle pagefault and resched IPI tracing key Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 12/44] x86/irqwork: Get rid of duplicated tracing interrupt code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 20/44] x86/irq_work: Make it depend on APIC Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 09/44] x86/apic: Use this_cpu_ptr in local_timer_interrupt Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 27/44] x86/ldttss: Cleanup 32bit descriptors Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 13/44] x86/mce: Remove duplicated tracing interrupt code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 36/44] x86/idt: Move debug stack init to table based Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 15/44] x86/smp: Use static key for reschedule interrupt tracing Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 03/44] x86/irq: Get rid of the first_system_vector bogisity Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 14/44] x86/smp: Remove pointless duplicated interrupt code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 28/44] x86/idt: Create file for IDT related code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 07/44] x86/traps: Simplify pagefault tracing logic Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 37/44] x86/idt: Move ist stack based traps to table init Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 10/44] x86/irq: Get rid of duplicated trace_x86_platform_ipi() code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 31/44] x86/idt: Consolidate IDT invalidation Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 25/44] x86: Replace access to desc_struct:a/b fields Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
Re: [patch V2 25/44] x86: Replace access to desc_struct:a/b fields Boris Ostrovsky <boris.ostrovsky@oracle.com> - 2017-08-26 04:20 +0200
[patch V2 34/44] x86/idt: Prepare for table based init Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 22/44] x86/idt: Unify gate_struct handling for 32/64bit Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 32/44] x86/idt: Move early IDT handler setup to IDT code Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 08/44] x86/apic: Remove the duplicated tracing version of local_timer_interrupt Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 30/44] x86/idt: Remove unused set_trap_gate() Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 24/44] x86/fpu: Use bitfield accessors for desc_struct Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:10 +0200
[patch V2 01/44] x86/irq: Remove vector_used_by_percpu_irq() Thomas Gleixner <tglx@linutronix.de> - 2017-08-26 00:20 +0200
Page 1 of 2 [1] 2 Next page →
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 00/44] x86: Cleanup IDT code |
| Message-ID | <uiuNX-Yh-7@gated-at.bofh.it> |
The IDT code in x86 is a convoluted mess and contains quite some bogosities. One of the main offenders is the extra tracing IDT which has been introduced to reduce the impact of tracing on the exception vectors when tracepoints are disabled. This results in an unholy macro mess which magically creates IDT entries by prepending the exception handler name by trace_. For most exceptions the tracepoint overhead in the disabled case is two NOP5, which are negligible compared to the heavy work of the exception handler itself. Modern CPUs are pretty good in optimizing NOPs. The only two handlers where the overhead matters are the pagefault handler and the reschedule IPI, where an active tracepoint introduces more extra work. These two can be handled with separate static keys which reduces the impact to a minimum. As a result the whole tracing IDT machinery can be removed. The second part of the series cleans up the handling of IDT/GDT/LDT/TSS descriptors to get rid of macro based initialization via the obscure raw 32bit union fields a and b. The last part moves the setup of the IDT into a separate file, where all gate related code is moved to. The gate setup is converted to a table based mechanism so the resulting code is smaller and better understandable. The series applies on top of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/apic and is available as a git branch from git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git WIP.x86/apic There is more cleanup to come in the near future, which aims at replacing the braindamaged vector assignment mechanics, which has quite some shortcomings. Changes since V1: - Reordered patch series to maintain bisectability - Addressed the review comments - Addressed the fallout reported by kbuild robot - Picked up acks and reviewed by tags Thanks, tglx --- arch/x86/boot/compressed/eboot.c | 8 arch/x86/entry/entry_32.S | 20 - arch/x86/entry/entry_64.S | 26 -- arch/x86/entry/vdso/vma.c | 2 arch/x86/include/asm/desc.h | 248 +++------------------ arch/x86/include/asm/desc_defs.h | 122 +++++----- arch/x86/include/asm/entry_arch.h | 17 - arch/x86/include/asm/hw_irq.h | 20 - arch/x86/include/asm/irq.h | 4 arch/x86/include/asm/irq_work.h | 8 arch/x86/include/asm/segment.h | 4 arch/x86/include/asm/trace/common.h | 16 + arch/x86/include/asm/trace/exceptions.h | 8 arch/x86/include/asm/trace/irq_vectors.h | 51 +++- arch/x86/include/asm/traps.h | 10 arch/x86/include/asm/xen/hypercall.h | 6 arch/x86/kernel/Makefile | 3 arch/x86/kernel/apic/apic.c | 70 +---- arch/x86/kernel/apic/vector.c | 2 arch/x86/kernel/cpu/common.c | 9 arch/x86/kernel/cpu/mcheck/mce_amd.c | 16 - arch/x86/kernel/cpu/mcheck/therm_throt.c | 20 - arch/x86/kernel/cpu/mcheck/threshold.c | 16 - arch/x86/kernel/cpu/mshyperv.c | 9 arch/x86/kernel/eisa.c | 18 + arch/x86/kernel/head32.c | 4 arch/x86/kernel/head64.c | 6 arch/x86/kernel/head_32.S | 42 --- arch/x86/kernel/idt.c | 365 +++++++++++++++++++++++++++++++ arch/x86/kernel/irq.c | 40 +-- arch/x86/kernel/irq_work.c | 20 - arch/x86/kernel/irqinit.c | 102 -------- arch/x86/kernel/kvm.c | 4 arch/x86/kernel/machine_kexec_32.c | 14 - arch/x86/kernel/reboot.c | 4 arch/x86/kernel/setup.c | 4 arch/x86/kernel/setup_percpu.c | 9 arch/x86/kernel/smp.c | 81 +----- arch/x86/kernel/tls.c | 2 arch/x86/kernel/tracepoint.c | 57 +--- arch/x86/kernel/traps.c | 108 --------- arch/x86/kvm/vmx.c | 2 arch/x86/math-emu/fpu_entry.c | 11 arch/x86/math-emu/fpu_system.h | 48 +++- arch/x86/math-emu/get_address.c | 17 - arch/x86/mm/fault.c | 49 +--- arch/x86/xen/enlighten_pv.c | 14 - drivers/xen/events/events_base.c | 6 48 files changed, 759 insertions(+), 983 deletions(-)
[toc] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 23/44] x86/percpu: Use static initializer for GDT entry |
| Message-ID | <uiuNY-Yh-35@gated-at.bofh.it> |
| In reply to | #1720440 |
The IDT cleanup is about to remove pack_descriptor(). The GDT setup for the
percpu storage can be achieved with the static initializer as well. Replace
it.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/setup_percpu.c | 9 +++------
1 file changed, 3 insertions(+), 6 deletions(-)
--- a/arch/x86/kernel/setup_percpu.c
+++ b/arch/x86/kernel/setup_percpu.c
@@ -155,13 +155,10 @@ static void __init pcpup_populate_pte(un
static inline void setup_percpu_segment(int cpu)
{
#ifdef CONFIG_X86_32
- struct desc_struct gdt;
+ struct desc_struct d = GDT_ENTRY_INIT(0x8092, per_cpu_offset(cpu),
+ 0xFFFFF);
- pack_descriptor(&gdt, per_cpu_offset(cpu), 0xFFFFF,
- 0x2 | DESCTYPE_S, 0x8);
- gdt.s = 1;
- write_gdt_entry(get_cpu_gdt_rw(cpu),
- GDT_ENTRY_PERCPU, &gdt, DESCTYPE_S);
+ write_gdt_entry(get_cpu_gdt_rw(cpu), GDT_ENTRY_PERCPU, &d, DESCTYPE_S);
#endif
}
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 33/44] x86/idt: Move early IDT setup out of 32bit asm |
| Message-ID | <uiuNZ-Yh-37@gated-at.bofh.it> |
| In reply to | #1720440 |
The early IDT setup can be done in C code like it's done on 64 bit. Reuse
the 64 bit version.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/segment.h | 1 +
arch/x86/kernel/head32.c | 4 ++++
arch/x86/kernel/head_32.S | 36 ++----------------------------------
arch/x86/kernel/idt.c | 4 ++++
4 files changed, 11 insertions(+), 34 deletions(-)
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -238,6 +238,7 @@
#ifndef __ASSEMBLY__
extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE];
+extern void early_ignore_irq(void);
/*
* Load a segment. Fall back on loading the zero segment if something goes
--- a/arch/x86/kernel/head32.c
+++ b/arch/x86/kernel/head32.c
@@ -10,6 +10,7 @@
#include <linux/mm.h>
#include <linux/memblock.h>
+#include <asm/desc.h>
#include <asm/setup.h>
#include <asm/sections.h>
#include <asm/e820/api.h>
@@ -30,6 +31,9 @@ static void __init i386_default_early_se
asmlinkage __visible void __init i386_start_kernel(void)
{
cr4_init_shadow();
+
+ idt_setup_early_handler();
+
sanitize_boot_params(&boot_params);
x86_early_init_platform_quirks();
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -345,7 +345,6 @@ ENTRY(startup_32_smp)
movl %eax,%cr0
lgdt early_gdt_descr
- lidt idt_descr
ljmp $(__KERNEL_CS),$1f
1: movl $(__KERNEL_DS),%eax # reload all the segment registers
movl %eax,%ss # after changing gdt.
@@ -378,37 +377,6 @@ ENDPROC(startup_32_smp)
*/
__INIT
setup_once:
- /*
- * Set up a idt with 256 interrupt gates that push zero if there
- * is no error code and then jump to early_idt_handler_common.
- * It doesn't actually load the idt - that needs to be done on
- * each CPU. Interrupts are enabled elsewhere, when we can be
- * relatively sure everything is ok.
- */
-
- movl $idt_table,%edi
- movl $early_idt_handler_array,%eax
- movl $NUM_EXCEPTION_VECTORS,%ecx
-1:
- movl %eax,(%edi)
- movl %eax,4(%edi)
- /* interrupt gate, dpl=0, present */
- movl $(0x8E000000 + __KERNEL_CS),2(%edi)
- addl $EARLY_IDT_HANDLER_SIZE,%eax
- addl $8,%edi
- loop 1b
-
- movl $256 - NUM_EXCEPTION_VECTORS,%ecx
- movl $ignore_int,%edx
- movl $(__KERNEL_CS << 16),%eax
- movw %dx,%ax /* selector = 0x0010 = cs */
- movw $0x8E00,%dx /* interrupt gate - dpl=0, present */
-2:
- movl %eax,(%edi)
- movl %edx,4(%edi)
- addl $8,%edi
- loop 2b
-
#ifdef CONFIG_CC_STACKPROTECTOR
/*
* Configure the stack canary. The linker can't handle this by
@@ -498,7 +466,7 @@ ENDPROC(early_idt_handler_common)
/* This is the default interrupt "handler" :-) */
ALIGN
-ignore_int:
+ENTRY(early_ignore_irq)
cld
#ifdef CONFIG_PRINTK
pushl %eax
@@ -533,7 +501,7 @@ ENDPROC(early_idt_handler_common)
hlt_loop:
hlt
jmp hlt_loop
-ENDPROC(ignore_int)
+ENDPROC(early_ignore_irq)
__INITDATA
.align 4
GLOBAL(early_recursion_flag)
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -34,6 +34,10 @@ void __init idt_setup_early_handler(void
for (i = 0; i < NUM_EXCEPTION_VECTORS; i++)
set_intr_gate(i, early_idt_handler_array[i]);
+#ifdef CONFIG_X86_32
+ for ( ; i < NR_VECTORS; i++)
+ set_intr_gate(i, early_ignore_irq);
+#endif
load_idt((const struct desc_ptr *)&idt_descr);
}
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 44/44] x86/idt: Hide set_intr_gate() |
| Message-ID | <uiuNZ-Yh-41@gated-at.bofh.it> |
| In reply to | #1720440 |
set_intr_gate() is an internal function of the IDT code. The only user left
is the KVM code which replaces the pagefault handler eventually.
Provide an explicit update_intr_gate() function and make set_intr_gate()
static. While at it replace the magic number 14 in the KVM code with the
proper trap define.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Acked-by: Paolo Bonzini <pbonzini@redhat.com>
---
arch/x86/include/asm/desc.h | 2 +-
arch/x86/kernel/idt.c | 33 ++++++++++++++++++++-------------
arch/x86/kernel/kvm.c | 2 +-
3 files changed, 22 insertions(+), 15 deletions(-)
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -390,7 +390,7 @@ static inline void set_desc_limit(struct
desc->limit1 = (limit >> 16) & 0xf;
}
-void set_intr_gate(unsigned int n, const void *addr);
+void update_intr_gate(unsigned int n, const void *addr);
void alloc_intr_gate(unsigned int n, const void *addr);
extern unsigned long used_vectors[];
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -225,6 +225,22 @@ idt_setup_from_table(gate_desc *idt, con
}
}
+static void set_intr_gate(unsigned int n, const void *addr)
+{
+ struct idt_data data;
+
+ BUG_ON(n > 0xFF);
+
+ memset(&data, 0, sizeof(data));
+ data.vector = n;
+ data.addr = addr;
+ data.segment = __KERNEL_CS;
+ data.bits.type = GATE_INTERRUPT;
+ data.bits.p = 1;
+
+ idt_setup_from_table(idt_table, &data, 1, false);
+}
+
/**
* idt_setup_early_traps - Initialize the idt table with early traps
*
@@ -334,20 +350,11 @@ void idt_invalidate(void *addr)
load_idt(&idt);
}
-void set_intr_gate(unsigned int n, const void *addr)
+void __init update_intr_gate(unsigned int n, const void *addr)
{
- struct idt_data data;
-
- BUG_ON(n > 0xFF);
-
- memset(&data, 0, sizeof(data));
- data.vector = n;
- data.addr = addr;
- data.segment = __KERNEL_CS;
- data.bits.type = GATE_INTERRUPT;
- data.bits.p = 1;
-
- idt_setup_from_table(idt_table, &data, 1, false);
+ if (WARN_ON_ONCE(test_bit(n, used_vectors)))
+ return;
+ set_intr_gate(n, addr);
}
void alloc_intr_gate(unsigned int n, const void *addr)
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -455,7 +455,7 @@ static int kvm_cpu_down_prepare(unsigned
static void __init kvm_apf_trap_init(void)
{
- set_intr_gate(14, async_page_fault);
+ update_intr_gate(X86_TRAP_PF, async_page_fault);
}
void __init kvm_guest_init(void)
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 38/44] x86/idt: Move regular trap init to tables |
| Message-ID | <uiuNZ-Yh-39@gated-at.bofh.it> |
| In reply to | #1720440 |
Initialize the regular traps with a table.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/desc.h | 1
arch/x86/kernel/idt.c | 51 ++++++++++++++++++++++++++++++++++++++++++++
arch/x86/kernel/traps.c | 42 +-----------------------------------
3 files changed, 54 insertions(+), 40 deletions(-)
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -506,6 +506,7 @@ static inline void load_current_idt(void
extern void idt_setup_early_handler(void);
extern void idt_setup_early_traps(void);
+extern void idt_setup_traps(void);
#ifdef CONFIG_X86_64
extern void idt_setup_early_pf(void);
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -60,6 +60,49 @@ static const __initdata struct idt_data
#endif
};
+/*
+ * The default IDT entries which are set up in trap_init() before
+ * cpu_init() is invoked. Interrupt stacks cannot be used at that point and
+ * the traps which use them are reinitialized with IST after cpu_init() has
+ * set up TSS.
+ */
+static const __initdata struct idt_data def_idts[] = {
+ INTG(X86_TRAP_DE, divide_error),
+ INTG(X86_TRAP_NMI, nmi),
+ INTG(X86_TRAP_BR, bounds),
+ INTG(X86_TRAP_UD, invalid_op),
+ INTG(X86_TRAP_NM, device_not_available),
+ INTG(X86_TRAP_OLD_MF, coprocessor_segment_overrun),
+ INTG(X86_TRAP_TS, invalid_TSS),
+ INTG(X86_TRAP_NP, segment_not_present),
+ INTG(X86_TRAP_SS, stack_segment),
+ INTG(X86_TRAP_GP, general_protection),
+ INTG(X86_TRAP_SPURIOUS, spurious_interrupt_bug),
+ INTG(X86_TRAP_MF, coprocessor_error),
+ INTG(X86_TRAP_AC, alignment_check),
+ INTG(X86_TRAP_XF, simd_coprocessor_error),
+
+#ifdef CONFIG_X86_32
+ TSKG(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS),
+#else
+ INTG(X86_TRAP_DF, double_fault),
+#endif
+ INTG(X86_TRAP_DB, debug),
+ INTG(X86_TRAP_NMI, nmi),
+ INTG(X86_TRAP_BP, int3),
+
+#ifdef CONFIG_X86_MCE
+ INTG(X86_TRAP_MC, &machine_check),
+#endif
+
+ SYSG(X86_TRAP_OF, overflow),
+#if defined(CONFIG_IA32_EMULATION)
+ SYSG(IA32_SYSCALL_VECTOR, entry_INT80_compat),
+#elif defined(CONFIG_X86_32)
+ SYSG(IA32_SYSCALL_VECTOR, entry_INT80_32),
+#endif
+};
+
#ifdef CONFIG_X86_64
/*
* Early traps running on the DEFAULT_STACK because the other interrupt
@@ -153,6 +196,14 @@ void __init idt_setup_early_traps(void)
idt_setup_from_table(idt_table, early_idts, ARRAY_SIZE(early_idts));
}
+/**
+ * idt_setup_traps - Initialize the idt table with default traps
+ */
+void __init idt_setup_traps(void)
+{
+ idt_setup_from_table(idt_table, def_idts, ARRAY_SIZE(def_idts));
+}
+
#ifdef CONFIG_X86_64
/**
* idt_setup_early_pf - Initialize the idt table with early pagefault handler
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -925,46 +925,8 @@ dotraplinkage void do_iret_error(struct
void __init trap_init(void)
{
- int i;
-
- set_intr_gate(X86_TRAP_DE, divide_error);
- set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
- /* int4 can be called from all */
- set_system_intr_gate(X86_TRAP_OF, &overflow);
- set_intr_gate(X86_TRAP_BR, bounds);
- set_intr_gate(X86_TRAP_UD, invalid_op);
- set_intr_gate(X86_TRAP_NM, device_not_available);
-#ifdef CONFIG_X86_32
- set_task_gate(X86_TRAP_DF, GDT_ENTRY_DOUBLEFAULT_TSS);
-#else
- set_intr_gate_ist(X86_TRAP_DF, &double_fault, DOUBLEFAULT_STACK);
-#endif
- set_intr_gate(X86_TRAP_OLD_MF, coprocessor_segment_overrun);
- set_intr_gate(X86_TRAP_TS, invalid_TSS);
- set_intr_gate(X86_TRAP_NP, segment_not_present);
- set_intr_gate(X86_TRAP_SS, stack_segment);
- set_intr_gate(X86_TRAP_GP, general_protection);
- set_intr_gate(X86_TRAP_SPURIOUS, spurious_interrupt_bug);
- set_intr_gate(X86_TRAP_MF, coprocessor_error);
- set_intr_gate(X86_TRAP_AC, alignment_check);
-#ifdef CONFIG_X86_MCE
- set_intr_gate_ist(X86_TRAP_MC, &machine_check, MCE_STACK);
-#endif
- set_intr_gate(X86_TRAP_XF, simd_coprocessor_error);
-
- /* Reserve all the builtin and the syscall vector: */
- for (i = 0; i < FIRST_EXTERNAL_VECTOR; i++)
- set_bit(i, used_vectors);
-
-#ifdef CONFIG_IA32_EMULATION
- set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_compat);
- set_bit(IA32_SYSCALL_VECTOR, used_vectors);
-#endif
-
-#ifdef CONFIG_X86_32
- set_system_intr_gate(IA32_SYSCALL_VECTOR, entry_INT80_32);
- set_bit(IA32_SYSCALL_VECTOR, used_vectors);
-#endif
+ /* Initial trap setup. No IST stacks used. */
+ idt_setup_traps();
/*
* Set the IDT descriptor to a fixed read-only location, so that the
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 02/44] x86/irq: Unexport used_vectors |
| Message-ID | <uiuNZ-Yh-45@gated-at.bofh.it> |
| In reply to | #1720440 |
No modular users.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/traps.c | 1 -
1 file changed, 1 deletion(-)
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -83,7 +83,6 @@ gate_desc debug_idt_table[NR_VECTORS] __
gate_desc idt_table[NR_VECTORS] __page_aligned_bss;
DECLARE_BITMAP(used_vectors, NR_VECTORS);
-EXPORT_SYMBOL_GPL(used_vectors);
static inline void cond_local_irq_enable(struct pt_regs *regs)
{
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 21/44] x86/tracing: Build tracepoints only when they are used |
| Message-ID | <uiuNZ-Yh-43@gated-at.bofh.it> |
| In reply to | #1720440 |
The tracepoint macro magic emits code for all tracepoints in a event header file. That code stays around even if the tracepoint is not used at all. The linker does not discard it. Build the various irq_vector tracepoints dependent on the appropriate CONFIG switches. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/x86/include/asm/trace/irq_vectors.h | 36 ++++++++++++++++++++----------- 1 file changed, 24 insertions(+), 12 deletions(-) --- a/arch/x86/include/asm/trace/irq_vectors.h +++ b/arch/x86/include/asm/trace/irq_vectors.h @@ -7,6 +7,8 @@ #include <linux/tracepoint.h> #include <asm/trace/common.h> +#ifdef CONFIG_X86_LOCAL_APIC + extern int trace_resched_ipi_reg(void); extern void trace_resched_ipi_unreg(void); @@ -53,18 +55,6 @@ DEFINE_EVENT_FN(x86_irq_vector, name##_e DEFINE_IRQ_VECTOR_EVENT(local_timer); /* - * The ifdef is required because that tracepoint macro hell emits tracepoint - * code in files which include this header even if the tracepoint is not - * enabled. Brilliant stuff that. - */ -#ifdef CONFIG_SMP -/* - * reschedule - called when entering/exiting a reschedule vector handler - */ -DEFINE_RESCHED_IPI_EVENT(reschedule); -#endif - -/* * spurious_apic - called when entering/exiting a spurious apic vector handler */ DEFINE_IRQ_VECTOR_EVENT(spurious_apic); @@ -80,6 +70,7 @@ DEFINE_IRQ_VECTOR_EVENT(error_apic); */ DEFINE_IRQ_VECTOR_EVENT(x86_platform_ipi); +#ifdef CONFIG_IRQ_WORK /* * irq_work - called when entering/exiting a irq work interrupt * vector handler @@ -96,6 +87,18 @@ DEFINE_IRQ_VECTOR_EVENT(irq_work); * 4) goto 1 */ TRACE_EVENT_PERF_PERM(irq_work_exit, is_sampling_event(p_event) ? -EPERM : 0); +#endif + +/* + * The ifdef is required because that tracepoint macro hell emits tracepoint + * code in files which include this header even if the tracepoint is not + * enabled. Brilliant stuff that. + */ +#ifdef CONFIG_SMP +/* + * reschedule - called when entering/exiting a reschedule vector handler + */ +DEFINE_RESCHED_IPI_EVENT(reschedule); /* * call_function - called when entering/exiting a call function interrupt @@ -108,24 +111,33 @@ DEFINE_IRQ_VECTOR_EVENT(call_function); * single interrupt vector handler */ DEFINE_IRQ_VECTOR_EVENT(call_function_single); +#endif +#ifdef CONFIG_X86_MCE_THRESHOLD /* * threshold_apic - called when entering/exiting a threshold apic interrupt * vector handler */ DEFINE_IRQ_VECTOR_EVENT(threshold_apic); +#endif +#ifdef CONFIG_X86_MCE_AMD /* * deferred_error_apic - called when entering/exiting a deferred apic interrupt * vector handler */ DEFINE_IRQ_VECTOR_EVENT(deferred_error_apic); +#endif +#ifdef CONFIG_X86_THERMAL_VECTOR /* * thermal_apic - called when entering/exiting a thermal apic interrupt * vector handler */ DEFINE_IRQ_VECTOR_EVENT(thermal_apic); +#endif + +#endif /* CONFIG_X86_LOCAL_APIC */ #undef TRACE_INCLUDE_PATH #define TRACE_INCLUDE_PATH .
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 04/44] x86/irq: Remove duplicated used_vectors definition |
| Message-ID | <uiuNY-Yh-31@gated-at.bofh.it> |
| In reply to | #1720440 |
Remove the unparseable comment in the other place while at it. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/x86/include/asm/desc.h | 1 - arch/x86/include/asm/irq.h | 3 --- 2 files changed, 4 deletions(-) --- a/arch/x86/include/asm/desc.h +++ b/arch/x86/include/asm/desc.h @@ -483,7 +483,6 @@ static inline void _set_gate(int gate, u 0, 0, __KERNEL_CS); \ } while (0) -/* used_vectors is BITMAP for irq is not managed by percpu vector_irq */ extern unsigned long used_vectors[]; static inline void alloc_system_vector(int vector) --- a/arch/x86/include/asm/irq.h +++ b/arch/x86/include/asm/irq.h @@ -42,9 +42,6 @@ extern bool handle_irq(struct irq_desc * extern __visible unsigned int do_IRQ(struct pt_regs *regs); -/* Interrupt vector management */ -extern DECLARE_BITMAP(used_vectors, NR_VECTORS); - extern void init_ISA_irqs(void); #ifdef CONFIG_X86_LOCAL_APIC
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 39/44] x86/idt: Move APIC gate initialization to tables |
| Message-ID | <uiuNZ-Yh-47@gated-at.bofh.it> |
| In reply to | #1720440 |
Replace the APIC/SMP vector gate initialization with the table based
mechanism.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/desc.h | 1
arch/x86/kernel/idt.c | 48 ++++++++++++++++++++++++++++++
arch/x86/kernel/irqinit.c | 69 --------------------------------------------
3 files changed, 50 insertions(+), 68 deletions(-)
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -507,6 +507,7 @@ static inline void load_current_idt(void
extern void idt_setup_early_handler(void);
extern void idt_setup_early_traps(void);
extern void idt_setup_traps(void);
+extern void idt_setup_apic_and_irq_gates(void);
#ifdef CONFIG_X86_64
extern void idt_setup_early_pf(void);
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -103,6 +103,46 @@ static const __initdata struct idt_data
#endif
};
+/*
+ * The APIC and SMP idt entries
+ */
+static const __initdata struct idt_data apic_idts[] = {
+#ifdef CONFIG_SMP
+ INTG(RESCHEDULE_VECTOR, reschedule_interrupt),
+ INTG(CALL_FUNCTION_VECTOR, call_function_interrupt),
+ INTG(CALL_FUNCTION_SINGLE_VECTOR, call_function_single_interrupt),
+ INTG(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt),
+ INTG(REBOOT_VECTOR, reboot_interrupt),
+#endif
+
+#ifdef CONFIG_X86_THERMAL_VECTOR
+ INTG(THERMAL_APIC_VECTOR, thermal_interrupt),
+#endif
+
+#ifdef CONFIG_X86_MCE_THRESHOLD
+ INTG(THRESHOLD_APIC_VECTOR, threshold_interrupt),
+#endif
+
+#ifdef CONFIG_X86_MCE_AMD
+ INTG(DEFERRED_ERROR_VECTOR, deferred_error_interrupt),
+#endif
+
+#ifdef CONFIG_X86_LOCAL_APIC
+ INTG(LOCAL_TIMER_VECTOR, apic_timer_interrupt),
+ INTG(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi),
+# ifdef CONFIG_HAVE_KVM
+ INTG(POSTED_INTR_VECTOR, kvm_posted_intr_ipi),
+ INTG(POSTED_INTR_WAKEUP_VECTOR, kvm_posted_intr_wakeup_ipi),
+ INTG(POSTED_INTR_NESTED_VECTOR, kvm_posted_intr_nested_ipi),
+# endif
+# ifdef CONFIG_IRQ_WORK
+ INTG(IRQ_WORK_VECTOR, irq_work_interrupt),
+# endif
+ INTG(SPURIOUS_APIC_VECTOR, spurious_interrupt),
+ INTG(ERROR_APIC_VECTOR, error_interrupt),
+#endif
+};
+
#ifdef CONFIG_X86_64
/*
* Early traps running on the DEFAULT_STACK because the other interrupt
@@ -241,6 +281,14 @@ void __init idt_setup_debugidt_traps(voi
#endif
/**
+ * idt_setup_apic_and_irq_gates - Setup APIC/SMP and normal interrupt gates
+ */
+void __init idt_setup_apic_and_irq_gates(void)
+{
+ idt_setup_from_table(idt_table, apic_idts, ARRAY_SIZE(apic_idts));
+}
+
+/**
* idt_setup_early_handler - Initializes the idt table with early handlers
*/
void __init idt_setup_early_handler(void)
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -87,73 +87,6 @@ void __init init_IRQ(void)
x86_init.irqs.intr_init();
}
-static void __init smp_intr_init(void)
-{
-#ifdef CONFIG_SMP
- /*
- * The reschedule interrupt is a CPU-to-CPU reschedule-helper
- * IPI, driven by wakeup.
- */
- alloc_intr_gate(RESCHEDULE_VECTOR, reschedule_interrupt);
-
- /* IPI for generic function call */
- alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
-
- /* IPI for generic single function call */
- alloc_intr_gate(CALL_FUNCTION_SINGLE_VECTOR,
- call_function_single_interrupt);
-
- /* Low priority IPI to cleanup after moving an irq */
- set_intr_gate(IRQ_MOVE_CLEANUP_VECTOR, irq_move_cleanup_interrupt);
- set_bit(IRQ_MOVE_CLEANUP_VECTOR, used_vectors);
-
- /* IPI used for rebooting/stopping */
- alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt);
-#endif /* CONFIG_SMP */
-}
-
-static void __init apic_intr_init(void)
-{
- smp_intr_init();
-
-#ifdef CONFIG_X86_THERMAL_VECTOR
- alloc_intr_gate(THERMAL_APIC_VECTOR, thermal_interrupt);
-#endif
-#ifdef CONFIG_X86_MCE_THRESHOLD
- alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt);
-#endif
-
-#ifdef CONFIG_X86_MCE_AMD
- alloc_intr_gate(DEFERRED_ERROR_VECTOR, deferred_error_interrupt);
-#endif
-
-#ifdef CONFIG_X86_LOCAL_APIC
- /* self generated IPI for local APIC timer */
- alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt);
-
- /* IPI for X86 platform specific use */
- alloc_intr_gate(X86_PLATFORM_IPI_VECTOR, x86_platform_ipi);
-#ifdef CONFIG_HAVE_KVM
- /* IPI for KVM to deliver posted interrupt */
- alloc_intr_gate(POSTED_INTR_VECTOR, kvm_posted_intr_ipi);
- /* IPI for KVM to deliver interrupt to wake up tasks */
- alloc_intr_gate(POSTED_INTR_WAKEUP_VECTOR, kvm_posted_intr_wakeup_ipi);
- /* IPI for KVM to deliver nested posted interrupt */
- alloc_intr_gate(POSTED_INTR_NESTED_VECTOR, kvm_posted_intr_nested_ipi);
-#endif
-
- /* IPI vectors for APIC spurious and error interrupts */
- alloc_intr_gate(SPURIOUS_APIC_VECTOR, spurious_interrupt);
- alloc_intr_gate(ERROR_APIC_VECTOR, error_interrupt);
-
- /* IRQ work interrupts: */
-# ifdef CONFIG_IRQ_WORK
- alloc_intr_gate(IRQ_WORK_VECTOR, irq_work_interrupt);
-# endif
-
-#endif
-}
-
void __init native_init_IRQ(void)
{
int i;
@@ -161,7 +94,7 @@ void __init native_init_IRQ(void)
/* Execute any quirks before the call gates are initialised: */
x86_init.irqs.pre_vector_init();
- apic_intr_init();
+ idt_setup_apic_and_irq_gates();
/*
* Cover the whole vector space, no vector can escape
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:00 +0200 |
| Subject | [patch V2 11/44] x86/apic: Remove the duplicated tracing versions of interrupts |
| Message-ID | <uiuNZ-Yh-49@gated-at.bofh.it> |
| In reply to | #1720440 |
The error and the spurious interrupt are really rare events and not at all
so performance sensitive that two NOP5s can not be tolerated when tracing
is disabled.
Remove the nonsense.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Reviewed-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
arch/x86/include/asm/hw_irq.h | 4 +--
arch/x86/kernel/apic/apic.c | 43 +++++++++---------------------------------
2 files changed, 12 insertions(+), 35 deletions(-)
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -48,15 +48,15 @@ extern asmlinkage void call_function_sin
#ifdef CONFIG_TRACING
/* Interrupt handlers registered during init_IRQ */
-extern void trace_error_interrupt(void);
extern void trace_irq_work_interrupt(void);
-extern void trace_spurious_interrupt(void);
extern void trace_thermal_interrupt(void);
extern void trace_reschedule_interrupt(void);
extern void trace_threshold_interrupt(void);
extern void trace_deferred_error_interrupt(void);
extern void trace_call_function_interrupt(void);
extern void trace_call_function_single_interrupt(void);
+#define trace_error_interrupt error_interrupt
+#define trace_spurious_interrupt spurious_interrupt
#define trace_x86_platform_ipi x86_platform_ipi
#define trace_apic_timer_interrupt apic_timer_interrupt
#define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -1899,10 +1899,14 @@ void __init register_lapic_address(unsig
/*
* This interrupt should _never_ happen with our APIC/SMP architecture
*/
-static void __smp_spurious_interrupt(u8 vector)
+__visible void __irq_entry smp_spurious_interrupt(struct pt_regs *regs)
{
+ u8 vector = ~regs->orig_ax;
u32 v;
+ entering_irq();
+ trace_spurious_apic_entry(vector);
+
/*
* Check if this really is a spurious interrupt and ACK it
* if it is a vectored one. Just in case...
@@ -1917,22 +1921,7 @@ static void __smp_spurious_interrupt(u8
/* see sw-dev-man vol 3, chapter 7.4.13.5 */
pr_info("spurious APIC interrupt through vector %02x on CPU#%d, "
"should never happen.\n", vector, smp_processor_id());
-}
-__visible void __irq_entry smp_spurious_interrupt(struct pt_regs *regs)
-{
- entering_irq();
- __smp_spurious_interrupt(~regs->orig_ax);
- exiting_irq();
-}
-
-__visible void __irq_entry smp_trace_spurious_interrupt(struct pt_regs *regs)
-{
- u8 vector = ~regs->orig_ax;
-
- entering_irq();
- trace_spurious_apic_entry(vector);
- __smp_spurious_interrupt(vector);
trace_spurious_apic_exit(vector);
exiting_irq();
}
@@ -1940,10 +1929,8 @@ static void __smp_spurious_interrupt(u8
/*
* This interrupt should never happen with our APIC/SMP architecture
*/
-static void __smp_error_interrupt(struct pt_regs *regs)
+__visible void __irq_entry smp_error_interrupt(struct pt_regs *regs)
{
- u32 v;
- u32 i = 0;
static const char * const error_interrupt_reason[] = {
"Send CS error", /* APIC Error Bit 0 */
"Receive CS error", /* APIC Error Bit 1 */
@@ -1954,6 +1941,10 @@ static void __smp_error_interrupt(struct
"Received illegal vector", /* APIC Error Bit 6 */
"Illegal register address", /* APIC Error Bit 7 */
};
+ u32 v, i = 0;
+
+ entering_irq();
+ trace_error_apic_entry(ERROR_APIC_VECTOR);
/* First tickle the hardware, only then report what went on. -- REW */
if (lapic_get_maxlvt() > 3) /* Due to the Pentium erratum 3AP. */
@@ -1975,20 +1966,6 @@ static void __smp_error_interrupt(struct
apic_printk(APIC_DEBUG, KERN_CONT "\n");
-}
-
-__visible void __irq_entry smp_error_interrupt(struct pt_regs *regs)
-{
- entering_irq();
- __smp_error_interrupt(regs);
- exiting_irq();
-}
-
-__visible void __irq_entry smp_trace_error_interrupt(struct pt_regs *regs)
-{
- entering_irq();
- trace_error_apic_entry(ERROR_APIC_VECTOR);
- __smp_error_interrupt(regs);
trace_error_apic_exit(ERROR_APIC_VECTOR);
exiting_irq();
}
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 29/44] x86/idt: Move 32bit idt_descr to C code |
| Message-ID | <uiuXE-1gP-3@gated-at.bofh.it> |
| In reply to | #1720440 |
32bit has the idt_descr sitting in the low level assembly entry code. There
is no reason for that. Move it into the C file and use the 64bit version of
it.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/head_32.S | 6 ------
arch/x86/kernel/idt.c | 10 +++++-----
2 files changed, 5 insertions(+), 11 deletions(-)
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -622,7 +622,6 @@ ENTRY(initial_stack)
.data
.globl boot_gdt_descr
-.globl idt_descr
ALIGN
# early boot GDT descriptor (must use 1:1 address mapping)
@@ -631,11 +630,6 @@ ENTRY(initial_stack)
.word __BOOT_DS+7
.long boot_gdt - __PAGE_OFFSET
- .word 0 # 32-bit align idt_desc.address
-idt_descr:
- .word IDT_ENTRIES*8-1 # idt contains 256 entries
- .long idt_table
-
# boot GDT descriptor (later on used by CPU#0):
.word 0 # 32 bit align gdt_desc.address
ENTRY(early_gdt_descr)
--- a/arch/x86/kernel/idt.c
+++ b/arch/x86/kernel/idt.c
@@ -10,15 +10,15 @@
/* Must be page-aligned because the real IDT is used in a fixmap. */
gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss;
-#ifdef CONFIG_X86_64
-/* No need to be aligned, but done to keep all IDTs defined the same way. */
-gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss;
-
struct desc_ptr idt_descr __ro_after_init = {
- .size = IDT_ENTRIES * 16 - 1,
+ .size = (IDT_ENTRIES * 2 * sizeof(unsigned long)) - 1,
.address = (unsigned long) idt_table,
};
+#ifdef CONFIG_X86_64
+/* No need to be aligned, but done to keep all IDTs defined the same way. */
+gate_desc debug_idt_table[IDT_ENTRIES] __page_aligned_bss;
+
const struct desc_ptr debug_idt_descr = {
.size = IDT_ENTRIES * 16 - 1,
.address = (unsigned long) debug_idt_table,
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 16/44] x86/idt: Remove tracing idt completely |
| Message-ID | <uiuXE-1gP-5@gated-at.bofh.it> |
| In reply to | #1720440 |
No more users of the tracing idt. All exception tracepoints have been moved
into the regular handlers. Get rid of the mess which shouldn't have been
created in the first place.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/entry/entry_32.S | 12 +-----
arch/x86/entry/entry_64.S | 13 ------
arch/x86/include/asm/desc.h | 82 +++--------------------------------------
arch/x86/include/asm/hw_irq.h | 20 ----------
arch/x86/include/asm/segment.h | 3 -
arch/x86/kernel/tracepoint.c | 43 ---------------------
arch/x86/kernel/traps.c | 6 ---
7 files changed, 9 insertions(+), 170 deletions(-)
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -673,16 +673,8 @@ ENTRY(name) \
jmp ret_from_intr; \
ENDPROC(name)
-
-#ifdef CONFIG_TRACING
-# define TRACE_BUILD_INTERRUPT(name, nr) BUILD_INTERRUPT3(trace_##name, nr, smp_trace_##name)
-#else
-# define TRACE_BUILD_INTERRUPT(name, nr)
-#endif
-
#define BUILD_INTERRUPT(name, nr) \
BUILD_INTERRUPT3(name, nr, smp_##name); \
- TRACE_BUILD_INTERRUPT(name, nr)
/* The include is where all of the SMP etc. interrupts come from */
#include <asm/entry_arch.h>
@@ -880,14 +872,14 @@ ENTRY(xen_failsafe_callback)
ENDPROC(xen_failsafe_callback)
BUILD_INTERRUPT3(xen_hvm_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
- xen_evtchn_do_upcall)
+ xen_evtchn_do_upcall)
#endif /* CONFIG_XEN */
#if IS_ENABLED(CONFIG_HYPERV)
BUILD_INTERRUPT3(hyperv_callback_vector, HYPERVISOR_CALLBACK_VECTOR,
- hyperv_vector_handler)
+ hyperv_vector_handler)
#endif /* CONFIG_HYPERV */
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -748,18 +748,6 @@ ENTRY(\sym)
END(\sym)
.endm
-#ifdef CONFIG_TRACING
-#define trace(sym) trace_##sym
-#define smp_trace(sym) smp_trace_##sym
-
-.macro trace_apicinterrupt num sym
-apicinterrupt3 \num trace(\sym) smp_trace(\sym)
-.endm
-#else
-.macro trace_apicinterrupt num sym do_sym
-.endm
-#endif
-
/* Make sure APIC interrupt handlers end up in the irqentry section: */
#if defined(CONFIG_FUNCTION_GRAPH_TRACER) || defined(CONFIG_KASAN)
# define PUSH_SECTION_IRQENTRY .pushsection .irqentry.text, "ax"
@@ -772,7 +760,6 @@ apicinterrupt3 \num trace(\sym) smp_trac
.macro apicinterrupt num sym do_sym
PUSH_SECTION_IRQENTRY
apicinterrupt3 \num \sym \do_sym
-trace_apicinterrupt \num \sym
POP_SECTION_IRQENTRY
.endm
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -421,35 +421,7 @@ static inline void set_nmi_gate(int gate
}
#endif
-#ifdef CONFIG_TRACING
-extern struct desc_ptr trace_idt_descr;
-extern gate_desc trace_idt_table[];
-static inline void write_trace_idt_entry(int entry, const gate_desc *gate)
-{
- write_idt_entry(trace_idt_table, entry, gate);
-}
-
-static inline void _trace_set_gate(int gate, unsigned type, void *addr,
- unsigned dpl, unsigned ist, unsigned seg)
-{
- gate_desc s;
-
- pack_gate(&s, type, (unsigned long)addr, dpl, ist, seg);
- /*
- * does not need to be atomic because it is only done once at
- * setup time
- */
- write_trace_idt_entry(gate, &s);
-}
-#else
-static inline void write_trace_idt_entry(int entry, const gate_desc *gate)
-{
-}
-
-#define _trace_set_gate(gate, type, addr, dpl, ist, seg)
-#endif
-
-static inline void _set_gate(int gate, unsigned type, void *addr,
+static inline void _set_gate(int gate, unsigned type, const void *addr,
unsigned dpl, unsigned ist, unsigned seg)
{
gate_desc s;
@@ -460,28 +432,13 @@ static inline void _set_gate(int gate, u
* setup time
*/
write_idt_entry(idt_table, gate, &s);
- write_trace_idt_entry(gate, &s);
}
-/*
- * This needs to use 'idt_table' rather than 'idt', and
- * thus use the _nonmapped_ version of the IDT, as the
- * Pentium F0 0F bugfix can have resulted in the mapped
- * IDT being write-protected.
- */
-#define set_intr_gate_notrace(n, addr) \
- do { \
- BUG_ON((unsigned)n > 0xFF); \
- _set_gate(n, GATE_INTERRUPT, (void *)addr, 0, 0, \
- __KERNEL_CS); \
- } while (0)
-
-#define set_intr_gate(n, addr) \
- do { \
- set_intr_gate_notrace(n, addr); \
- _trace_set_gate(n, GATE_INTERRUPT, (void *)trace_##addr,\
- 0, 0, __KERNEL_CS); \
- } while (0)
+static inline void set_intr_gate(unsigned int n, const void *addr)
+{
+ BUG_ON(n > 0xFF);
+ _set_gate(n, GATE_INTERRUPT, addr, 0, 0, __KERNEL_CS);
+}
extern unsigned long used_vectors[];
@@ -565,31 +522,6 @@ static inline void load_debug_idt(void)
}
#endif
-#ifdef CONFIG_TRACING
-extern atomic_t trace_idt_ctr;
-static inline bool is_trace_idt_enabled(void)
-{
- if (atomic_read(&trace_idt_ctr))
- return true;
-
- return false;
-}
-
-static inline void load_trace_idt(void)
-{
- load_idt((const struct desc_ptr *)&trace_idt_descr);
-}
-#else
-static inline bool is_trace_idt_enabled(void)
-{
- return false;
-}
-
-static inline void load_trace_idt(void)
-{
-}
-#endif
-
/*
* The load_current_idt() must be called with interrupts disabled
* to avoid races. That way the IDT will always be set back to the expected
@@ -601,8 +533,6 @@ static inline void load_current_idt(void
{
if (is_debug_idt_enabled())
load_debug_idt();
- else if (is_trace_idt_enabled())
- load_trace_idt();
else
load_idt((const struct desc_ptr *)&idt_descr);
}
--- 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_in
extern asmlinkage void call_function_interrupt(void);
extern asmlinkage void call_function_single_interrupt(void);
-#ifdef CONFIG_TRACING
-/* Interrupt handlers registered during init_IRQ */
-#define trace_reschedule_interrupt reschedule_interrupt
-#define trace_call_function_interrupt call_function_interrupt
-#define trace_call_function_single_interrupt call_function_single_interrupt
-#define trace_thermal_interrupt thermal_interrupt
-#define trace_threshold_interrupt threshold_interrupt
-#define trace_deferred_error_interrupt deferred_error_interrupt
-#define trace_irq_work_interrupt irq_work_interrupt
-#define trace_error_interrupt error_interrupt
-#define trace_spurious_interrupt spurious_interrupt
-#define trace_x86_platform_ipi x86_platform_ipi
-#define trace_apic_timer_interrupt apic_timer_interrupt
-#define trace_irq_move_cleanup_interrupt irq_move_cleanup_interrupt
-#define trace_reboot_interrupt reboot_interrupt
-#define trace_kvm_posted_intr_ipi kvm_posted_intr_ipi
-#define trace_kvm_posted_intr_wakeup_ipi kvm_posted_intr_wakeup_ipi
-#define trace_kvm_posted_intr_nested_ipi kvm_posted_intr_nested_ipi
-#endif /* CONFIG_TRACING */
-
#ifdef CONFIG_X86_LOCAL_APIC
struct irq_data;
struct pci_dev;
--- a/arch/x86/include/asm/segment.h
+++ b/arch/x86/include/asm/segment.h
@@ -238,9 +238,6 @@
#ifndef __ASSEMBLY__
extern const char early_idt_handler_array[NUM_EXCEPTION_VECTORS][EARLY_IDT_HANDLER_SIZE];
-#ifdef CONFIG_TRACING
-# define trace_early_idt_handler_array early_idt_handler_array
-#endif
/*
* Load a segment. Fall back on loading the zero segment if something goes
--- a/arch/x86/kernel/tracepoint.c
+++ b/arch/x86/kernel/tracepoint.c
@@ -10,58 +10,15 @@
#include <asm/hw_irq.h>
#include <asm/desc.h>
-atomic_t trace_idt_ctr = ATOMIC_INIT(0);
-struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1,
- (unsigned long) trace_idt_table };
-
-/* No need to be aligned, but done to keep all IDTs defined the same way. */
-gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss;
-
DEFINE_STATIC_KEY_FALSE(trace_irqvectors_key);
-static int trace_irq_vector_refcount;
-static DEFINE_MUTEX(irq_vector_mutex);
-
-static void set_trace_idt_ctr(int val)
-{
- atomic_set(&trace_idt_ctr, val);
- /* Ensure the trace_idt_ctr is set before sending IPI */
- wmb();
-}
-
-static void switch_idt(void *arg)
-{
- unsigned long flags;
-
- local_irq_save(flags);
- load_current_idt();
- local_irq_restore(flags);
-}
int trace_irq_vector_regfunc(void)
{
static_branch_inc(&trace_irqvectors_key);
-
- mutex_lock(&irq_vector_mutex);
- if (!trace_irq_vector_refcount) {
- set_trace_idt_ctr(1);
- smp_call_function(switch_idt, NULL, 0);
- switch_idt(NULL);
- }
- trace_irq_vector_refcount++;
- mutex_unlock(&irq_vector_mutex);
return 0;
}
void trace_irq_vector_unregfunc(void)
{
static_branch_dec(&trace_irqvectors_key);
-
- mutex_lock(&irq_vector_mutex);
- trace_irq_vector_refcount--;
- if (!trace_irq_vector_refcount) {
- set_trace_idt_ctr(0);
- smp_call_function(switch_idt, NULL, 0);
- switch_idt(NULL);
- }
- mutex_unlock(&irq_vector_mutex);
}
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -939,12 +939,8 @@ void __init early_trap_init(void)
* stack. Using the original stack works well enough at this
* early stage. DEBUG_STACK will be equipped after cpu_init() in
* trap_init().
- *
- * We don't need to set trace_idt_table like set_intr_gate(),
- * since we don't have trace_debug and it will be reset to
- * 'debug' in trap_init() by set_intr_gate_ist().
*/
- set_intr_gate_notrace(X86_TRAP_DB, debug);
+ set_intr_gate(X86_TRAP_DB, debug);
/* int3 can be called from all */
set_system_intr_gate(X86_TRAP_BP, &int3);
#ifdef CONFIG_X86_32
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 05/44] x86/boot: Move EISA setup to a proper place |
| Message-ID | <uiuXE-1gP-7@gated-at.bofh.it> |
| In reply to | #1720440 |
EISA has absolutely nothing to do with traps. The EISA bus detection does
not need to run in the very early boot. It's good enough to run it before
the EISA bus and drivers are initialized.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/Makefile | 1 +
arch/x86/kernel/eisa.c | 18 ++++++++++++++++++
arch/x86/kernel/traps.c | 13 -------------
3 files changed, 19 insertions(+), 13 deletions(-)
--- a/arch/x86/kernel/Makefile
+++ b/arch/x86/kernel/Makefile
@@ -111,6 +111,7 @@ obj-$(CONFIG_PARAVIRT_SPINLOCKS)+= parav
obj-$(CONFIG_PARAVIRT_CLOCK) += pvclock.o
obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o
+obj-$(CONFIG_EISA) += eisa.o
obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o
obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
--- /dev/null
+++ b/arch/x86/kernel/eisa.c
@@ -0,0 +1,18 @@
+/*
+ * EISA specific code
+ *
+ * This file is licensed under the GPL V2
+ */
+#include <linux/ioport.h>
+#include <linux/eisa.h>
+
+static __init int eisa_bus_probe(void)
+{
+ void __iomem *p = ioremap(0x0FFFD9, 4);
+
+ if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
+ EISA_bus = 1;
+ iounmap(p);
+ return 0;
+}
+subsys_initcall(eisa_bus_probe);
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -38,11 +38,6 @@
#include <linux/smp.h>
#include <linux/io.h>
-#ifdef CONFIG_EISA
-#include <linux/ioport.h>
-#include <linux/eisa.h>
-#endif
-
#if defined(CONFIG_EDAC)
#include <linux/edac.h>
#endif
@@ -969,14 +964,6 @@ void __init trap_init(void)
{
int i;
-#ifdef CONFIG_EISA
- void __iomem *p = early_ioremap(0x0FFFD9, 4);
-
- if (readl(p) == 'E' + ('I'<<8) + ('S'<<16) + ('A'<<24))
- EISA_bus = 1;
- early_iounmap(p, 4);
-#endif
-
set_intr_gate(X86_TRAP_DE, divide_error);
set_intr_gate_ist(X86_TRAP_NMI, &nmi, NMI_STACK);
/* int4 can be called from all */
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 17/44] x86/idt: Cleanup the i386 low level entry macros |
| Message-ID | <uiuXE-1gP-13@gated-at.bofh.it> |
| In reply to | #1720440 |
Some of the entry function defines for i386 were explictely using the BUILD_INTERRUPT3() macro to prevent that the extra trace entry got added via BUILD_INTERRUPT(). No that the trace cruft is gone, the file can be cleaned up and converted to use BUILD_INTERRUPT() which avoids the ugly line breaks. Signed-off-by: Thomas Gleixner <tglx@linutronix.de> --- arch/x86/include/asm/entry_arch.h | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) --- a/arch/x86/include/asm/entry_arch.h +++ b/arch/x86/include/asm/entry_arch.h @@ -13,20 +13,16 @@ BUILD_INTERRUPT(reschedule_interrupt,RESCHEDULE_VECTOR) BUILD_INTERRUPT(call_function_interrupt,CALL_FUNCTION_VECTOR) BUILD_INTERRUPT(call_function_single_interrupt,CALL_FUNCTION_SINGLE_VECTOR) -BUILD_INTERRUPT3(irq_move_cleanup_interrupt, IRQ_MOVE_CLEANUP_VECTOR, - smp_irq_move_cleanup_interrupt) -BUILD_INTERRUPT3(reboot_interrupt, REBOOT_VECTOR, smp_reboot_interrupt) +BUILD_INTERRUPT(irq_move_cleanup_interrupt, IRQ_MOVE_CLEANUP_VECTOR) +BUILD_INTERRUPT(reboot_interrupt, REBOOT_VECTOR) #endif BUILD_INTERRUPT(x86_platform_ipi, X86_PLATFORM_IPI_VECTOR) #ifdef CONFIG_HAVE_KVM -BUILD_INTERRUPT3(kvm_posted_intr_ipi, POSTED_INTR_VECTOR, - smp_kvm_posted_intr_ipi) -BUILD_INTERRUPT3(kvm_posted_intr_wakeup_ipi, POSTED_INTR_WAKEUP_VECTOR, - smp_kvm_posted_intr_wakeup_ipi) -BUILD_INTERRUPT3(kvm_posted_intr_nested_ipi, POSTED_INTR_NESTED_VECTOR, - smp_kvm_posted_intr_nested_ipi) +BUILD_INTERRUPT(kvm_posted_intr_ipi, POSTED_INTR_VECTOR) +BUILD_INTERRUPT(kvm_posted_intr_wakeup_ipi, POSTED_INTR_WAKEUP_VECTOR) +BUILD_INTERRUPT(kvm_posted_intr_nested_ipi, POSTED_INTR_NESTED_VECTOR) #endif /*
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 26/44] x86/gdt: Use bitfields for initialization |
| Message-ID | <uiuXE-1gP-17@gated-at.bofh.it> |
| In reply to | #1720440 |
The GDT entry related code uses partially bitfields and macros which
initialize the two 16 bit parts of the entry by magic shift and mask
operations.
Clean it up and use the bitfields to initialize and access entries.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/entry/vdso/vma.c | 2 -
arch/x86/include/asm/desc.h | 26 ++++++++++++++---------
arch/x86/include/asm/desc_defs.h | 44 +++++++++++++++++----------------------
arch/x86/math-emu/fpu_system.h | 2 -
4 files changed, 38 insertions(+), 36 deletions(-)
--- 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)
* and 8 bits for the node)
*/
d.limit0 = cpu | ((node & 0xf) << 12);
- d.limit = node >> 4;
+ d.limit1 = node >> 4;
d.type = 5; /* RO data, expand down, accessed */
d.dpl = 3; /* Visible to user code */
d.s = 1; /* Not a system segment */
--- a/arch/x86/include/asm/desc.h
+++ b/arch/x86/include/asm/desc.h
@@ -23,7 +23,7 @@ static inline void fill_ldt(struct desc_
desc->s = 1;
desc->dpl = 0x3;
desc->p = info->seg_not_present ^ 1;
- desc->limit = (info->limit & 0xf0000) >> 16;
+ desc->limit1 = (info->limit & 0xf0000) >> 16;
desc->avl = info->useable;
desc->d = info->seg_32bit;
desc->g = info->limit_in_pages;
@@ -170,14 +170,20 @@ static inline void pack_descriptor(struc
unsigned long limit, unsigned char type,
unsigned char flags)
{
- desc->a = ((base & 0xffff) << 16) | (limit & 0xffff);
- desc->b = (base & 0xff000000) | ((base & 0xff0000) >> 16) |
- (limit & 0x000f0000) | ((type & 0xff) << 8) |
- ((flags & 0xf) << 20);
- desc->p = 1;
+ desc->limit0 = (u16) limit;
+ desc->base0 = (u16) base;
+ desc->base1 = (base >> 16) & 0xFF;
+ desc->type = type & 0x0F;
+ desc->s = 0;
+ desc->dpl = 0;
+ desc->p = 1;
+ desc->limit1 = (limit >> 16) & 0xF;
+ desc->avl = (flags >> 0) & 0x01;
+ desc->l = (flags >> 1) & 0x01;
+ desc->d = (flags >> 2) & 0x01;
+ desc->g = (flags >> 3) & 0x01;
}
-
static inline void set_tssldt_descriptor(void *d, unsigned long addr,
unsigned type, unsigned size)
{
@@ -195,7 +201,7 @@ static inline void set_tssldt_descriptor
desc->base2 = (addr >> 24) & 0xFF;
desc->base3 = (u32) (addr >> 32);
#else
- pack_descriptor((struct desc_struct *)d, addr, size, 0x80 | type, 0);
+ pack_descriptor((struct desc_struct *)d, addr, size, type, 0);
#endif
}
@@ -395,13 +401,13 @@ static inline void set_desc_base(struct
static inline unsigned long get_desc_limit(const struct desc_struct *desc)
{
- return desc->limit0 | (desc->limit << 16);
+ return desc->limit0 | (desc->limit1 << 16);
}
static inline void set_desc_limit(struct desc_struct *desc, unsigned long limit)
{
desc->limit0 = limit & 0xffff;
- desc->limit = (limit >> 16) & 0xf;
+ desc->limit1 = (limit >> 16) & 0xf;
}
#ifdef CONFIG_X86_64
--- a/arch/x86/include/asm/desc_defs.h
+++ b/arch/x86/include/asm/desc_defs.h
@@ -11,34 +11,30 @@
#include <linux/types.h>
-/*
- * FIXME: Accessing the desc_struct through its fields is more elegant,
- * and should be the one valid thing to do. However, a lot of open code
- * still touches the a and b accessors, and doing this allow us to do it
- * incrementally. We keep the signature as a struct, rather than a union,
- * so we can get rid of it transparently in the future -- glommer
- */
/* 8 byte segment descriptor */
struct desc_struct {
- union {
- struct {
- unsigned int a;
- unsigned int b;
- };
- struct {
- u16 limit0;
- u16 base0;
- unsigned base1: 8, type: 4, s: 1, dpl: 2, p: 1;
- unsigned limit: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
- };
- };
+ u16 limit0;
+ u16 base0;
+ u16 base1: 8, type: 4, s: 1, dpl: 2, p: 1;
+ u16 limit1: 4, avl: 1, l: 1, d: 1, g: 1, base2: 8;
} __attribute__((packed));
-#define GDT_ENTRY_INIT(flags, base, limit) { { { \
- .a = ((limit) & 0xffff) | (((base) & 0xffff) << 16), \
- .b = (((base) & 0xff0000) >> 16) | (((flags) & 0xf0ff) << 8) | \
- ((limit) & 0xf0000) | ((base) & 0xff000000), \
- } } }
+#define GDT_ENTRY_INIT(flags, base, limit) \
+ { \
+ .limit0 = (u16) (limit), \
+ .limit1 = ((limit) >> 16) & 0x0F, \
+ .base0 = (u16) (base), \
+ .base1 = ((base) >> 16) & 0xFF, \
+ .base2 = ((base) >> 24) & 0xFF, \
+ .type = (flags & 0x0f), \
+ .s = (flags >> 4) & 0x01, \
+ .dpl = (flags >> 5) & 0x03, \
+ .p = (flags >> 7) & 0x01, \
+ .avl = (flags >> 12) & 0x01, \
+ .l = (flags >> 13) & 0x01, \
+ .d = (flags >> 14) & 0x01, \
+ .g = (flags >> 15) & 0x01, \
+ }
enum {
GATE_INTERRUPT = 0xE,
--- a/arch/x86/math-emu/fpu_system.h
+++ b/arch/x86/math-emu/fpu_system.h
@@ -49,7 +49,7 @@ static inline unsigned long seg_get_base
static inline unsigned long seg_get_limit(struct desc_struct *d)
{
- return ((unsigned long)d->limit << 16) | d->limit0;
+ return ((unsigned long)d->limit1 << 16) | d->limit0;
}
static inline unsigned long seg_get_granularity(struct desc_struct *d)
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 06/44] x86/tracing: Introduce a static key for exception tracing |
| Message-ID | <uiuXE-1gP-15@gated-at.bofh.it> |
| In reply to | #1720440 |
Switching the IDT just for avoiding tracepoints creates a complete
impenetrable macro/inline/ifdef mess.
There is no point in avoiding tracepoints for most of the traps/exceptions.
For the more expensive tracepoints, like pagefaults, this can be handled with
an explicit static key.
Preparatory patch to remove the tracing idt.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/trace/common.h | 15 +++++++++++++++
arch/x86/include/asm/trace/exceptions.h | 4 +---
arch/x86/include/asm/trace/irq_vectors.h | 4 +---
arch/x86/kernel/tracepoint.c | 9 ++++++++-
4 files changed, 25 insertions(+), 7 deletions(-)
--- /dev/null
+++ b/arch/x86/include/asm/trace/common.h
@@ -0,0 +1,15 @@
+#ifndef _ASM_TRACE_COMMON_H
+#define _ASM_TRACE_COMMON_H
+
+extern int trace_irq_vector_regfunc(void);
+extern void trace_irq_vector_unregfunc(void);
+
+#ifdef CONFIG_TRACING
+DECLARE_STATIC_KEY_FALSE(trace_irqvectors_key);
+#define trace_irqvectors_enabled() \
+ static_branch_unlikely(&trace_irqvectors_key)
+#else
+static inline bool trace_irqvectors_enabled(void) { return false; }
+#endif
+
+#endif
--- a/arch/x86/include/asm/trace/exceptions.h
+++ b/arch/x86/include/asm/trace/exceptions.h
@@ -5,9 +5,7 @@
#define _TRACE_PAGE_FAULT_H
#include <linux/tracepoint.h>
-
-extern int trace_irq_vector_regfunc(void);
-extern void trace_irq_vector_unregfunc(void);
+#include <asm/trace/common.h>
DECLARE_EVENT_CLASS(x86_exceptions,
--- a/arch/x86/include/asm/trace/irq_vectors.h
+++ b/arch/x86/include/asm/trace/irq_vectors.h
@@ -5,9 +5,7 @@
#define _TRACE_IRQ_VECTORS_H
#include <linux/tracepoint.h>
-
-extern int trace_irq_vector_regfunc(void);
-extern void trace_irq_vector_unregfunc(void);
+#include <asm/trace/common.h>
DECLARE_EVENT_CLASS(x86_irq_vector,
--- a/arch/x86/kernel/tracepoint.c
+++ b/arch/x86/kernel/tracepoint.c
@@ -4,9 +4,11 @@
* Copyright (C) 2013 Seiji Aguchi <seiji.aguchi@hds.com>
*
*/
+#include <linux/jump_label.h>
+#include <linux/atomic.h>
+
#include <asm/hw_irq.h>
#include <asm/desc.h>
-#include <linux/atomic.h>
atomic_t trace_idt_ctr = ATOMIC_INIT(0);
struct desc_ptr trace_idt_descr = { NR_VECTORS * 16 - 1,
@@ -15,6 +17,7 @@ struct desc_ptr trace_idt_descr = { NR_V
/* No need to be aligned, but done to keep all IDTs defined the same way. */
gate_desc trace_idt_table[NR_VECTORS] __page_aligned_bss;
+DEFINE_STATIC_KEY_FALSE(trace_irqvectors_key);
static int trace_irq_vector_refcount;
static DEFINE_MUTEX(irq_vector_mutex);
@@ -36,6 +39,8 @@ static void switch_idt(void *arg)
int trace_irq_vector_regfunc(void)
{
+ static_branch_inc(&trace_irqvectors_key);
+
mutex_lock(&irq_vector_mutex);
if (!trace_irq_vector_refcount) {
set_trace_idt_ctr(1);
@@ -49,6 +54,8 @@ int trace_irq_vector_regfunc(void)
void trace_irq_vector_unregfunc(void)
{
+ static_branch_dec(&trace_irqvectors_key);
+
mutex_lock(&irq_vector_mutex);
trace_irq_vector_refcount--;
if (!trace_irq_vector_refcount) {
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 18/44] x86/tracing: Disentangle pagefault and resched IPI tracing key |
| Message-ID | <uiuXE-1gP-19@gated-at.bofh.it> |
| In reply to | #1720440 |
The pagefault and the resched IPI handler are the only ones where it is
worth to optimize the code further in case tracepoints are disabled. But it
makes no sense to have a single static key for both.
Seperate the static keys so the facilities are handled seperately.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/trace/common.h | 15 ++++++++-------
arch/x86/include/asm/trace/exceptions.h | 6 ++++--
arch/x86/include/asm/trace/irq_vectors.h | 29 +++++++++++++++++++++++------
arch/x86/kernel/smp.c | 2 +-
arch/x86/kernel/tracepoint.c | 27 ++++++++++++++++++++++-----
arch/x86/mm/fault.c | 2 +-
6 files changed, 59 insertions(+), 22 deletions(-)
--- a/arch/x86/include/asm/trace/common.h
+++ b/arch/x86/include/asm/trace/common.h
@@ -1,15 +1,16 @@
#ifndef _ASM_TRACE_COMMON_H
#define _ASM_TRACE_COMMON_H
-extern int trace_irq_vector_regfunc(void);
-extern void trace_irq_vector_unregfunc(void);
-
#ifdef CONFIG_TRACING
-DECLARE_STATIC_KEY_FALSE(trace_irqvectors_key);
-#define trace_irqvectors_enabled() \
- static_branch_unlikely(&trace_irqvectors_key)
+DECLARE_STATIC_KEY_FALSE(trace_pagefault_key);
+#define trace_pagefault_enabled() \
+ static_branch_unlikely(&trace_pagefault_key)
+DECLARE_STATIC_KEY_FALSE(trace_resched_ipi_key);
+#define trace_resched_ipi_enabled() \
+ static_branch_unlikely(&trace_resched_ipi_key)
#else
-static inline bool trace_irqvectors_enabled(void) { return false; }
+static inline bool trace_pagefault_enabled(void) { return false; }
+static inline bool trace_resched_ipi_enabled(void) { return false; }
#endif
#endif
--- a/arch/x86/include/asm/trace/exceptions.h
+++ b/arch/x86/include/asm/trace/exceptions.h
@@ -7,6 +7,9 @@
#include <linux/tracepoint.h>
#include <asm/trace/common.h>
+extern int trace_pagefault_reg(void);
+extern void trace_pagefault_unreg(void);
+
DECLARE_EVENT_CLASS(x86_exceptions,
TP_PROTO(unsigned long address, struct pt_regs *regs,
@@ -35,8 +38,7 @@ DEFINE_EVENT_FN(x86_exceptions, name,
TP_PROTO(unsigned long address, struct pt_regs *regs, \
unsigned long error_code), \
TP_ARGS(address, regs, error_code), \
- trace_irq_vector_regfunc, \
- trace_irq_vector_unregfunc);
+ trace_pagefault_reg, trace_pagefault_unreg);
DEFINE_PAGE_FAULT_EVENT(page_fault_user);
DEFINE_PAGE_FAULT_EVENT(page_fault_kernel);
--- a/arch/x86/include/asm/trace/irq_vectors.h
+++ b/arch/x86/include/asm/trace/irq_vectors.h
@@ -7,6 +7,9 @@
#include <linux/tracepoint.h>
#include <asm/trace/common.h>
+extern int trace_resched_ipi_reg(void);
+extern void trace_resched_ipi_unreg(void);
+
DECLARE_EVENT_CLASS(x86_irq_vector,
TP_PROTO(int vector),
@@ -26,15 +29,22 @@ DECLARE_EVENT_CLASS(x86_irq_vector,
#define DEFINE_IRQ_VECTOR_EVENT(name) \
DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \
TP_PROTO(int vector), \
+ TP_ARGS(vector), NULL, NULL); \
+DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \
+ TP_PROTO(int vector), \
+ TP_ARGS(vector), NULL, NULL);
+
+#define DEFINE_RESCHED_IPI_EVENT(name) \
+DEFINE_EVENT_FN(x86_irq_vector, name##_entry, \
+ TP_PROTO(int vector), \
TP_ARGS(vector), \
- trace_irq_vector_regfunc, \
- trace_irq_vector_unregfunc); \
+ trace_resched_ipi_reg, \
+ trace_resched_ipi_unreg); \
DEFINE_EVENT_FN(x86_irq_vector, name##_exit, \
TP_PROTO(int vector), \
TP_ARGS(vector), \
- trace_irq_vector_regfunc, \
- trace_irq_vector_unregfunc);
-
+ trace_resched_ipi_reg, \
+ trace_resched_ipi_unreg);
/*
* local_timer - called when entering/exiting a local timer interrupt
@@ -43,9 +53,16 @@ DEFINE_EVENT_FN(x86_irq_vector, name##_e
DEFINE_IRQ_VECTOR_EVENT(local_timer);
/*
+ * The ifdef is required because that tracepoint macro hell emits tracepoint
+ * code in files which include this header even if the tracepoint is not
+ * enabled. Brilliant stuff that.
+ */
+#ifdef CONFIG_SMP
+/*
* reschedule - called when entering/exiting a reschedule vector handler
*/
-DEFINE_IRQ_VECTOR_EVENT(reschedule);
+DEFINE_RESCHED_IPI_EVENT(reschedule);
+#endif
/*
* spurious_apic - called when entering/exiting a spurious apic vector handler
--- a/arch/x86/kernel/smp.c
+++ b/arch/x86/kernel/smp.c
@@ -262,7 +262,7 @@ static void native_stop_other_cpus(int w
ack_APIC_irq();
inc_irq_stat(irq_resched_count);
- if (trace_irqvectors_enabled()) {
+ if (trace_resched_ipi_enabled()) {
/*
* scheduler_ipi() might call irq_enter() as well, but
* nested calls are fine.
--- a/arch/x86/kernel/tracepoint.c
+++ b/arch/x86/kernel/tracepoint.c
@@ -10,15 +10,32 @@
#include <asm/hw_irq.h>
#include <asm/desc.h>
-DEFINE_STATIC_KEY_FALSE(trace_irqvectors_key);
+DEFINE_STATIC_KEY_FALSE(trace_pagefault_key);
-int trace_irq_vector_regfunc(void)
+int trace_pagefault_reg(void)
{
- static_branch_inc(&trace_irqvectors_key);
+ static_branch_inc(&trace_pagefault_key);
return 0;
}
-void trace_irq_vector_unregfunc(void)
+void trace_pagefault_unreg(void)
{
- static_branch_dec(&trace_irqvectors_key);
+ static_branch_dec(&trace_pagefault_key);
}
+
+#ifdef CONFIG_SMP
+
+DEFINE_STATIC_KEY_FALSE(trace_resched_ipi_key);
+
+int trace_resched_ipi_reg(void)
+{
+ static_branch_inc(&trace_resched_ipi_key);
+ return 0;
+}
+
+void trace_resched_ipi_unreg(void)
+{
+ static_branch_dec(&trace_resched_ipi_key);
+}
+
+#endif
--- a/arch/x86/mm/fault.c
+++ b/arch/x86/mm/fault.c
@@ -1510,7 +1510,7 @@ do_page_fault(struct pt_regs *regs, unsi
enum ctx_state prev_state;
prev_state = exception_enter();
- if (trace_irqvectors_enabled())
+ if (trace_pagefault_enabled())
trace_page_fault_entries(address, regs, error_code);
__do_page_fault(regs, error_code, address);
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 12/44] x86/irqwork: Get rid of duplicated tracing interrupt code |
| Message-ID | <uiuXE-1gP-21@gated-at.bofh.it> |
| In reply to | #1720440 |
Two NOP5 are a reasonable tradeoff to avoid duplicated code and the
requirement to switch the IDT.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/hw_irq.h | 2 +-
arch/x86/kernel/irq_work.c | 16 ++--------------
2 files changed, 3 insertions(+), 15 deletions(-)
--- a/arch/x86/include/asm/hw_irq.h
+++ b/arch/x86/include/asm/hw_irq.h
@@ -48,13 +48,13 @@ extern asmlinkage void call_function_sin
#ifdef CONFIG_TRACING
/* Interrupt handlers registered during init_IRQ */
-extern void trace_irq_work_interrupt(void);
extern void trace_thermal_interrupt(void);
extern void trace_reschedule_interrupt(void);
extern void trace_threshold_interrupt(void);
extern void trace_deferred_error_interrupt(void);
extern void trace_call_function_interrupt(void);
extern void trace_call_function_single_interrupt(void);
+#define trace_irq_work_interrupt irq_work_interrupt
#define trace_error_interrupt error_interrupt
#define trace_spurious_interrupt spurious_interrupt
#define trace_x86_platform_ipi x86_platform_ipi
--- a/arch/x86/kernel/irq_work.c
+++ b/arch/x86/kernel/irq_work.c
@@ -11,24 +11,12 @@
#include <asm/trace/irq_vectors.h>
#include <linux/interrupt.h>
-static inline void __smp_irq_work_interrupt(void)
-{
- inc_irq_stat(apic_irq_work_irqs);
- irq_work_run();
-}
-
__visible void __irq_entry smp_irq_work_interrupt(struct pt_regs *regs)
{
ipi_entering_ack_irq();
- __smp_irq_work_interrupt();
- exiting_irq();
-}
-
-__visible void __irq_entry smp_trace_irq_work_interrupt(struct pt_regs *regs)
-{
- ipi_entering_ack_irq();
trace_irq_work_entry(IRQ_WORK_VECTOR);
- __smp_irq_work_interrupt();
+ inc_irq_stat(apic_irq_work_irqs);
+ irq_work_run();
trace_irq_work_exit(IRQ_WORK_VECTOR);
exiting_irq();
}
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 20/44] x86/irq_work: Make it depend on APIC |
| Message-ID | <uiuXF-1gP-29@gated-at.bofh.it> |
| In reply to | #1720440 |
The irq work interrupt vector is only installed when CONFIG_X86_LOCAL_APIC is
enabled, but the interrupt handler is compiled in unconditionally.
Compile the cruft out when the APIC is disabled.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/include/asm/irq_work.h | 8 ++++++++
arch/x86/kernel/irq_work.c | 4 ++--
2 files changed, 10 insertions(+), 2 deletions(-)
--- a/arch/x86/include/asm/irq_work.h
+++ b/arch/x86/include/asm/irq_work.h
@@ -3,9 +3,17 @@
#include <asm/cpufeature.h>
+#ifdef CONFIG_X86_LOCAL_APIC
static inline bool arch_irq_work_has_interrupt(void)
{
return boot_cpu_has(X86_FEATURE_APIC);
}
+extern void arch_irq_work_raise(void);
+#else
+static inline bool arch_irq_work_has_interrupt(void)
+{
+ return false;
+}
+#endif
#endif /* _ASM_IRQ_WORK_H */
--- a/arch/x86/kernel/irq_work.c
+++ b/arch/x86/kernel/irq_work.c
@@ -11,6 +11,7 @@
#include <asm/trace/irq_vectors.h>
#include <linux/interrupt.h>
+#ifdef CONFIG_X86_LOCAL_APIC
__visible void __irq_entry smp_irq_work_interrupt(struct pt_regs *regs)
{
ipi_entering_ack_irq();
@@ -23,11 +24,10 @@
void arch_irq_work_raise(void)
{
-#ifdef CONFIG_X86_LOCAL_APIC
if (!arch_irq_work_has_interrupt())
return;
apic->send_IPI_self(IRQ_WORK_VECTOR);
apic_wait_icr_idle();
-#endif
}
+#endif
[toc] | [prev] | [next] | [standalone]
| From | Thomas Gleixner <tglx@linutronix.de> |
|---|---|
| Date | 2017-08-26 00:10 +0200 |
| Subject | [patch V2 09/44] x86/apic: Use this_cpu_ptr in local_timer_interrupt |
| Message-ID | <uiuXE-1gP-23@gated-at.bofh.it> |
| In reply to | #1720440 |
Accessing the per cpu data via per_cpu(, smp_processor_id()) is
pointless. Use this_cpu_ptr() instead.
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
arch/x86/kernel/apic/apic.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
--- a/arch/x86/kernel/apic/apic.c
+++ b/arch/x86/kernel/apic/apic.c
@@ -988,8 +988,7 @@ void setup_secondary_APIC_clock(void)
*/
static void local_apic_timer_interrupt(void)
{
- int cpu = smp_processor_id();
- struct clock_event_device *evt = &per_cpu(lapic_events, cpu);
+ struct clock_event_device *evt = this_cpu_ptr(&lapic_events);
/*
* Normally we should not be here till LAPIC has been initialized but
@@ -1003,7 +1002,8 @@ static void local_apic_timer_interrupt(v
* spurious.
*/
if (!evt->event_handler) {
- pr_warning("Spurious LAPIC timer interrupt on cpu %d\n", cpu);
+ pr_warning("Spurious LAPIC timer interrupt on cpu %d\n",
+ smp_processor_id());
/* Switch it off */
lapic_timer_shutdown(evt);
return;
[toc] | [prev] | [next] | [standalone]
Page 1 of 2 [1] 2 Next page →
Back to top | Article view | linux.kernel
csiph-web