|
|
1.1 ! root 1: #ifndef _ASM_IRQ_H ! 2: #define _ASM_IRQ_H ! 3: ! 4: /* ! 5: * linux/include/asm/irq.h ! 6: * ! 7: * (C) 1992, 1993 Linus Torvalds ! 8: * ! 9: * IRQ/IPI changes taken from work by Thomas Radke <[email protected]> ! 10: */ ! 11: ! 12: #include <linux/linkage.h> ! 13: #include <asm/segment.h> ! 14: ! 15: #define NR_IRQS 16 ! 16: ! 17: #define TIMER_IRQ 0 ! 18: ! 19: extern void disable_irq(unsigned int); ! 20: extern void enable_irq(unsigned int); ! 21: ! 22: #define __STR(x) #x ! 23: #define STR(x) __STR(x) ! 24: ! 25: #define SAVE_ALL \ ! 26: "cld\n\t" \ ! 27: "push %gs\n\t" \ ! 28: "push %fs\n\t" \ ! 29: "push %es\n\t" \ ! 30: "push %ds\n\t" \ ! 31: "pushl %eax\n\t" \ ! 32: "pushl %ebp\n\t" \ ! 33: "pushl %edi\n\t" \ ! 34: "pushl %esi\n\t" \ ! 35: "pushl %edx\n\t" \ ! 36: "pushl %ecx\n\t" \ ! 37: "pushl %ebx\n\t" \ ! 38: "movl $" STR(KERNEL_DS) ",%edx\n\t" \ ! 39: "mov %dx,%ds\n\t" \ ! 40: "mov %dx,%es\n\t" \ ! 41: "movl $" STR(USER_DS) ",%edx\n\t" \ ! 42: "mov %dx,%fs\n\t" \ ! 43: "movl $0,%edx\n\t" \ ! 44: "movl %edx,%db7\n\t" ! 45: ! 46: /* ! 47: * SAVE_MOST/RESTORE_MOST is used for the faster version of IRQ handlers, ! 48: * installed by using the SA_INTERRUPT flag. These kinds of IRQ's don't ! 49: * call the routines that do signal handling etc on return, and can have ! 50: * more relaxed register-saving etc. They are also atomic, and are thus ! 51: * suited for small, fast interrupts like the serial lines or the harddisk ! 52: * drivers, which don't actually need signal handling etc. ! 53: * ! 54: * Also note that we actually save only those registers that are used in ! 55: * C subroutines (%eax, %edx and %ecx), so if you do something weird, ! 56: * you're on your own. The only segments that are saved (not counting the ! 57: * automatic stack and code segment handling) are %ds and %es, and they ! 58: * point to kernel space. No messing around with %fs here. ! 59: */ ! 60: #define SAVE_MOST \ ! 61: "cld\n\t" \ ! 62: "push %es\n\t" \ ! 63: "push %ds\n\t" \ ! 64: "pushl %eax\n\t" \ ! 65: "pushl %edx\n\t" \ ! 66: "pushl %ecx\n\t" \ ! 67: "movl $" STR(KERNEL_DS) ",%edx\n\t" \ ! 68: "mov %dx,%ds\n\t" \ ! 69: "mov %dx,%es\n\t" ! 70: ! 71: #define RESTORE_MOST \ ! 72: "popl %ecx\n\t" \ ! 73: "popl %edx\n\t" \ ! 74: "popl %eax\n\t" \ ! 75: "pop %ds\n\t" \ ! 76: "pop %es\n\t" \ ! 77: "iret" ! 78: ! 79: /* ! 80: * The "inb" instructions are not needed, but seem to change the timings ! 81: * a bit - without them it seems that the harddisk driver won't work on ! 82: * all hardware. Arghh. ! 83: */ ! 84: #define ACK_FIRST(mask,nr) \ ! 85: "inb $0x21,%al\n\t" \ ! 86: "jmp 1f\n" \ ! 87: "1:\tjmp 1f\n" \ ! 88: "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_21)"\n\t" \ ! 89: "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ ! 90: "outb %al,$0x21\n\t" \ ! 91: "jmp 1f\n" \ ! 92: "1:\tjmp 1f\n" \ ! 93: "1:\tmovb $0x20,%al\n\t" \ ! 94: "outb %al,$0x20\n\t" ! 95: ! 96: #define ACK_SECOND(mask,nr) \ ! 97: "inb $0xA1,%al\n\t" \ ! 98: "jmp 1f\n" \ ! 99: "1:\tjmp 1f\n" \ ! 100: "1:\torb $" #mask ","SYMBOL_NAME_STR(cache_A1)"\n\t" \ ! 101: "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ ! 102: "outb %al,$0xA1\n\t" \ ! 103: "jmp 1f\n" \ ! 104: "1:\tjmp 1f\n" \ ! 105: "1:\tmovb $0x20,%al\n\t" \ ! 106: "outb %al,$0xA0\n\t" \ ! 107: "jmp 1f\n" \ ! 108: "1:\tjmp 1f\n" \ ! 109: "1:\toutb %al,$0x20\n\t" ! 110: ! 111: /* do not modify the ISR nor the cache_A1 variable */ ! 112: #define MSGACK_SECOND(mask,nr) \ ! 113: "inb $0xA1,%al\n\t" \ ! 114: "jmp 1f\n" \ ! 115: "1:\tjmp 1f\n" \ ! 116: "1:\tmovb $0x20,%al\n\t" \ ! 117: "outb %al,$0xA0\n\t" \ ! 118: "jmp 1f\n" \ ! 119: "1:\tjmp 1f\n" \ ! 120: "1:\toutb %al,$0x20\n\t" ! 121: ! 122: #define UNBLK_FIRST(mask) \ ! 123: "inb $0x21,%al\n\t" \ ! 124: "jmp 1f\n" \ ! 125: "1:\tjmp 1f\n" \ ! 126: "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_21)"\n\t" \ ! 127: "movb "SYMBOL_NAME_STR(cache_21)",%al\n\t" \ ! 128: "outb %al,$0x21\n\t" ! 129: ! 130: #define UNBLK_SECOND(mask) \ ! 131: "inb $0xA1,%al\n\t" \ ! 132: "jmp 1f\n" \ ! 133: "1:\tjmp 1f\n" \ ! 134: "1:\tandb $~(" #mask "),"SYMBOL_NAME_STR(cache_A1)"\n\t" \ ! 135: "movb "SYMBOL_NAME_STR(cache_A1)",%al\n\t" \ ! 136: "outb %al,$0xA1\n\t" ! 137: ! 138: #define IRQ_NAME2(nr) nr##_interrupt(void) ! 139: #define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) ! 140: #define FAST_IRQ_NAME(nr) IRQ_NAME2(fast_IRQ##nr) ! 141: #define BAD_IRQ_NAME(nr) IRQ_NAME2(bad_IRQ##nr) ! 142: ! 143: #ifdef __SMP__ ! 144: ! 145: #ifndef __SMP_PROF__ ! 146: #define SMP_PROF_INT_SPINS ! 147: #define SMP_PROF_IPI_CNT ! 148: #else ! 149: #define SMP_PROF_INT_SPINS "incl "SYMBOL_NAME_STR(smp_spins)"(,%eax,4)\n\t" ! 150: #define SMP_PROF_IPI_CNT "incl "SYMBOL_NAME_STR(ipi_count)"\n\t" ! 151: #endif ! 152: ! 153: #define GET_PROCESSOR_ID \ ! 154: "movl "SYMBOL_NAME_STR(apic_reg)", %edx\n\t" \ ! 155: "movl 32(%edx), %eax\n\t" \ ! 156: "shrl $24,%eax\n\t" \ ! 157: "andl $0x0F,%eax\n" ! 158: ! 159: #define ENTER_KERNEL \ ! 160: "pushl %eax\n\t" \ ! 161: "pushl %ebx\n\t" \ ! 162: "pushl %ecx\n\t" \ ! 163: "pushl %edx\n\t" \ ! 164: "pushfl\n\t" \ ! 165: "cli\n\t" \ ! 166: "movl $6000, %ebx\n\t" \ ! 167: "movl "SYMBOL_NAME_STR(smp_loops_per_tick)", %ecx\n\t" \ ! 168: GET_PROCESSOR_ID \ ! 169: "btsl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \ ! 170: "1: " \ ! 171: "lock\n\t" \ ! 172: "btsl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ ! 173: "jnc 3f\n\t" \ ! 174: "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \ ! 175: "je 4f\n\t" \ ! 176: "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \ ! 177: "jne 2f\n\t" \ ! 178: "movb $1, "SYMBOL_NAME_STR(smp_blocked_interrupt_pending)"\n\t" \ ! 179: "2: " \ ! 180: SMP_PROF_INT_SPINS \ ! 181: "btl %eax, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \ ! 182: "jnc 5f\n\t" \ ! 183: "lock\n\t" \ ! 184: "btrl %eax, "SYMBOL_NAME_STR(smp_invalidate_needed)"\n\t" \ ! 185: "jnc 5f\n\t" \ ! 186: "movl %cr3,%edx\n\t" \ ! 187: "movl %edx,%cr3\n" \ ! 188: "5: btl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ ! 189: "jnc 1b\n\t" \ ! 190: "cmpb "SYMBOL_NAME_STR(active_kernel_processor)", %al\n\t" \ ! 191: "je 4f\n\t" \ ! 192: "decl %ecx\n\t" \ ! 193: "jne 2b\n\t" \ ! 194: "decl %ebx\n\t" \ ! 195: "jne 6f\n\t" \ ! 196: "call "SYMBOL_NAME_STR(irq_deadlock_detected)"\n\t" \ ! 197: "6: movl "SYMBOL_NAME_STR(smp_loops_per_tick)", %ecx\n\t" \ ! 198: "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \ ! 199: "jne 2b\n\t" \ ! 200: "incl "SYMBOL_NAME_STR(jiffies)"\n\t" \ ! 201: "jmp 2b\n\t" \ ! 202: "3: " \ ! 203: "movb %al, "SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \ ! 204: "4: " \ ! 205: "incl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \ ! 206: "cmpb "SYMBOL_NAME_STR(boot_cpu_id)", %al\n\t" \ ! 207: "jne 7f\n\t" \ ! 208: "movb $0, "SYMBOL_NAME_STR(smp_blocked_interrupt_pending)"\n\t" \ ! 209: "7: " \ ! 210: "popfl\n\t" \ ! 211: "popl %edx\n\t" \ ! 212: "popl %ecx\n\t" \ ! 213: "popl %ebx\n\t" \ ! 214: "popl %eax\n\t" ! 215: ! 216: #define LEAVE_KERNEL \ ! 217: GET_PROCESSOR_ID \ ! 218: "btrl $" STR(SMP_FROM_INT) ","SYMBOL_NAME_STR(smp_proc_in_lock)"(,%eax,4)\n\t" \ ! 219: "pushfl\n\t" \ ! 220: "cli\n\t" \ ! 221: "decl "SYMBOL_NAME_STR(kernel_counter)"\n\t" \ ! 222: "jnz 1f\n\t" \ ! 223: "movb "SYMBOL_NAME_STR(saved_active_kernel_processor)",%al\n\t" \ ! 224: "movb %al,"SYMBOL_NAME_STR(active_kernel_processor)"\n\t" \ ! 225: "cmpb $" STR (NO_PROC_ID) ",%al\n\t" \ ! 226: "jne 1f\n\t" \ ! 227: "lock\n\t" \ ! 228: "btrl $0, "SYMBOL_NAME_STR(kernel_flag)"\n\t" \ ! 229: "1: " \ ! 230: "popfl\n\t" ! 231: ! 232: ! 233: /* ! 234: * the syscall count inc is a gross hack because ret_from_syscall is used by both irq and ! 235: * syscall return paths (urghh). ! 236: */ ! 237: ! 238: #define BUILD_IRQ(chip,nr,mask) \ ! 239: asmlinkage void IRQ_NAME(nr); \ ! 240: asmlinkage void FAST_IRQ_NAME(nr); \ ! 241: asmlinkage void BAD_IRQ_NAME(nr); \ ! 242: __asm__( \ ! 243: "\n"__ALIGN_STR"\n" \ ! 244: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 245: "pushl $-"#nr"-2\n\t" \ ! 246: SAVE_ALL \ ! 247: ENTER_KERNEL \ ! 248: ACK_##chip(mask,(nr&7)) \ ! 249: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 250: "sti\n\t" \ ! 251: "movl %esp,%ebx\n\t" \ ! 252: "pushl %ebx\n\t" \ ! 253: "pushl $" #nr "\n\t" \ ! 254: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 255: "addl $8,%esp\n\t" \ ! 256: "cli\n\t" \ ! 257: UNBLK_##chip(mask) \ ! 258: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 259: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ ! 260: "jmp ret_from_sys_call\n" \ ! 261: "\n"__ALIGN_STR"\n" \ ! 262: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 263: SAVE_MOST \ ! 264: ENTER_KERNEL \ ! 265: ACK_##chip(mask,(nr&7)) \ ! 266: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 267: "pushl $" #nr "\n\t" \ ! 268: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ ! 269: "addl $4,%esp\n\t" \ ! 270: "cli\n\t" \ ! 271: UNBLK_##chip(mask) \ ! 272: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 273: LEAVE_KERNEL \ ! 274: RESTORE_MOST \ ! 275: "\n"__ALIGN_STR"\n" \ ! 276: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 277: SAVE_MOST \ ! 278: ENTER_KERNEL \ ! 279: ACK_##chip(mask,(nr&7)) \ ! 280: LEAVE_KERNEL \ ! 281: RESTORE_MOST); ! 282: ! 283: ! 284: #define BUILD_TIMER_IRQ(chip,nr,mask) \ ! 285: asmlinkage void IRQ_NAME(nr); \ ! 286: asmlinkage void FAST_IRQ_NAME(nr); \ ! 287: asmlinkage void BAD_IRQ_NAME(nr); \ ! 288: __asm__( \ ! 289: "\n"__ALIGN_STR"\n" \ ! 290: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 291: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 292: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 293: "pushl $-"#nr"-2\n\t" \ ! 294: SAVE_ALL \ ! 295: ENTER_KERNEL \ ! 296: ACK_##chip(mask,(nr&7)) \ ! 297: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 298: "movl %esp,%ebx\n\t" \ ! 299: "pushl %ebx\n\t" \ ! 300: "pushl $" #nr "\n\t" \ ! 301: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 302: "addl $8,%esp\n\t" \ ! 303: "cli\n\t" \ ! 304: UNBLK_##chip(mask) \ ! 305: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 306: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ ! 307: "jmp ret_from_sys_call\n"); ! 308: ! 309: ! 310: /* ! 311: * Message pass must be a fast IRQ.. ! 312: */ ! 313: ! 314: #define BUILD_MSGIRQ(chip,nr,mask) \ ! 315: asmlinkage void IRQ_NAME(nr); \ ! 316: asmlinkage void FAST_IRQ_NAME(nr); \ ! 317: asmlinkage void BAD_IRQ_NAME(nr); \ ! 318: __asm__( \ ! 319: "\n"__ALIGN_STR"\n" \ ! 320: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 321: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 322: SAVE_MOST \ ! 323: MSGACK_##chip(mask,(nr&7)) \ ! 324: SMP_PROF_IPI_CNT \ ! 325: "pushl $" #nr "\n\t" \ ! 326: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ ! 327: "addl $4,%esp\n\t" \ ! 328: "cli\n\t" \ ! 329: RESTORE_MOST \ ! 330: "\n"__ALIGN_STR"\n" \ ! 331: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 332: SAVE_MOST \ ! 333: ACK_##chip(mask,(nr&7)) \ ! 334: RESTORE_MOST); ! 335: ! 336: #define BUILD_RESCHEDIRQ(nr) \ ! 337: asmlinkage void IRQ_NAME(nr); \ ! 338: __asm__( \ ! 339: "\n"__ALIGN_STR"\n" \ ! 340: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 341: "pushl $-"#nr"-2\n\t" \ ! 342: SAVE_ALL \ ! 343: ENTER_KERNEL \ ! 344: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 345: "sti\n\t" \ ! 346: "movl %esp,%ebx\n\t" \ ! 347: "pushl %ebx\n\t" \ ! 348: "pushl $" #nr "\n\t" \ ! 349: "call "SYMBOL_NAME_STR(smp_reschedule_irq)"\n\t" \ ! 350: "addl $8,%esp\n\t" \ ! 351: "cli\n\t" \ ! 352: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 353: "incl "SYMBOL_NAME_STR(syscall_count)"\n\t" \ ! 354: "jmp ret_from_sys_call\n"); ! 355: #else ! 356: ! 357: #define BUILD_IRQ(chip,nr,mask) \ ! 358: asmlinkage void IRQ_NAME(nr); \ ! 359: asmlinkage void FAST_IRQ_NAME(nr); \ ! 360: asmlinkage void BAD_IRQ_NAME(nr); \ ! 361: __asm__( \ ! 362: "\n"__ALIGN_STR"\n" \ ! 363: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 364: "pushl $-"#nr"-2\n\t" \ ! 365: SAVE_ALL \ ! 366: ACK_##chip(mask,(nr&7)) \ ! 367: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 368: "sti\n\t" \ ! 369: "movl %esp,%ebx\n\t" \ ! 370: "pushl %ebx\n\t" \ ! 371: "pushl $" #nr "\n\t" \ ! 372: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 373: "addl $8,%esp\n\t" \ ! 374: "cli\n\t" \ ! 375: UNBLK_##chip(mask) \ ! 376: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 377: "jmp ret_from_sys_call\n" \ ! 378: "\n"__ALIGN_STR"\n" \ ! 379: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 380: SAVE_MOST \ ! 381: ACK_##chip(mask,(nr&7)) \ ! 382: "incl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 383: "pushl $" #nr "\n\t" \ ! 384: "call "SYMBOL_NAME_STR(do_fast_IRQ)"\n\t" \ ! 385: "addl $4,%esp\n\t" \ ! 386: "cli\n\t" \ ! 387: UNBLK_##chip(mask) \ ! 388: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 389: RESTORE_MOST \ ! 390: "\n"__ALIGN_STR"\n" \ ! 391: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 392: SAVE_MOST \ ! 393: ACK_##chip(mask,(nr&7)) \ ! 394: RESTORE_MOST); ! 395: ! 396: #define BUILD_TIMER_IRQ(chip,nr,mask) \ ! 397: asmlinkage void IRQ_NAME(nr); \ ! 398: asmlinkage void FAST_IRQ_NAME(nr); \ ! 399: asmlinkage void BAD_IRQ_NAME(nr); \ ! 400: __asm__( \ ! 401: "\n"__ALIGN_STR"\n" \ ! 402: SYMBOL_NAME_STR(fast_IRQ) #nr "_interrupt:\n\t" \ ! 403: SYMBOL_NAME_STR(bad_IRQ) #nr "_interrupt:\n\t" \ ! 404: SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ ! 405: "pushl $-"#nr"-2\n\t" \ ! 406: SAVE_ALL \ ! 407: ACK_##chip(mask,(nr&7)) \ ! 408: "incl "SYMBOL_NAME_STR(intr_count)"\n\t"\ ! 409: "movl %esp,%ebx\n\t" \ ! 410: "pushl %ebx\n\t" \ ! 411: "pushl $" #nr "\n\t" \ ! 412: "call "SYMBOL_NAME_STR(do_IRQ)"\n\t" \ ! 413: "addl $8,%esp\n\t" \ ! 414: "cli\n\t" \ ! 415: UNBLK_##chip(mask) \ ! 416: "decl "SYMBOL_NAME_STR(intr_count)"\n\t" \ ! 417: "jmp ret_from_sys_call\n"); ! 418: ! 419: #endif ! 420: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.