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