1#ifndef _ASM_HW_IRQ_H 2#define _ASM_HW_IRQ_H 3 4/* 5 * linux/include/asm/hw_irq.h 6 * 7 * (C) 1992, 1993 Linus Torvalds, (C) 1997 Ingo Molnar 8 * 9 * moved some of the old arch/i386/kernel/irq.h to here. VY 10 * 11 * IRQ/IPI changes taken from work by Thomas Radke 12 * <tomsoft@informatik.tu-chemnitz.de> 13 * 14 * hacked by Andi Kleen for x86-64. 15 * 16 * $Id: hw_irq.h,v 1.1.1.1 2008/10/15 03:29:18 james26_jang Exp $ 17 */ 18 19#include <linux/config.h> 20#include <asm/atomic.h> 21#include <asm/irq.h> 22 23/* 24 * IDT vectors usable for external interrupt sources start 25 * at 0x20: 26 */ 27#define FIRST_EXTERNAL_VECTOR 0x20 28 29#define IA32_SYSCALL_VECTOR 0x80 30#define KDBENTER_VECTOR 0x81 31 32 33/* 34 * Vectors 0x20-0x2f are used for ISA interrupts. 35 */ 36 37/* 38 * Special IRQ vectors used by the SMP architecture, 0xf0-0xff 39 * 40 * some of the following vectors are 'rare', they are merged 41 * into a single vector (CALL_FUNCTION_VECTOR) to save vector space. 42 * TLB, reschedule and local APIC vectors are performance-critical. 43 * 44 * Vectors 0xf0-0xf9 are free (reserved for future Linux use). 45 */ 46#define SPURIOUS_APIC_VECTOR 0xff 47#define ERROR_APIC_VECTOR 0xfe 48#define INVALIDATE_TLB_VECTOR 0xfd 49#define RESCHEDULE_VECTOR 0xfc 50#define KDB_VECTOR 0xfa 51#define CALL_FUNCTION_VECTOR 0xfb 52#define KDB_VECTOR 0xfa 53 54/* 55 * Local APIC timer IRQ vector is on a different priority level, 56 * to work around the 'lost local interrupt if more than 2 IRQ 57 * sources per level' errata. 58 */ 59#define LOCAL_TIMER_VECTOR 0xef 60 61/* 62 * First APIC vector available to drivers: (vectors 0x30-0xee) 63 * we start at 0x31 to spread out vectors evenly between priority 64 * levels. (0x80 is the syscall vector) 65 */ 66#define FIRST_DEVICE_VECTOR 0x31 67#define FIRST_SYSTEM_VECTOR 0xef 68 69extern int irq_vector[NR_IRQS]; 70#define IO_APIC_VECTOR(irq) irq_vector[irq] 71 72/* 73 * Various low-level irq details needed by irq.c, process.c, 74 * time.c, io_apic.c and smp.c 75 * 76 * Interrupt entry/exit code at both C and assembly level 77 */ 78 79extern void mask_irq(unsigned int irq); 80extern void unmask_irq(unsigned int irq); 81extern void disable_8259A_irq(unsigned int irq); 82extern void enable_8259A_irq(unsigned int irq); 83extern int i8259A_irq_pending(unsigned int irq); 84extern void make_8259A_irq(unsigned int irq); 85extern void init_8259A(int aeoi); 86extern void FASTCALL(send_IPI_self(int vector)); 87extern void init_VISWS_APIC_irqs(void); 88extern void setup_IO_APIC(void); 89extern void disable_IO_APIC(void); 90extern void print_IO_APIC(void); 91extern int IO_APIC_get_PCI_irq_vector(int bus, int slot, int fn); 92extern void send_IPI(int dest, int vector); 93 94extern unsigned long io_apic_irqs; 95 96extern atomic_t irq_err_count; 97extern atomic_t irq_mis_count; 98 99extern char _stext, _etext; 100 101#define IO_APIC_IRQ(x) (((x) >= 16) || ((1<<(x)) & io_apic_irqs)) 102 103#define __STR(x) #x 104#define STR(x) __STR(x) 105 106#include <asm/ptrace.h> 107#ifndef ASM_OFFSET_H 108#include <asm/offset.h> 109#endif 110 111/* IF:off, stack contains irq number on origrax */ 112#define IRQ_ENTER \ 113" cld ;" \ 114" pushq %rdi ;" \ 115" pushq %rsi ;" \ 116" pushq %rdx ;" \ 117" pushq %rcx ;" \ 118" pushq %rax ;" \ 119" pushq %r8 ;" \ 120" pushq %r9 ;" \ 121" pushq %r10 ;" \ 122" pushq %r11 ;" \ 123" leaq -48(%rsp),%rdi ;" \ 124" testl $3,136(%rdi) ;" \ 125" je 1f ;" \ 126" swapgs ;" \ 127"1: addl $1,%gs: " STR(pda_irqcount) ";" \ 128" movq %gs: " STR(pda_irqstackptr) ",%rax ;" \ 129" cmoveq %rax,%rsp ;" \ 130" pushq %rdi ;" 131 132#define IRQ_NAME2(nr) nr##_interrupt(void) 133#define IRQ_NAME(nr) IRQ_NAME2(IRQ##nr) 134 135/* 136 * SMP has a few special interrupts for IPI messages 137 */ 138 139 /* there is a second layer of macro just to get the symbolic 140 name for the vector evaluated. This change is for RTLinux */ 141#define BUILD_SMP_INTERRUPT(x,v) XBUILD_SMP_INTERRUPT(x,v) 142#define XBUILD_SMP_INTERRUPT(x,v)\ 143asmlinkage void x(void); \ 144asmlinkage void call_##x(void); \ 145__asm__( \ 146"\n"__ALIGN_STR"\n" \ 147SYMBOL_NAME_STR(x) ":\n\t" \ 148 "push $" #v "-256;" \ 149 IRQ_ENTER \ 150 "call " SYMBOL_NAME_STR(smp_##x) " ; " \ 151 "jmp ret_from_intr") 152 153#define BUILD_COMMON_IRQ() 154 155#define BUILD_IRQ(nr) \ 156asmlinkage void IRQ_NAME(nr); \ 157__asm__( \ 158"\n"__ALIGN_STR "\n" \ 159SYMBOL_NAME_STR(IRQ) #nr "_interrupt:\n\t" \ 160 "push $" #nr "-256 ; " \ 161 "jmp common_interrupt"); 162 163extern unsigned long prof_cpu_mask; 164extern unsigned int * prof_buffer; 165extern unsigned long prof_len; 166extern unsigned long prof_shift; 167 168/* 169 * x86 profiling function, SMP safe. We might want to do this in 170 * assembly totally? 171 */ 172static inline void x86_do_profile (unsigned long eip) 173{ 174 if (!prof_buffer) 175 return; 176 177 /* 178 * Only measure the CPUs specified by /proc/irq/prof_cpu_mask. 179 * (default is all CPUs.) 180 */ 181 if (!((1<<smp_processor_id()) & prof_cpu_mask)) 182 return; 183 184 eip -= (unsigned long) &_stext; 185 eip >>= prof_shift; 186 /* 187 * Don't ignore out-of-bounds EIP values silently, 188 * put them into the last histogram slot, so if 189 * present, they will show up as a sharp peak. 190 */ 191 if (eip > prof_len-1) 192 eip = prof_len-1; 193 atomic_inc((atomic_t *)&prof_buffer[eip]); 194} 195 196#ifdef CONFIG_SMP /*more of this file should probably be ifdefed SMP */ 197static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) { 198 if (IO_APIC_IRQ(i)) 199 send_IPI_self(IO_APIC_VECTOR(i)); 200} 201#else 202static inline void hw_resend_irq(struct hw_interrupt_type *h, unsigned int i) {} 203#endif 204 205#endif /* _ASM_HW_IRQ_H */ 206