This commit was manufactured by cvs2svn to create branch 'vserver'.
[linux-2.6.git] / arch / i386 / kernel / apic-xen.c
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  */
16
17 #include <linux/config.h>
18 #include <linux/init.h>
19
20 #include <linux/mm.h>
21 #include <linux/delay.h>
22 #include <linux/bootmem.h>
23 #include <linux/smp_lock.h>
24 #include <linux/interrupt.h>
25 #include <linux/mc146818rtc.h>
26 #include <linux/kernel_stat.h>
27 #include <linux/sysdev.h>
28 #include <linux/cpu.h>
29 #include <linux/module.h>
30
31 #include <asm/atomic.h>
32 #include <asm/smp.h>
33 #include <asm/mtrr.h>
34 #include <asm/mpspec.h>
35 #include <asm/desc.h>
36 #include <asm/arch_hooks.h>
37 #include <asm/hpet.h>
38 #include <asm/i8253.h>
39
40 #include <mach_apic.h>
41 #include <mach_apicdef.h>
42 #include <mach_ipi.h>
43
44 #include "io_ports.h"
45
46 #ifndef CONFIG_XEN
47 /*
48  * cpu_mask that denotes the CPUs that needs timer interrupt coming in as
49  * IPIs in place of local APIC timers
50  */
51 static cpumask_t timer_bcast_ipi;
52 #endif
53
54 /*
55  * Knob to control our willingness to enable the local APIC.
56  */
57 int enable_local_apic __initdata = 0; /* -1=force-disable, +1=force-enable */
58
59 /*
60  * Debug level
61  */
62 int apic_verbosity;
63
64 int modern_apic(void)
65 {
66 #ifndef CONFIG_XEN
67         unsigned int lvr, version;
68         /* AMD systems use old APIC versions, so check the CPU */
69         if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
70                 boot_cpu_data.x86 >= 0xf)
71                 return 1;
72         lvr = apic_read(APIC_LVR);
73         version = GET_APIC_VERSION(lvr);
74         return version >= 0x14;
75 #else
76         return 1;
77 #endif
78 }
79
80 /*
81  * 'what should we do if we get a hw irq event on an illegal vector'.
82  * each architecture has to answer this themselves.
83  */
84 void ack_bad_irq(unsigned int irq)
85 {
86         printk("unexpected IRQ trap at vector %02x\n", irq);
87         /*
88          * Currently unexpected vectors happen only on SMP and APIC.
89          * We _must_ ack these because every local APIC has only N
90          * irq slots per priority level, and a 'hanging, unacked' IRQ
91          * holds up an irq slot - in excessive cases (when multiple
92          * unexpected vectors occur) that might lock up the APIC
93          * completely.
94          * But only ack when the APIC is enabled -AK
95          */
96         if (cpu_has_apic)
97                 ack_APIC_irq();
98 }
99
100 int get_physical_broadcast(void)
101 {
102         if (modern_apic())
103                 return 0xff;
104         else
105                 return 0xf;
106 }
107
108 #ifndef CONFIG_XEN
109 #ifndef CONFIG_SMP
110 static void up_apic_timer_interrupt_call(struct pt_regs *regs)
111 {
112         int cpu = smp_processor_id();
113
114         /*
115          * the NMI deadlock-detector uses this.
116          */
117         per_cpu(irq_stat, cpu).apic_timer_irqs++;
118
119         smp_local_timer_interrupt(regs);
120 }
121 #endif
122
123 void smp_send_timer_broadcast_ipi(struct pt_regs *regs)
124 {
125         cpumask_t mask;
126
127         cpus_and(mask, cpu_online_map, timer_bcast_ipi);
128         if (!cpus_empty(mask)) {
129 #ifdef CONFIG_SMP
130                 send_IPI_mask(mask, LOCAL_TIMER_VECTOR);
131 #else
132                 /*
133                  * We can directly call the apic timer interrupt handler
134                  * in UP case. Minus all irq related functions
135                  */
136                 up_apic_timer_interrupt_call(regs);
137 #endif
138         }
139 }
140 #endif
141
142 int setup_profiling_timer(unsigned int multiplier)
143 {
144         return -EINVAL;
145 }
146
147 /*
148  * This initializes the IO-APIC and APIC hardware if this is
149  * a UP kernel.
150  */
151 int __init APIC_init_uniprocessor (void)
152 {
153 #ifdef CONFIG_X86_IO_APIC
154         if (smp_found_config)
155                 if (!skip_ioapic_setup && nr_ioapics)
156                         setup_IO_APIC();
157 #endif
158
159         return 0;
160 }