]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/l4util/include/ARCH-amd64/apic.h
948d96b859dd13512687e59af5920a56f8ee329a
[l4.git] / l4 / pkg / l4util / include / ARCH-amd64 / apic.h
1 /**
2  * \file
3  * \brief APIC for AMD64
4  */
5 /*
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.
10  */
11 #ifndef __L4_UTIL_APIC_H
12 #define __L4_UTIL_APIC_H
13
14 /*
15  * Local APIC programming library
16  *
17  * For documentation, see
18  *
19  * "Intel Architecture Software Developer's Manual", Volume 3, chapter 7.5:
20  * "Advanced Programmable Interrupt Controller (APIC)"
21  *
22  * Local APIC is present since
23  * - INTEL P6 (PPro)
24  * - AMD K7 (Athlon), Model 2
25  *
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.
29  *
30  * See linux/include/asm-i386/i82489.h for further details.
31  */
32
33 #define APIC_PHYS_BASE              0xFEE00000
34 #define APIC_MAP_BASE               0xA0200000
35 #define APIC_BASE_MSR               0x1b
36
37 #define APIC_ID                     0x20
38 #define   GET_APIC_ID(x)              (((x)>>24)&0x0F)
39 #define APIC_LVR                    0x30
40 #define   GET_APIC_VERSION(x)         ((x)&0xFF)
41 #define APIC_TASKPRI                0x80
42 #define   APIC_TPRI_MASK              0xFF
43 #define APIC_EOI                    0xB0
44 #define APIC_LDR                    0xD0
45 #define   APIC_LDR_MASK               (0xFF<<24)
46 #define APIC_DFR                    0xE0
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
59
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
70
71 #include <l4/sys/compiler.h>
72 #include <l4/sys/types.h>
73
74 EXTERN_C_BEGIN
75
76 /* prototypes */
77 extern unsigned long apic_map_base;
78 extern unsigned long apic_timer_divisor;
79
80 extern unsigned long l4_scaler_apic_to_ms;
81
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);
86
87 L4_CV unsigned long l4_calibrate_apic(void);
88
89 EXTERN_C_END
90
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);
101
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);
106
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);
114
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);
118
119
120 /* write APIC register */
121 L4_INLINE void
122 apic_write(unsigned long reg, unsigned long v)
123 {
124   *((volatile unsigned long *)(apic_map_base+reg))=v;
125 }
126     
127
128 /* read APIC register */
129 L4_INLINE unsigned long
130 apic_read(unsigned long reg)
131 {
132   return *((volatile unsigned long *)(apic_map_base+reg));
133 }
134
135
136 /* disable LINT0 */
137 L4_INLINE void
138 apic_lvt0_disable_irq(void)
139 {
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);
144 }
145
146
147 /* enable LINT0 */
148 L4_INLINE void
149 apic_lvt0_enable_irq(void)
150 {
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);
155 }
156
157
158 /* disable LINT1 */
159 L4_INLINE void
160 apic_lvt1_disable_irq(void)
161 {
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);
166 }
167
168
169 /* enable LINT1 */
170 L4_INLINE void
171 apic_lvt1_enable_irq(void)
172 {
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);
177 }
178
179
180 /* write APIC timer register */
181 L4_INLINE void
182 apic_timer_write(unsigned long value)
183 {
184   apic_read(APIC_TMICT);
185   apic_write(APIC_TMICT,value);
186 }
187
188
189 /* read APIC timer register */
190 L4_INLINE unsigned long
191 apic_timer_read(void)
192 {
193   return apic_read(APIC_TMCCT);
194 }
195
196
197 /* disable IRQ when APIC timer passes 0 */
198 L4_INLINE void
199 apic_timer_disable_irq(void)
200 {
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);
205 }
206
207
208 /* enable IRQ when APIC timer passes 0 */
209 L4_INLINE void
210 apic_timer_enable_irq(void)
211 {
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);
216 }
217
218
219 L4_INLINE void
220 apic_timer_set_periodic(void)
221 {
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);
227 }
228
229
230 L4_INLINE void
231 apic_timer_set_one_shot(void)
232 {
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);
238 }
239
240
241 /* set vector of APIC timer irq */
242 L4_INLINE void
243 apic_timer_assign_irq(unsigned long vector)
244 {
245   unsigned long tmp_val;
246   tmp_val = apic_read(APIC_LVTT);
247   tmp_val &= 0xffffff00;
248   tmp_val |= vector;
249   tmp_val |= APIC_LVT_MASKED;
250   apic_write(APIC_LVTT, tmp_val);
251 }
252
253
254 /* disable IRQ when performance counter passes 0 */
255 L4_INLINE void
256 apic_perf_disable_irq(void)
257 {
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);
262 }
263
264
265 /* enable IRQ when performance counter passes 0 */
266 L4_INLINE void
267 apic_perf_enable_irq(void)
268 {
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);
273 }
274
275
276 /* set vector of performance counter irq */
277 L4_INLINE void
278 apic_perf_assign_irq(unsigned long vector)
279 {
280   unsigned long tmp_val;
281   tmp_val = apic_read(APIC_LVTPC);
282   tmp_val &= 0xffffff00;
283   tmp_val |= vector;
284   tmp_val |= APIC_LVT_MASKED;
285   apic_write(APIC_LVTPC, tmp_val);
286 }
287
288
289 /* activate APIC by writing to appropriate MSR */
290 L4_INLINE void
291 apic_activate_by_msr(void)
292 {
293   unsigned long low;
294   unsigned long high;
295     
296   /* rdmsr */
297   asm volatile(".byte 0xf; .byte 0x32\n"
298                :"=a" (low),
299                 "=d" (high)
300                :"c" (APIC_BASE_MSR)
301                );
302
303   low |= 0x800;                         /* activate APIC */
304   low &= 0x00000fff;
305   low |= (APIC_PHYS_BASE & 0xfffff000); /* set address */
306   
307   /* wrmsr */
308   asm volatile(".byte 0xf; .byte 0x30\n"
309                :
310                :"c" (APIC_BASE_MSR),
311                 "a" (low),
312                 "d" (high)
313                );
314 }
315
316
317 /* deactivate APIC by writing to appropriate MSR */
318 L4_INLINE void
319 apic_deactivate_by_msr(void)
320 {
321   unsigned long low;
322   unsigned long high;
323     
324   /* rdmsr */
325   asm volatile(".byte 0xf; .byte 0x32\n"
326                :"=a" (low),
327                 "=d" (high)
328                :"c" (APIC_BASE_MSR)
329                );
330
331   low  &= 0xfffff7ff;                    /* deactivate APIC */
332     
333   /* wrmsr */
334   asm volatile(".byte 0xf; .byte 0x30\n"
335                :
336                :"c" (APIC_BASE_MSR),
337                 "a" (low),
338                 "d" (high)
339                );
340 }
341
342
343 /* read memory mapped address of apic */
344 L4_INLINE unsigned long
345 apic_read_phys_address(void)
346 {
347   unsigned long low;
348   unsigned long high;
349
350   /* rdmsr */
351   asm volatile(".byte 0xf; .byte 0x32\n"
352                :"=a" (low),
353                 "=d" (high)
354                :"c" (APIC_BASE_MSR)
355                );
356
357   return (low  &= 0xfffff000);
358 }
359
360
361 /* test if APIC present */
362 L4_INLINE int
363 apic_test_present(void)
364 {
365   unsigned int dummy;
366   unsigned int capability;
367
368   asm volatile("pushl %%ebx ; cpuid ; popl %%ebx"
369              : "=a" (dummy),
370                "=c" (dummy),
371                "=d" (capability)
372              : "a" (0x00000001)
373              : "cc");
374
375   return ((capability & 1<<9) !=0);
376 }
377
378
379 L4_INLINE void
380 apic_soft_enable(void)
381 {
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);
388 }
389
390
391 L4_INLINE void
392 apic_init(unsigned long base_addr)
393 {
394   apic_map_base = base_addr;
395 }
396
397
398 L4_INLINE void
399 apic_done(void)
400 {
401   apic_map_base = 0;
402 }
403
404
405 L4_INLINE void
406 apic_irq_ack(void)
407 {
408   apic_read(APIC_SPIV);
409   apic_write(APIC_EOI, 0);
410 }
411
412
413 #endif /* __L4_UTIL_APIC_H */