diff options
author | H. Peter Anvin <hpa@zytor.com> | 2008-11-11 16:24:58 -0500 |
---|---|---|
committer | H. Peter Anvin <hpa@zytor.com> | 2008-11-11 16:24:58 -0500 |
commit | b7c6244f13d37592003b46e12500a90e9781ad9d (patch) | |
tree | 24b19efe784a1a9975610228ddfa98cee47dac06 /arch/x86/kernel/entry_32.S | |
parent | 4687518c4cb7807fbeff21770e309080f9eb7f2f (diff) |
x86: 32 bits: shrink and align IRQ stubs
Shrink the IRQ stubs on 32 bits down to just over four bytes per (we
fit seven into a 32-byte chunk.) This shrinks the total icache
consumption of the IRQ stubs down to an even kilobyte, if all of them
are in active use.
The downside is that we end up with a double jump, which could have a
negative effect on some pipelines. The double jump is always inside
the same cacheline on any modern chips (the exception being
486/Elan/Geode which have only 16-byte cachelines, but are unlikely to
have too many interrupt sources.)
To get the most effect, cache-align the IRQ stubs.
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
Diffstat (limited to 'arch/x86/kernel/entry_32.S')
-rw-r--r-- | arch/x86/kernel/entry_32.S | 34 |
1 files changed, 22 insertions, 12 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 4aea95652cff..dae81b9fd451 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -619,28 +619,37 @@ END(syscall_badsys) | |||
619 | 27:; | 619 | 27:; |
620 | 620 | ||
621 | /* | 621 | /* |
622 | * Build the entry stubs and pointer table with | 622 | * Build the entry stubs and pointer table with some assembler magic. |
623 | * some assembler magic. | 623 | * We pack 7 stubs into a single 32-byte chunk, which will fit in a |
624 | * single cache line on all modern x86 implementations. | ||
624 | */ | 625 | */ |
625 | .section .init.rodata,"a" | 626 | .section .init.rodata,"a" |
626 | ENTRY(interrupt) | 627 | ENTRY(interrupt) |
627 | .text | 628 | .text |
628 | 629 | .p2align 5 | |
630 | .p2align CONFIG_X86_L1_CACHE_SHIFT | ||
629 | ENTRY(irq_entries_start) | 631 | ENTRY(irq_entries_start) |
630 | RING0_INT_FRAME | 632 | RING0_INT_FRAME |
631 | vector=FIRST_EXTERNAL_VECTOR | 633 | vector=FIRST_EXTERNAL_VECTOR |
632 | .rept NR_VECTORS | 634 | .rept (NR_VECTORS-FIRST_EXTERNAL_VECTOR+6)/7 |
633 | ALIGN | 635 | .balign 32 |
634 | .if vector != FIRST_EXTERNAL_VECTOR | 636 | .rept 7 |
637 | .if vector < NR_VECTORS | ||
638 | .if vector != FIRST_EXTERNAL_VECTOR | ||
635 | CFI_ADJUST_CFA_OFFSET -4 | 639 | CFI_ADJUST_CFA_OFFSET -4 |
636 | .endif | 640 | .endif |
637 | 1: pushl $~(vector) | 641 | 1: pushl $(~vector+0x80) /* Note: always in signed byte range */ |
638 | CFI_ADJUST_CFA_OFFSET 4 | 642 | CFI_ADJUST_CFA_OFFSET 4 |
639 | jmp common_interrupt | 643 | .if ((vector-FIRST_EXTERNAL_VECTOR)%7) != 6 |
640 | .previous | 644 | jmp 2f |
645 | .endif | ||
646 | .previous | ||
641 | .long 1b | 647 | .long 1b |
642 | .text | 648 | .text |
643 | vector=vector+1 | 649 | vector=vector+1 |
650 | .endif | ||
651 | .endr | ||
652 | 2: jmp common_interrupt | ||
644 | .endr | 653 | .endr |
645 | END(irq_entries_start) | 654 | END(irq_entries_start) |
646 | 655 | ||
@@ -652,8 +661,9 @@ END(interrupt) | |||
652 | * the CPU automatically disables interrupts when executing an IRQ vector, | 661 | * the CPU automatically disables interrupts when executing an IRQ vector, |
653 | * so IRQ-flags tracing has to follow that: | 662 | * so IRQ-flags tracing has to follow that: |
654 | */ | 663 | */ |
655 | ALIGN | 664 | .p2align CONFIG_X86_L1_CACHE_SHIFT |
656 | common_interrupt: | 665 | common_interrupt: |
666 | addl $-0x80,(%esp) /* Adjust vector into the [-256,-1] range */ | ||
657 | SAVE_ALL | 667 | SAVE_ALL |
658 | TRACE_IRQS_OFF | 668 | TRACE_IRQS_OFF |
659 | movl %esp,%eax | 669 | movl %esp,%eax |