Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

x86: Avoid building unused IRQ entry stubs

When X86_LOCAL_APIC (i.e. unconditionally on x86-64),
first_system_vector will never end up being higher than
LOCAL_TIMER_VECTOR (0xef), and hence building stubs for vectors
0xef...0xff is pointlessly reducing code density. Deal with this at
build time already.

Taking into consideration that X86_64 implies X86_LOCAL_APIC, also
simplify (and hence make easier to read and more consistent with the
change done here) some #if-s in arch/x86/kernel/irqinit.c.

While we could further improve the packing of the IRQ entry stubs (the
four ones now left in the last set could be fit into the four padding
bytes each of the final four sets have) this doesn't seem to provide
any real benefit: Both irq_entries_start and common_interrupt getting
cache line aligned, eliminating the 30th set would just produce 32
bytes of padding between the 29th and common_interrupt.

[ tglx: Folded lguest fix from Dan Carpenter ]

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Andi Kleen <ak@linux.intel.com>
Cc: lguest@lists.ozlabs.org
Cc: Rusty Russell <rusty@rustcorp.com.au>
Link: http://lkml.kernel.org/r/54574D5F0200007800044389@mail.emea.novell.com
Link: http://lkml.kernel.org/r/20141115185718.GB6530@mwanda
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>

authored by

Jan Beulich and committed by
Thomas Gleixner
2414e021 e1067982

+34 -20
+2 -1
arch/x86/include/asm/hw_irq.h
··· 189 189 extern __visible void smp_invalidate_interrupt(struct pt_regs *); 190 190 #endif 191 191 192 - extern void (*__initconst interrupt[NR_VECTORS-FIRST_EXTERNAL_VECTOR])(void); 192 + extern void (*__initconst interrupt[FIRST_SYSTEM_VECTOR 193 + - FIRST_EXTERNAL_VECTOR])(void); 193 194 #ifdef CONFIG_TRACING 194 195 #define trace_interrupt interrupt 195 196 #endif
+6
arch/x86/include/asm/irq_vectors.h
··· 126 126 127 127 #define NR_VECTORS 256 128 128 129 + #ifdef CONFIG_X86_LOCAL_APIC 130 + #define FIRST_SYSTEM_VECTOR LOCAL_TIMER_VECTOR 131 + #else 132 + #define FIRST_SYSTEM_VECTOR NR_VECTORS 133 + #endif 134 + 129 135 #define FPU_IRQ 13 130 136 131 137 #define FIRST_VM86_IRQ 3
+12 -10
arch/x86/kernel/apic/apic.c
··· 196 196 int local_apic_timer_c2_ok; 197 197 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok); 198 198 199 - int first_system_vector = 0xfe; 199 + int first_system_vector = FIRST_SYSTEM_VECTOR; 200 200 201 201 /* 202 202 * Debug level, exported for io_apic.c ··· 1930 1930 /* 1931 1931 * This interrupt should _never_ happen with our APIC/SMP architecture 1932 1932 */ 1933 - static inline void __smp_spurious_interrupt(void) 1933 + static inline void __smp_spurious_interrupt(u8 vector) 1934 1934 { 1935 1935 u32 v; 1936 1936 ··· 1939 1939 * if it is a vectored one. Just in case... 1940 1940 * Spurious interrupts should not be ACKed. 1941 1941 */ 1942 - v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1)); 1943 - if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f))) 1942 + v = apic_read(APIC_ISR + ((vector & ~0x1f) >> 1)); 1943 + if (v & (1 << (vector & 0x1f))) 1944 1944 ack_APIC_irq(); 1945 1945 1946 1946 inc_irq_stat(irq_spurious_count); 1947 1947 1948 1948 /* see sw-dev-man vol 3, chapter 7.4.13.5 */ 1949 - pr_info("spurious APIC interrupt on CPU#%d, " 1950 - "should never happen.\n", smp_processor_id()); 1949 + pr_info("spurious APIC interrupt through vector %02x on CPU#%d, " 1950 + "should never happen.\n", vector, smp_processor_id()); 1951 1951 } 1952 1952 1953 1953 __visible void smp_spurious_interrupt(struct pt_regs *regs) 1954 1954 { 1955 1955 entering_irq(); 1956 - __smp_spurious_interrupt(); 1956 + __smp_spurious_interrupt(~regs->orig_ax); 1957 1957 exiting_irq(); 1958 1958 } 1959 1959 1960 1960 __visible void smp_trace_spurious_interrupt(struct pt_regs *regs) 1961 1961 { 1962 + u8 vector = ~regs->orig_ax; 1963 + 1962 1964 entering_irq(); 1963 - trace_spurious_apic_entry(SPURIOUS_APIC_VECTOR); 1964 - __smp_spurious_interrupt(); 1965 - trace_spurious_apic_exit(SPURIOUS_APIC_VECTOR); 1965 + trace_spurious_apic_entry(vector); 1966 + __smp_spurious_interrupt(vector); 1967 + trace_spurious_apic_exit(vector); 1966 1968 exiting_irq(); 1967 1969 } 1968 1970
+2 -2
arch/x86/kernel/entry_32.S
··· 732 732 ENTRY(irq_entries_start) 733 733 RING0_INT_FRAME 734 734 vector=FIRST_EXTERNAL_VECTOR 735 - .rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7 735 + .rept (FIRST_SYSTEM_VECTOR-FIRST_EXTERNAL_VECTOR+6)/7 736 736 .balign 32 737 737 .rept 7 738 - .if vector < NR_VECTORS 738 + .if vector < FIRST_SYSTEM_VECTOR 739 739 .if vector <> FIRST_EXTERNAL_VECTOR 740 740 CFI_ADJUST_CFA_OFFSET -4 741 741 .endif
+2 -2
arch/x86/kernel/entry_64.S
··· 712 712 ENTRY(irq_entries_start) 713 713 INTR_FRAME 714 714 vector=FIRST_EXTERNAL_VECTOR 715 - .rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7 715 + .rept (FIRST_SYSTEM_VECTOR-FIRST_EXTERNAL_VECTOR+6)/7 716 716 .balign 32 717 717 .rept 7 718 - .if vector < NR_VECTORS 718 + .if vector < FIRST_SYSTEM_VECTOR 719 719 .if vector <> FIRST_EXTERNAL_VECTOR 720 720 CFI_ADJUST_CFA_OFFSET -8 721 721 .endif
+9 -4
arch/x86/kernel/irqinit.c
··· 124 124 static void __init smp_intr_init(void) 125 125 { 126 126 #ifdef CONFIG_SMP 127 - #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) 128 127 /* 129 128 * The reschedule interrupt is a CPU-to-CPU reschedule-helper 130 129 * IPI, driven by wakeup. ··· 143 144 144 145 /* IPI used for rebooting/stopping */ 145 146 alloc_intr_gate(REBOOT_VECTOR, reboot_interrupt); 146 - #endif 147 147 #endif /* CONFIG_SMP */ 148 148 } 149 149 ··· 157 159 alloc_intr_gate(THRESHOLD_APIC_VECTOR, threshold_interrupt); 158 160 #endif 159 161 160 - #if defined(CONFIG_X86_64) || defined(CONFIG_X86_LOCAL_APIC) 162 + #ifdef CONFIG_X86_LOCAL_APIC 161 163 /* self generated IPI for local APIC timer */ 162 164 alloc_intr_gate(LOCAL_TIMER_VECTOR, apic_timer_interrupt); 163 165 ··· 195 197 * 'special' SMP interrupts) 196 198 */ 197 199 i = FIRST_EXTERNAL_VECTOR; 198 - for_each_clear_bit_from(i, used_vectors, NR_VECTORS) { 200 + #ifndef CONFIG_X86_LOCAL_APIC 201 + #define first_system_vector NR_VECTORS 202 + #endif 203 + for_each_clear_bit_from(i, used_vectors, first_system_vector) { 199 204 /* IA32_SYSCALL_VECTOR could be used in trap_init already. */ 200 205 set_intr_gate(i, interrupt[i - FIRST_EXTERNAL_VECTOR]); 201 206 } 207 + #ifdef CONFIG_X86_LOCAL_APIC 208 + for_each_clear_bit_from(i, used_vectors, NR_VECTORS) 209 + set_intr_gate(i, spurious_interrupt); 210 + #endif 202 211 203 212 if (!acpi_ioapic && !of_ioapic && nr_legacy_irqs()) 204 213 setup_irq(2, &irq2);
+1 -1
arch/x86/lguest/boot.c
··· 841 841 { 842 842 unsigned int i; 843 843 844 - for (i = FIRST_EXTERNAL_VECTOR; i < NR_VECTORS; i++) { 844 + for (i = FIRST_EXTERNAL_VECTOR; i < FIRST_SYSTEM_VECTOR; i++) { 845 845 /* Some systems map "vectors" to interrupts weirdly. Not us! */ 846 846 __this_cpu_write(vector_irq[i], i - FIRST_EXTERNAL_VECTOR); 847 847 if (i != SYSCALL_VECTOR)