3 * \brief APIC for AMD64
6 * (c) 2008-2009 Technische Universität Dresden
7 * This file is part of TUD:OS and distributed under the terms of the
8 * GNU Lesser General Public License 2.1.
9 * Please see the COPYING-LGPL-2.1 file for details.
11 #ifndef __L4_UTIL_APIC_H
12 #define __L4_UTIL_APIC_H
15 * Local APIC programming library
17 * For documentation, see
19 * "Intel Architecture Software Developer's Manual", Volume 3, chapter 7.5:
20 * "Advanced Programmable Interrupt Controller (APIC)"
22 * Local APIC is present since
24 * - AMD K7 (Athlon), Model 2
26 * In non-SMP-boards, local APIC is disabled, but
27 * can be activated by writing to a MSR register.
28 * For using APIC see packets cpufreq and l4rtl.
30 * See linux/include/asm-i386/i82489.h for further details.
33 #define APIC_PHYS_BASE 0xFEE00000
34 #define APIC_MAP_BASE 0xA0200000
35 #define APIC_BASE_MSR 0x1b
38 #define GET_APIC_ID(x) (((x)>>24)&0x0F)
40 #define GET_APIC_VERSION(x) ((x)&0xFF)
41 #define APIC_TASKPRI 0x80
42 #define APIC_TPRI_MASK 0xFF
45 #define APIC_LDR_MASK (0xFF<<24)
47 #define SET_APIC_DFR(x) ((x)<<28)
48 #define APIC_SPIV 0xF0
49 #define APIC_LVTT 0x320
50 #define APIC_LVTPC 0x340
51 #define APIC_LVT0 0x350
52 #define SET_APIC_TIMER_BASE(x) (((x)<<18))
53 #define APIC_TIMER_BASE_DIV 0x2
54 #define APIC_LVT1 0x360
55 #define APIC_LVTERR 0x370
56 #define APIC_TMICT 0x380
57 #define APIC_TMCCT 0x390
58 #define APIC_TDCR 0x3E0
60 #define APIC_LVT_MASKED (1<<16)
61 #define APIC_LVT_TIMER_PERIODIC (1<<17)
62 #define APIC_TDR_DIV_1 0xB
63 #define APIC_TDR_DIV_2 0x0
64 #define APIC_TDR_DIV_4 0x1
65 #define APIC_TDR_DIV_8 0x2
66 #define APIC_TDR_DIV_16 0x3
67 #define APIC_TDR_DIV_32 0x8
68 #define APIC_TDR_DIV_64 0x9
69 #define APIC_TDR_DIV_128 0xA
71 #include <l4/sys/compiler.h>
72 #include <l4/sys/types.h>
77 extern unsigned long apic_map_base;
78 extern unsigned long apic_timer_divisor;
80 extern unsigned long l4_scaler_apic_to_ms;
82 L4_CV void apic_show_registers(void);
83 L4_CV int apic_check_working(void);
84 L4_CV void apic_activate_by_io(void);
85 L4_CV void apic_timer_set_divisor(int divisor);
87 L4_CV unsigned long l4_calibrate_apic(void);
91 L4_INLINE void apic_write(unsigned long reg, unsigned long v);
92 L4_INLINE unsigned long apic_read(unsigned long reg);
93 L4_INLINE void apic_activate_by_msr(void);
94 L4_INLINE void apic_deactivate_by_msr(void);
95 L4_INLINE unsigned long apic_read_phys_address(void);
96 L4_INLINE int apic_test_present(void);
97 L4_INLINE void apic_soft_enable(void);
98 L4_INLINE void apic_init(unsigned long map_addr);
99 L4_INLINE void apic_done(void);
100 L4_INLINE void apic_irq_ack(void);
102 L4_INLINE void apic_lvt0_disable_irq(void);
103 L4_INLINE void apic_lvt0_enable_irq(void);
104 L4_INLINE void apic_lvt1_disable_irq(void);
105 L4_INLINE void apic_lvt1_enable_irq(void);
107 L4_INLINE void apic_timer_write(unsigned long value);
108 L4_INLINE unsigned long apic_timer_read(void);
109 L4_INLINE void apic_timer_disable_irq(void);
110 L4_INLINE void apic_timer_enable_irq(void);
111 L4_INLINE void apic_timer_assign_irq(unsigned long vector);
112 L4_INLINE void apic_timer_set_periodic(void);
113 L4_INLINE void apic_timer_set_one_shot(void);
115 L4_INLINE void apic_perf_disable_irq(void);
116 L4_INLINE void apic_perf_enable_irq(void);
117 L4_INLINE void apic_perf_assign_irq(unsigned long vector);
120 /* write APIC register */
122 apic_write(unsigned long reg, unsigned long v)
124 *((volatile unsigned long *)(apic_map_base+reg))=v;
128 /* read APIC register */
129 L4_INLINE unsigned long
130 apic_read(unsigned long reg)
132 return *((volatile unsigned long *)(apic_map_base+reg));
138 apic_lvt0_disable_irq(void)
140 unsigned long tmp_val;
141 tmp_val = apic_read(APIC_LVT0);
142 tmp_val |= APIC_LVT_MASKED;
143 apic_write(APIC_LVT0, tmp_val);
149 apic_lvt0_enable_irq(void)
151 unsigned long tmp_val;
152 tmp_val = apic_read(APIC_LVT0);
153 tmp_val &= ~(APIC_LVT_MASKED);
154 apic_write(APIC_LVT0, tmp_val);
160 apic_lvt1_disable_irq(void)
162 unsigned long tmp_val;
163 tmp_val = apic_read(APIC_LVT1);
164 tmp_val |= APIC_LVT_MASKED;
165 apic_write(APIC_LVT1, tmp_val);
171 apic_lvt1_enable_irq(void)
173 unsigned long tmp_val;
174 tmp_val = apic_read(APIC_LVT1);
175 tmp_val &= ~(APIC_LVT_MASKED);
176 apic_write(APIC_LVT1, tmp_val);
180 /* write APIC timer register */
182 apic_timer_write(unsigned long value)
184 apic_read(APIC_TMICT);
185 apic_write(APIC_TMICT,value);
189 /* read APIC timer register */
190 L4_INLINE unsigned long
191 apic_timer_read(void)
193 return apic_read(APIC_TMCCT);
197 /* disable IRQ when APIC timer passes 0 */
199 apic_timer_disable_irq(void)
201 unsigned long tmp_val;
202 tmp_val = apic_read(APIC_LVTT);
203 tmp_val |= APIC_LVT_MASKED;
204 apic_write(APIC_LVTT, tmp_val);
208 /* enable IRQ when APIC timer passes 0 */
210 apic_timer_enable_irq(void)
212 unsigned long tmp_val;
213 tmp_val = apic_read(APIC_LVTT);
214 tmp_val &= ~(APIC_LVT_MASKED);
215 apic_write(APIC_LVTT, tmp_val);
220 apic_timer_set_periodic(void)
222 unsigned long tmp_val;
223 tmp_val = apic_read(APIC_LVTT);
224 tmp_val |= APIC_LVT_TIMER_PERIODIC;
225 tmp_val |= APIC_LVT_MASKED;
226 apic_write(APIC_LVTT, tmp_val);
231 apic_timer_set_one_shot(void)
233 unsigned long tmp_val;
234 tmp_val = apic_read(APIC_LVTT);
235 tmp_val &= ~APIC_LVT_TIMER_PERIODIC;
236 tmp_val |= APIC_LVT_MASKED;
237 apic_write(APIC_LVTT, tmp_val);
241 /* set vector of APIC timer irq */
243 apic_timer_assign_irq(unsigned long vector)
245 unsigned long tmp_val;
246 tmp_val = apic_read(APIC_LVTT);
247 tmp_val &= 0xffffff00;
249 tmp_val |= APIC_LVT_MASKED;
250 apic_write(APIC_LVTT, tmp_val);
254 /* disable IRQ when performance counter passes 0 */
256 apic_perf_disable_irq(void)
258 unsigned long tmp_val;
259 tmp_val = apic_read(APIC_LVTPC);
260 tmp_val |= APIC_LVT_MASKED;
261 apic_write(APIC_LVTPC, tmp_val);
265 /* enable IRQ when performance counter passes 0 */
267 apic_perf_enable_irq(void)
269 unsigned long tmp_val;
270 tmp_val = apic_read(APIC_LVTPC);
271 tmp_val &= ~(APIC_LVT_MASKED);
272 apic_write(APIC_LVTPC, tmp_val);
276 /* set vector of performance counter irq */
278 apic_perf_assign_irq(unsigned long vector)
280 unsigned long tmp_val;
281 tmp_val = apic_read(APIC_LVTPC);
282 tmp_val &= 0xffffff00;
284 tmp_val |= APIC_LVT_MASKED;
285 apic_write(APIC_LVTPC, tmp_val);
289 /* activate APIC by writing to appropriate MSR */
291 apic_activate_by_msr(void)
297 asm volatile(".byte 0xf; .byte 0x32\n"
303 low |= 0x800; /* activate APIC */
305 low |= (APIC_PHYS_BASE & 0xfffff000); /* set address */
308 asm volatile(".byte 0xf; .byte 0x30\n"
310 :"c" (APIC_BASE_MSR),
317 /* deactivate APIC by writing to appropriate MSR */
319 apic_deactivate_by_msr(void)
325 asm volatile(".byte 0xf; .byte 0x32\n"
331 low &= 0xfffff7ff; /* deactivate APIC */
334 asm volatile(".byte 0xf; .byte 0x30\n"
336 :"c" (APIC_BASE_MSR),
343 /* read memory mapped address of apic */
344 L4_INLINE unsigned long
345 apic_read_phys_address(void)
351 asm volatile(".byte 0xf; .byte 0x32\n"
357 return (low &= 0xfffff000);
361 /* test if APIC present */
363 apic_test_present(void)
366 unsigned int capability;
368 asm volatile("pushl %%ebx ; cpuid ; popl %%ebx"
375 return ((capability & 1<<9) !=0);
380 apic_soft_enable(void)
382 unsigned long tmp_val;
383 tmp_val = apic_read(APIC_SPIV);
384 tmp_val |= (1<<8); /* enable APIC */
385 tmp_val &= ~(1<<9); /* enable Focus Processor Checking */
386 tmp_val |= 0xff; /* Set spurious IRQ vector to 0xff */
387 apic_write(APIC_SPIV, tmp_val);
392 apic_init(unsigned long base_addr)
394 apic_map_base = base_addr;
408 apic_read(APIC_SPIV);
409 apic_write(APIC_EOI, 0);
413 #endif /* __L4_UTIL_APIC_H */