L4Re - L4 Runtime Environment
apic.h
Go to the documentation of this file.
1 
5 /*
6  * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>,
7  * Torsten Frenzel <frenzel@os.inf.tu-dresden.de>
8  * economic rights: Technische Universit├Ąt Dresden (Germany)
9  * This file is part of TUD:OS and distributed under the terms of the
10  * GNU Lesser General Public License 2.1.
11  * Please see the COPYING-LGPL-2.1 file for details.
12  */
13 #ifndef __L4_UTIL_APIC_H
14 #define __L4_UTIL_APIC_H
15 
16 /*
17  * Local APIC programming library
18  *
19  * For documentation, see
20  *
21  * "Intel Architecture Software Developer's Manual", Volume 3, chapter 7.5:
22  * "Advanced Programmable Interrupt Controller (APIC)"
23  *
24  * Local APIC is present since
25  * - INTEL P6 (PPro)
26  * - AMD K7 (Athlon), Model 2
27  *
28  * In non-SMP-boards, local APIC is disabled, but
29  * can be activated by writing to a MSR register.
30  * For using APIC see packets cpufreq and l4rtl.
31  *
32  * See linux/include/asm-i386/i82489.h for further details.
33  */
34 
35 #define APIC_PHYS_BASE 0xFEE00000
36 #define APIC_MAP_BASE 0xA0200000
37 #define APIC_BASE_MSR 0x1b
38 
39 #define APIC_ID 0x20
40 #define GET_APIC_ID(x) (((x)>>24)&0x0F)
41 #define APIC_LVR 0x30
42 #define GET_APIC_VERSION(x) ((x)&0xFF)
43 #define APIC_TASKPRI 0x80
44 #define APIC_TPRI_MASK 0xFF
45 #define APIC_EOI 0xB0
46 #define APIC_LDR 0xD0
47 #define APIC_LDR_MASK (0xFF<<24)
48 #define APIC_DFR 0xE0
49 #define SET_APIC_DFR(x) ((x)<<28)
50 #define APIC_SPIV 0xF0
51 #define APIC_LVTT 0x320
52 #define APIC_LVTPC 0x340
53 #define APIC_LVT0 0x350
54 #define SET_APIC_TIMER_BASE(x) (((x)<<18))
55 #define APIC_TIMER_BASE_DIV 0x2
56 #define APIC_LVT1 0x360
57 #define APIC_LVTERR 0x370
58 #define APIC_TMICT 0x380
59 #define APIC_TMCCT 0x390
60 #define APIC_TDCR 0x3E0
61 
62 #define APIC_LVT_MASKED (1<<16)
63 #define APIC_LVT_TIMER_PERIODIC (1<<17)
64 #define APIC_TDR_DIV_1 0xB
65 #define APIC_TDR_DIV_2 0x0
66 #define APIC_TDR_DIV_4 0x1
67 #define APIC_TDR_DIV_8 0x2
68 #define APIC_TDR_DIV_16 0x3
69 #define APIC_TDR_DIV_32 0x8
70 #define APIC_TDR_DIV_64 0x9
71 #define APIC_TDR_DIV_128 0xA
72 
73 #include <l4/sys/compiler.h>
74 #include <l4/sys/types.h>
75 
77 
78 /* prototypes */
79 extern unsigned long apic_map_base;
80 extern unsigned long apic_timer_divisor;
81 
82 extern unsigned long l4_scaler_apic_to_ms;
83 
84 L4_CV void apic_show_registers(void);
85 L4_CV int apic_check_working(void);
86 L4_CV void apic_activate_by_io(void);
87 L4_CV void apic_timer_set_divisor(int divisor);
88 
89 L4_CV unsigned long l4_calibrate_apic(void);
90 
92 
93 L4_INLINE void apic_write(unsigned long reg, unsigned long v);
94 L4_INLINE unsigned long apic_read(unsigned long reg);
95 L4_INLINE void apic_activate_by_msr(void);
96 L4_INLINE void apic_deactivate_by_msr(void);
97 L4_INLINE unsigned long apic_read_phys_address(void);
98 L4_INLINE int apic_test_present(void);
99 L4_INLINE void apic_soft_enable(void);
100 L4_INLINE void apic_init(unsigned long map_addr);
101 L4_INLINE void apic_done(void);
102 L4_INLINE void apic_irq_ack(void);
103 
104 L4_INLINE void apic_lvt0_disable_irq(void);
105 L4_INLINE void apic_lvt0_enable_irq(void);
106 L4_INLINE void apic_lvt1_disable_irq(void);
107 L4_INLINE void apic_lvt1_enable_irq(void);
108 
109 L4_INLINE void apic_timer_write(unsigned long value);
110 L4_INLINE unsigned long apic_timer_read(void);
111 L4_INLINE void apic_timer_disable_irq(void);
112 L4_INLINE void apic_timer_enable_irq(void);
113 L4_INLINE void apic_timer_assign_irq(unsigned long vector);
114 L4_INLINE void apic_timer_set_periodic(void);
115 L4_INLINE void apic_timer_set_one_shot(void);
116 
117 L4_INLINE void apic_perf_disable_irq(void);
118 L4_INLINE void apic_perf_enable_irq(void);
119 L4_INLINE void apic_perf_assign_irq(unsigned long vector);
120 
121 
122 /* write APIC register */
123 L4_INLINE void
124 apic_write(unsigned long reg, unsigned long v)
125 {
126  *((volatile unsigned long *)(apic_map_base+reg))=v;
127 }
128 
129 
130 /* read APIC register */
131 L4_INLINE unsigned long
132 apic_read(unsigned long reg)
133 {
134  return *((volatile unsigned long *)(apic_map_base+reg));
135 }
136 
137 
138 /* disable LINT0 */
139 L4_INLINE void
140 apic_lvt0_disable_irq(void)
141 {
142  unsigned long tmp_val;
143  tmp_val = apic_read(APIC_LVT0);
144  tmp_val |= APIC_LVT_MASKED;
145  apic_write(APIC_LVT0, tmp_val);
146 }
147 
148 
149 /* enable LINT0 */
150 L4_INLINE void
151 apic_lvt0_enable_irq(void)
152 {
153  unsigned long tmp_val;
154  tmp_val = apic_read(APIC_LVT0);
155  tmp_val &= ~(APIC_LVT_MASKED);
156  apic_write(APIC_LVT0, tmp_val);
157 }
158 
159 
160 /* disable LINT1 */
161 L4_INLINE void
162 apic_lvt1_disable_irq(void)
163 {
164  unsigned long tmp_val;
165  tmp_val = apic_read(APIC_LVT1);
166  tmp_val |= APIC_LVT_MASKED;
167  apic_write(APIC_LVT1, tmp_val);
168 }
169 
170 
171 /* enable LINT1 */
172 L4_INLINE void
173 apic_lvt1_enable_irq(void)
174 {
175  unsigned long tmp_val;
176  tmp_val = apic_read(APIC_LVT1);
177  tmp_val &= ~(APIC_LVT_MASKED);
178  apic_write(APIC_LVT1, tmp_val);
179 }
180 
181 
182 /* write APIC timer register */
183 L4_INLINE void
184 apic_timer_write(unsigned long value)
185 {
186  apic_read(APIC_TMICT);
187  apic_write(APIC_TMICT,value);
188 }
189 
190 
191 /* read APIC timer register */
192 L4_INLINE unsigned long
193 apic_timer_read(void)
194 {
195  return apic_read(APIC_TMCCT);
196 }
197 
198 
199 /* disable IRQ when APIC timer passes 0 */
200 L4_INLINE void
201 apic_timer_disable_irq(void)
202 {
203  unsigned long tmp_val;
204  tmp_val = apic_read(APIC_LVTT);
205  tmp_val |= APIC_LVT_MASKED;
206  apic_write(APIC_LVTT, tmp_val);
207 }
208 
209 
210 /* enable IRQ when APIC timer passes 0 */
211 L4_INLINE void
212 apic_timer_enable_irq(void)
213 {
214  unsigned long tmp_val;
215  tmp_val = apic_read(APIC_LVTT);
216  tmp_val &= ~(APIC_LVT_MASKED);
217  apic_write(APIC_LVTT, tmp_val);
218 }
219 
220 
221 L4_INLINE void
222 apic_timer_set_periodic(void)
223 {
224  unsigned long tmp_val;
225  tmp_val = apic_read(APIC_LVTT);
226  tmp_val |= APIC_LVT_TIMER_PERIODIC;
227  tmp_val |= APIC_LVT_MASKED;
228  apic_write(APIC_LVTT, tmp_val);
229 }
230 
231 
232 L4_INLINE void
233 apic_timer_set_one_shot(void)
234 {
235  unsigned long tmp_val;
236  tmp_val = apic_read(APIC_LVTT);
237  tmp_val &= ~APIC_LVT_TIMER_PERIODIC;
238  tmp_val |= APIC_LVT_MASKED;
239  apic_write(APIC_LVTT, tmp_val);
240 }
241 
242 
243 /* set vector of APIC timer irq */
244 L4_INLINE void
245 apic_timer_assign_irq(unsigned long vector)
246 {
247  unsigned long tmp_val;
248  tmp_val = apic_read(APIC_LVTT);
249  tmp_val &= 0xffffff00;
250  tmp_val |= vector;
251  tmp_val |= APIC_LVT_MASKED;
252  apic_write(APIC_LVTT, tmp_val);
253 }
254 
255 
256 /* disable IRQ when performance counter passes 0 */
257 L4_INLINE void
258 apic_perf_disable_irq(void)
259 {
260  unsigned long tmp_val;
261  tmp_val = apic_read(APIC_LVTPC);
262  tmp_val |= APIC_LVT_MASKED;
263  apic_write(APIC_LVTPC, tmp_val);
264 }
265 
266 
267 /* enable IRQ when performance counter passes 0 */
268 L4_INLINE void
269 apic_perf_enable_irq(void)
270 {
271  unsigned long tmp_val;
272  tmp_val = apic_read(APIC_LVTPC);
273  tmp_val &= ~(APIC_LVT_MASKED);
274  apic_write(APIC_LVTPC, tmp_val);
275 }
276 
277 
278 /* set vector of performance counter irq */
279 L4_INLINE void
280 apic_perf_assign_irq(unsigned long vector)
281 {
282  unsigned long tmp_val;
283  tmp_val = apic_read(APIC_LVTPC);
284  tmp_val &= 0xffffff00;
285  tmp_val |= vector;
286  tmp_val |= APIC_LVT_MASKED;
287  apic_write(APIC_LVTPC, tmp_val);
288 }
289 
290 
291 /* activate APIC by writing to appropriate MSR */
292 L4_INLINE void
293 apic_activate_by_msr(void)
294 {
295  unsigned long low;
296  unsigned long high;
297 
298  /* rdmsr */
299  asm volatile(".byte 0xf; .byte 0x32\n"
300  :"=a" (low),
301  "=d" (high)
302  :"c" (APIC_BASE_MSR)
303  );
304 
305  low |= 0x800; /* activate APIC */
306  low &= 0x00000fff;
307  low |= (APIC_PHYS_BASE & 0xfffff000); /* set address */
308 
309  /* wrmsr */
310  asm volatile(".byte 0xf; .byte 0x30\n"
311  :
312  :"c" (APIC_BASE_MSR),
313  "a" (low),
314  "d" (high)
315  );
316 }
317 
318 
319 /* deactivate APIC by writing to appropriate MSR */
320 L4_INLINE void
321 apic_deactivate_by_msr(void)
322 {
323  unsigned long low;
324  unsigned long high;
325 
326  /* rdmsr */
327  asm volatile(".byte 0xf; .byte 0x32\n"
328  :"=a" (low),
329  "=d" (high)
330  :"c" (APIC_BASE_MSR)
331  );
332 
333  low &= 0xfffff7ff; /* deactivate APIC */
334 
335  /* wrmsr */
336  asm volatile(".byte 0xf; .byte 0x30\n"
337  :
338  :"c" (APIC_BASE_MSR),
339  "a" (low),
340  "d" (high)
341  );
342 }
343 
344 
345 /* read memory mapped address of apic */
346 L4_INLINE unsigned long
347 apic_read_phys_address(void)
348 {
349  unsigned long low;
350  unsigned long high;
351 
352  /* rdmsr */
353  asm volatile(".byte 0xf; .byte 0x32\n"
354  :"=a" (low),
355  "=d" (high)
356  :"c" (APIC_BASE_MSR)
357  );
358 
359  return (low &= 0xfffff000);
360 }
361 
362 
363 /* test if APIC present */
364 L4_INLINE int
365 apic_test_present(void)
366 {
367  unsigned int dummy;
368  unsigned int capability;
369 
370  asm volatile("pushl %%ebx ; cpuid ; popl %%ebx"
371  : "=a" (dummy),
372  "=c" (dummy),
373  "=d" (capability)
374  : "a" (0x00000001)
375  : "cc");
376 
377  return ((capability & 1<<9) !=0);
378 }
379 
380 
381 L4_INLINE void
382 apic_soft_enable(void)
383 {
384  unsigned long tmp_val;
385  tmp_val = apic_read(APIC_SPIV);
386  tmp_val |= (1<<8); /* enable APIC */
387  tmp_val &= ~(1<<9); /* enable Focus Processor Checking */
388  tmp_val |= 0xff; /* Set spurious IRQ vector to 0xff */
389  apic_write(APIC_SPIV, tmp_val);
390 }
391 
392 
393 L4_INLINE void
394 apic_init(unsigned long base_addr)
395 {
396  apic_map_base = base_addr;
397 }
398 
399 
400 L4_INLINE void
401 apic_done(void)
402 {
403  apic_map_base = 0;
404 }
405 
406 
407 L4_INLINE void
408 apic_irq_ack(void)
409 {
410  apic_read(APIC_SPIV);
411  apic_write(APIC_EOI, 0);
412 }
413 
414 
415 #endif /* __L4_UTIL_APIC_H */
Common L4 ABI Data Types.
#define EXTERN_C_END
End section with C types and functions.
Definition: compiler.h:187
L4 compiler related defines.
#define EXTERN_C_BEGIN
Start section with C types and functions.
Definition: compiler.h:186
#define L4_CV
Define calling convention.
Definition: linkage.h:44