ia64/xen-unstable

view linux-2.6-xen-sparse/arch/x86_64/kernel/apic-xen.c @ 13647:057c4c2991fa

32-on-64: Fix an one-off error in compat_addr_ok().
Signed-off-by: Jan Beulich <jbeulich@novell.com>
author kaf24@localhost.localdomain
date Fri Jan 26 13:36:52 2007 +0000 (2007-01-26)
parents 3adf00179a63
children
line source
1 /*
2 * Local APIC handling, local APIC timers
3 *
4 * (c) 1999, 2000 Ingo Molnar <mingo@redhat.com>
5 *
6 * Fixes
7 * Maciej W. Rozycki : Bits for genuine 82489DX APICs;
8 * thanks to Eric Gilmore
9 * and Rolf G. Tews
10 * for testing these extensively.
11 * Maciej W. Rozycki : Various updates and fixes.
12 * Mikael Pettersson : Power Management for UP-APIC.
13 * Pavel Machek and
14 * Mikael Pettersson : PM converted to driver model.
15 */
17 #include <linux/init.h>
19 #include <linux/mm.h>
20 #include <linux/delay.h>
21 #include <linux/bootmem.h>
22 #include <linux/smp_lock.h>
23 #include <linux/interrupt.h>
24 #include <linux/mc146818rtc.h>
25 #include <linux/kernel_stat.h>
26 #include <linux/sysdev.h>
27 #include <linux/module.h>
29 #include <asm/atomic.h>
30 #include <asm/smp.h>
31 #include <asm/mtrr.h>
32 #include <asm/mpspec.h>
33 #include <asm/desc.h>
34 #include <asm/arch_hooks.h>
35 #include <asm/hpet.h>
36 #include <asm/idle.h>
38 int apic_verbosity;
40 /*
41 * 'what should we do if we get a hw irq event on an illegal vector'.
42 * each architecture has to answer this themselves.
43 */
44 void ack_bad_irq(unsigned int irq)
45 {
46 printk("unexpected IRQ trap at vector %02x\n", irq);
47 /*
48 * Currently unexpected vectors happen only on SMP and APIC.
49 * We _must_ ack these because every local APIC has only N
50 * irq slots per priority level, and a 'hanging, unacked' IRQ
51 * holds up an irq slot - in excessive cases (when multiple
52 * unexpected vectors occur) that might lock up the APIC
53 * completely.
54 * But don't ack when the APIC is disabled. -AK
55 */
56 if (!disable_apic)
57 ack_APIC_irq();
58 }
60 int setup_profiling_timer(unsigned int multiplier)
61 {
62 return -EINVAL;
63 }
65 void smp_local_timer_interrupt(struct pt_regs *regs)
66 {
67 profile_tick(CPU_PROFILING, regs);
68 #ifndef CONFIG_XEN
69 #ifdef CONFIG_SMP
70 update_process_times(user_mode(regs));
71 #endif
72 #endif
73 /*
74 * We take the 'long' return path, and there every subsystem
75 * grabs the appropriate locks (kernel lock/ irq lock).
76 *
77 * we might want to decouple profiling from the 'long path',
78 * and do the profiling totally in assembly.
79 *
80 * Currently this isn't too much of an issue (performance wise),
81 * we can take more than 100K local irqs per second on a 100 MHz P5.
82 */
83 }
85 /*
86 * Local APIC timer interrupt. This is the most natural way for doing
87 * local interrupts, but local timer interrupts can be emulated by
88 * broadcast interrupts too. [in case the hw doesn't support APIC timers]
89 *
90 * [ if a single-CPU system runs an SMP kernel then we call the local
91 * interrupt as well. Thus we cannot inline the local irq ... ]
92 */
93 void smp_apic_timer_interrupt(struct pt_regs *regs)
94 {
95 /*
96 * the NMI deadlock-detector uses this.
97 */
98 add_pda(apic_timer_irqs, 1);
100 /*
101 * NOTE! We'd better ACK the irq immediately,
102 * because timer handling can be slow.
103 */
104 ack_APIC_irq();
105 /*
106 * update_process_times() expects us to have done irq_enter().
107 * Besides, if we don't timer interrupts ignore the global
108 * interrupt lock, which is the WrongThing (tm) to do.
109 */
110 exit_idle();
111 irq_enter();
112 smp_local_timer_interrupt(regs);
113 irq_exit();
114 }
116 /*
117 * This interrupt should _never_ happen with our APIC/SMP architecture
118 */
119 asmlinkage void smp_spurious_interrupt(void)
120 {
121 unsigned int v;
122 exit_idle();
123 irq_enter();
124 /*
125 * Check if this really is a spurious interrupt and ACK it
126 * if it is a vectored one. Just in case...
127 * Spurious interrupts should not be ACKed.
128 */
129 v = apic_read(APIC_ISR + ((SPURIOUS_APIC_VECTOR & ~0x1f) >> 1));
130 if (v & (1 << (SPURIOUS_APIC_VECTOR & 0x1f)))
131 ack_APIC_irq();
133 #if 0
134 static unsigned long last_warning;
135 static unsigned long skipped;
137 /* see sw-dev-man vol 3, chapter 7.4.13.5 */
138 if (time_before(last_warning+30*HZ,jiffies)) {
139 printk(KERN_INFO "spurious APIC interrupt on CPU#%d, %ld skipped.\n",
140 smp_processor_id(), skipped);
141 last_warning = jiffies;
142 skipped = 0;
143 } else {
144 skipped++;
145 }
146 #endif
147 irq_exit();
148 }
150 /*
151 * This interrupt should never happen with our APIC/SMP architecture
152 */
154 asmlinkage void smp_error_interrupt(void)
155 {
156 unsigned int v, v1;
158 exit_idle();
159 irq_enter();
160 /* First tickle the hardware, only then report what went on. -- REW */
161 v = apic_read(APIC_ESR);
162 apic_write(APIC_ESR, 0);
163 v1 = apic_read(APIC_ESR);
164 ack_APIC_irq();
165 atomic_inc(&irq_err_count);
167 /* Here is what the APIC error bits mean:
168 0: Send CS error
169 1: Receive CS error
170 2: Send accept error
171 3: Receive accept error
172 4: Reserved
173 5: Send illegal vector
174 6: Received illegal vector
175 7: Illegal register address
176 */
177 printk (KERN_DEBUG "APIC error on CPU%d: %02x(%02x)\n",
178 smp_processor_id(), v , v1);
179 irq_exit();
180 }
182 int disable_apic;
184 /*
185 * This initializes the IO-APIC and APIC hardware if this is
186 * a UP kernel.
187 */
188 int __init APIC_init_uniprocessor (void)
189 {
190 #ifdef CONFIG_X86_IO_APIC
191 if (smp_found_config)
192 if (!skip_ioapic_setup && nr_ioapics)
193 setup_IO_APIC();
194 #endif
196 return 1;
197 }