diff options
Diffstat (limited to 'arch/i386/kernel/irq.h')
-rw-r--r-- | arch/i386/kernel/irq.h | 187 |
1 files changed, 18 insertions, 169 deletions
diff --git a/arch/i386/kernel/irq.h b/arch/i386/kernel/irq.h index 3a349f20a..1f9e89399 100644 --- a/arch/i386/kernel/irq.h +++ b/arch/i386/kernel/irq.h @@ -33,7 +33,6 @@ static inline void irq_enter(int cpu, int irq) static inline void irq_exit(int cpu, int irq) { - __cli(); hardirq_exit(cpu); release_irqlock(cpu); } @@ -63,125 +62,12 @@ static inline void irq_exit(int cpu, int irq) "mov %dx,%ds\n\t" \ "mov %dx,%es\n\t" -/* - * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers, - * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't - * call the routines that do signal handling etc on return, and can have - * more relaxed register-saving etc. They are also atomic, and are thus - * suited for small, fast interrupts like the serial lines or the harddisk - * drivers, which don't actually need signal handling etc. - * - * Also note that we actually save only those registers that are used in - * C subroutines (%eax, %edx and %ecx), so if you do something weird, - * you're on your own. The only segments that are saved (not counting the - * automatic stack and code segment handling) are %ds and %es, and they - * point to kernel space. No messing around with %fs here. - */ -#define SAVE_MOST \ - "cld\n\t" \ - "push %es\n\t" \ - "push %ds\n\t" \ - "pushl %eax\n\t" \ - "pushl %edx\n\t" \ - "pushl %ecx\n\t" \ - "movl $" STR(KERNEL_DS) ",%edx\n\t" \ - "mov %dx,%ds\n\t" \ - "mov %dx,%es\n\t" - -#define RESTORE_MOST \ - "popl %ecx\n\t" \ - "popl %edx\n\t" \ - "popl %eax\n\t" \ - "pop %ds\n\t" \ - "pop %es\n\t" \ - "iret" - -/* - * Some fast irq handlers might want to access saved registers (mostly - * cs or flags) - */ - -struct fast_irq_regs { - long ecx; - long edx; - long eax; - int xds; - int xes; - long eip; - int xcs; - long eflags; - long esp; - int xss; -}; - -/* - * The "inb" instructions are not needed, but seem to change the timings - * a bit - without them it seems that the harddisk driver won't work on - * all hardware. Arghh. - */ -#define ACK_FIRST(mask,nr) \ - "inb $0x21,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ - "outb %al,$0x21\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ - "outb %al,$0x20\n\t" - -#define ACK_SECOND(mask,nr) \ - "inb $0xA1,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ - "outb %al,$0xA1\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tmovb $0x20,%al\n\t" \ - "outb %al,$0xA0\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\toutb %al,$0x20\n\t" - -#define UNBLK_FIRST(mask) \ - "inb $0x21,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ - "outb %al,$0x21\n\t" - -#define UNBLK_SECOND(mask) \ - "inb $0xA1,%al\n\t" \ - "jmp 1f\n" \ - "1:\tjmp 1f\n" \ - "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \ - "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ - "outb %al,$0xA1\n\t" - #define IRQ_NAME2(nr) nr##_interrupt(void) #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) -#define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) -#define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) - -#ifdef __SMP__ - -#define GET_CURRENT \ - "movl "SYMBOL_NAME_STR(apic_reg)", %ebx\n\t" \ - "movl 32(%ebx), %ebx\n\t" \ - "shrl $22,%ebx\n\t" \ - "andl $0x3C,%ebx\n\t" \ - "movl " SYMBOL_NAME_STR(current_set) "(,%ebx),%ebx\n\t" - -#else #define GET_CURRENT \ - "movl " SYMBOL_NAME_STR(current_set) ",%ebx\n\t" - -#endif + "movl %esp, %ebx\n\t" \ + "andl $-8192, %ebx\n\t" #ifdef __SMP__ @@ -205,66 +91,30 @@ __asm__( \ "\n"__ALIGN_STR"\n" \ SYMBOL_NAME_STR(x) ":\n\t" \ "pushl $-1\n\t" \ - SAVE_ALL \ - "movl %esp,%eax\n\t" \ - "pushl %eax\n\t" \ + SAVE_ALL \ + "movl %esp,%eax\n\t" \ + "pushl %eax\n\t" \ "call "SYMBOL_NAME_STR(smp_##x)"\n\t" \ - "addl $4,%esp\n\t" \ + "addl $4,%esp\n\t" \ "jmp ret_from_intr\n"); #endif /* __SMP__ */ -#define BUILD_IRQ(chip,nr,mask) \ -asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ +#define BUILD_COMMON_IRQ() \ __asm__( \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ + "\n" __ALIGN_STR"\n" \ + "common_interrupt:\n\t" \ SAVE_ALL \ - ACK_##chip(mask,(nr&7)) \ - "movl %esp,%eax\n\t" \ - "pushl %eax\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - UNBLK_##chip(mask) \ - "jmp ret_from_intr\n" \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask,(nr&7)) \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ - "addl $4,%esp\n\t" \ - UNBLK_##chip(mask) \ - RESTORE_MOST \ -"\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ - SAVE_MOST \ - ACK_##chip(mask,(nr&7)) \ - RESTORE_MOST); - -#define BUILD_TIMER_IRQ(chip,nr,mask) \ + "pushl $ret_from_intr\n\t" \ + "jmp "SYMBOL_NAME_STR(do_IRQ)); + +#define BUILD_IRQ(chip,nr,mask) \ asmlinkage void IRQ_NAME(nr); \ -asmlinkage void FAST_IRQ_NAME(nr); \ -asmlinkage void BAD_IRQ_NAME(nr); \ __asm__( \ "\n"__ALIGN_STR"\n" \ -SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ -SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ - "pushl $-"#nr"-2\n\t" \ - SAVE_ALL \ - ACK_##chip(mask,(nr&7)) \ - "movl %esp,%eax\n\t" \ - "pushl %eax\n\t" \ - "pushl $" #nr "\n\t" \ - "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ - "addl $8,%esp\n\t" \ - UNBLK_##chip(mask) \ - "jmp ret_from_intr\n"); + "pushl $"#nr"-256\n\t" \ + "jmp common_interrupt"); /* * x86 profiling function, SMP safe. We might want to do this in @@ -276,15 +126,14 @@ static inline void x86_do_profile (unsigned long eip) extern int _stext; eip -= (unsigned long) &_stext; eip >>= prof_shift; - if (eip < prof_len) - atomic_inc((atomic_t *)&prof_buffer[eip]); - else /* * Dont ignore out-of-bounds EIP values silently, * put them into the last histogram slot, so if * present, they will show up as a sharp peak. */ - atomic_inc((atomic_t *)&prof_buffer[prof_len-1]); + if (eip > prof_len-1) + eip = prof_len-1; + atomic_inc((atomic_t *)&prof_buffer[eip]); } } |