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