x86: PICs for everyone!
[akaros.git] / kern / arch / x86 / apic.h
1 /*
2  * Copyright (c) 2009 The Regents of the University of California
3  * Barret Rhoden <brho@cs.berkeley.edu>
4  * See LICENSE for details.
5  */
6
7 #ifndef ROS_KERN_APIC_H
8 #define ROS_KERN_APIC_H
9
10 /* 
11  * Functions and definitions for dealing with the APIC and PIC, specific to
12  * Intel.  Does not handle an x2APIC.
13  */
14 #include <arch/mmu.h>
15 #include <arch/x86.h>
16 #include <atomic.h>
17
18 /* PIC (8259A)
19  * When looking at the specs, A0 is our CMD line, and A1 is the DATA line.  This
20  * means that blindly writing to PIC1_DATA is an OCW1 (interrupt masks).  When
21  * writing to CMD (A0), the chip can determine betweeb OCW2 and OCW3 by the
22  * setting of a few specific bits (OCW2 has bit 3 unset, OCW3 has it set). */
23 #define PIC1_CMD                                        0x20
24 #define PIC1_DATA                                       0x21
25 #define PIC2_CMD                                        0xA0
26 #define PIC2_DATA                                       0xA1
27 // These are also hardcoded into the IRQ_HANDLERs of kern/trapentry.S
28 #define PIC1_OFFSET                                     0x20
29 #define PIC2_OFFSET                                     0x28
30 #define PIC1_SPURIOUS                           (7 + PIC1_OFFSET)
31 #define PIC2_SPURIOUS                           (7 + PIC2_OFFSET)
32 #define PIC_EOI                                         0x20    /* OCW2 EOI */
33 /* These set the next CMD read to return specific values.  Note that the chip
34  * remembers what setting we had before (IRR or ISR), if you do other reads of
35  * CMD. (not tested, written in the spec sheet) */
36 #define PIC_READ_IRR                            0x0a    /* OCW3 irq ready next CMD read */
37 #define PIC_READ_ISR                            0x0b    /* OCW3 irq service next CMD read */
38
39 // Local APIC
40 /* PBASE is the physical address.  It is mapped in at the VADDR LAPIC_BASE.
41  * 64 bit note: it looks like this is mapped to the same place in 64 bit address
42  * spaces.  We just happen to have a slight 'hole' in addressable physical
43  * memory.  We can move the PBASE, but we're limited to 32 bit (physical)
44  * addresses. */
45 #define LAPIC_PBASE                                     0xfee00000      /* default *physical* address */
46 #define LAPIC_EOI                                       (LAPIC_BASE + 0x0b0)
47 #define LAPIC_SPURIOUS                          (LAPIC_BASE + 0x0f0)
48 #define LAPIC_VERSION                           (LAPIC_BASE + 0x030)
49 #define LAPIC_ERROR                                     (LAPIC_BASE + 0x280)
50 #define LAPIC_ID                                        (LAPIC_BASE + 0x020)
51 #define LAPIC_LOGICAL_ID                        (LAPIC_BASE + 0x0d0)
52 // LAPIC Local Vector Table
53 #define LAPIC_LVT_TIMER                         (LAPIC_BASE + 0x320)
54 #define LAPIC_LVT_LINT0                         (LAPIC_BASE + 0x350)
55 #define LAPIC_LVT_LINT1                         (LAPIC_BASE + 0x360)
56 #define LAPIC_LVT_ERROR                         (LAPIC_BASE + 0x370)
57 #define LAPIC_LVT_PERFMON                       (LAPIC_BASE + 0x340)
58 #define LAPIC_LVT_THERMAL                       (LAPIC_BASE + 0x330)
59 #define LAPIC_LVT_MASK                          0x00010000
60 // LAPIC Timer
61 #define LAPIC_TIMER_INIT                        (LAPIC_BASE + 0x380)
62 #define LAPIC_TIMER_CURRENT                     (LAPIC_BASE + 0x390)
63 #define LAPIC_TIMER_DIVIDE                      (LAPIC_BASE + 0x3e0)
64 #define LAPIC_TIMER_DEFAULT_VECTOR      0xeb    /* Aka 235, IRQ203 */
65 /* Quick note on the divisor.  The LAPIC timer ticks once per divisor-bus ticks
66  * (system bus or APIC bus, depending on the model).  Ex: A divisor of 128 means
67  * 128 bus ticks results in 1 timer tick.  The divisor increases the time range
68  * and decreases the granularity of the timer.  Numbers are appx, based on 4
69  * billion ticks, vs 2^32 ticks.
70  * Ex:   1GHz bus, div 001:    4sec max,    1ns granularity
71  * Ex:   1GHz bus, div 128:  512sec max,  128ns granularity
72  * Ex: 100MHz bus, div 001:   40sec max,   10ns granularity
73  * Ex: 100MHz bus, div 128: 5120sec max, 1280ns granularity */
74 #define LAPIC_TIMER_DIVISOR_VAL         32      /* seems reasonable */
75 #define LAPIC_TIMER_DIVISOR_BITS        0x8     /* Div = 32 */
76
77 // IPI Interrupt Command Register
78 #define LAPIC_IPI_ICR_LOWER                     (LAPIC_BASE + 0x300)
79 #define LAPIC_IPI_ICR_UPPER                     (LAPIC_BASE + 0x310)
80 /* Interrupts being serviced (in-service) and pending (interrupt request reg).
81  * Note these registers are not normal bitmaps, but instead are 8 separate
82  * 32-bit registers, spaced/aligned on 16 byte boundaries in the LAPIC address
83  * space. */
84 #define LAPIC_ISR                                       (LAPIC_BASE + 0x100)
85 #define LAPIC_IRR                                       (LAPIC_BASE + 0x200)
86
87 // PIT (Programmable Interval Timer)
88 #define TIMER_REG_CNTR0 0       /* timer counter 0 port */
89 #define TIMER_REG_CNTR1 1       /* timer counter 1 port */
90 #define TIMER_REG_CNTR2 2       /* timer counter 2 port */
91 #define TIMER_REG_MODE  3       /* timer mode port */
92 #define TIMER_SEL0      0x00    /* select counter 0 */
93 #define TIMER_SEL1      0x40    /* select counter 1 */
94 #define TIMER_SEL2      0x80    /* select counter 2 */
95 #define TIMER_INTTC     0x00    /* mode 0, intr on terminal cnt */
96 #define TIMER_ONESHOT   0x02    /* mode 1, one shot */
97 #define TIMER_RATEGEN   0x04    /* mode 2, rate generator */
98 #define TIMER_SQWAVE    0x06    /* mode 3, square wave */
99 #define TIMER_SWSTROBE  0x08    /* mode 4, s/w triggered strobe */
100 #define TIMER_HWSTROBE  0x0a    /* mode 5, h/w triggered strobe */
101 #define TIMER_LATCH     0x00    /* latch counter for reading */
102 #define TIMER_LSB       0x10    /* r/w counter LSB */
103 #define TIMER_MSB       0x20    /* r/w counter MSB */
104 #define TIMER_16BIT     0x30    /* r/w counter 16 bits, LSB first */
105 #define TIMER_BCD       0x01    /* count in BCD */
106
107 #define PIT_FREQ                                        1193182
108
109 #define IO_TIMER1   0x40        /* 8253 Timer #1 */
110 #define TIMER_CNTR0 (IO_TIMER1 + TIMER_REG_CNTR0)
111 #define TIMER_CNTR1 (IO_TIMER1 + TIMER_REG_CNTR1)
112 #define TIMER_CNTR2 (IO_TIMER1 + TIMER_REG_CNTR2)
113 #define TIMER_MODE  (IO_TIMER1 + TIMER_REG_MODE)
114
115 typedef struct system_timing {
116         uint64_t tsc_freq;
117         uint64_t bus_freq;
118         uint64_t timing_overhead;
119         uint16_t pit_divisor;
120         uint8_t pit_mode;
121 } system_timing_t;
122
123 extern system_timing_t system_timing;
124
125 /* Tracks whether it is safe to execute core_id() or not.  If we're using the
126  * LAPIC, we need to have the LAPIC mapped into VM.  vm_init() sets this to
127  * TRUE.
128  *
129  * If we're using rdtscp, if the instruction is supported, we can call core_id()
130  * without rebooting.  cpuinfo should have panic'd if we're running on a machine
131  * that doesn't support rdtscp, before vm_init().
132  *
133  * If we're using something else (like segmentation), then that will need to get
134  * set up before vm_init(), at least for core 0.
135  *
136  * Note that core_id() will return 0 (or possibly another wrong answer) on cores
137  * other than core 0 when it is called before smp_boot completes. */
138 extern bool core_id_ready;
139
140 void pic_remap(void);
141 void pic_mask_irq(int trap_nr);
142 void pic_unmask_irq(int trap_nr);
143 void pic_mask_all(void);
144 uint16_t pic_get_mask(void);
145 uint16_t pic_get_irr(void);
146 uint16_t pic_get_isr(void);
147 bool pic_check_spurious(int trap_nr);
148 void pic_send_eoi(int trap_nr);
149 bool lapic_check_spurious(int trap_nr);
150 bool lapic_get_isr_bit(uint8_t vector);
151 bool lapic_get_irr_bit(uint8_t vector);
152 void lapic_print_isr(void);
153 bool ipi_is_pending(uint8_t vector);
154 void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div);
155 void lapic_set_timer(uint32_t usec, bool periodic);
156 uint32_t lapic_get_default_id(void);
157 // PIT related
158 void pit_set_timer(uint32_t freq, uint32_t mode);
159 void timer_init(void);
160 void udelay_pit(uint64_t usec);
161 // TODO: right now timer defaults to TSC
162 uint64_t gettimer(void);
163 uint64_t getfreq(void);
164
165 static inline void lapic_send_eoi(int unused);
166 static inline uint32_t lapic_get_version(void);
167 static inline uint32_t lapic_get_error(void);
168 static inline uint32_t lapic_get_id(void);
169 static inline void lapic_set_id(uint8_t id);    // Careful, may not actually work
170 static inline uint8_t lapic_get_logid(void);
171 static inline void lapic_set_logid(uint8_t id);
172 static inline void lapic_disable_timer(void);
173 static inline void lapic_disable(void);
174 static inline void lapic_enable(void);
175 static inline void lapic_wait_to_send(void);
176 static inline void send_init_ipi(void);
177 static inline void send_startup_ipi(uint8_t vector);
178 static inline void send_self_ipi(uint8_t vector);
179 static inline void send_broadcast_ipi(uint8_t vector);
180 static inline void send_all_others_ipi(uint8_t vector);
181 static inline void __send_ipi(uint8_t hw_coreid, uint8_t vector);
182 static inline void send_group_ipi(uint8_t hw_groupid, uint8_t vector);
183 static inline void __send_nmi(uint8_t hw_coreid);
184
185 #define mask_lapic_lvt(entry) \
186         write_mmreg32(entry, read_mmreg32(entry) | LAPIC_LVT_MASK)
187 #define unmask_lapic_lvt(entry) \
188         write_mmreg32(entry, read_mmreg32(entry) & ~LAPIC_LVT_MASK)
189
190 static inline void lapic_send_eoi(int unused)
191 {
192         write_mmreg32(LAPIC_EOI, 0);
193 }
194
195 static inline uint32_t lapic_get_version(void)
196 {
197         return read_mmreg32(LAPIC_VERSION);
198 }
199
200 static inline uint32_t lapic_get_error(void)
201 {
202         write_mmreg32(LAPIC_ERROR, 0xdeadbeef);
203         return read_mmreg32(LAPIC_ERROR);
204 }
205
206 static inline uint32_t lapic_get_id(void)
207 {
208         return read_mmreg32(LAPIC_ID) >> 24;
209 }
210
211 static inline void lapic_set_id(uint8_t id)
212 {
213         write_mmreg32(LAPIC_ID, id << 24);
214 }
215
216 static inline uint8_t lapic_get_logid(void)
217 {
218         return read_mmreg32(LAPIC_LOGICAL_ID) >> 24;
219 }
220
221 static inline void lapic_set_logid(uint8_t id)
222 {
223         write_mmreg32(LAPIC_LOGICAL_ID, id << 24);
224 }
225
226 static inline void lapic_disable_timer(void)
227 {
228         write_mmreg32(LAPIC_LVT_TIMER, 0);
229 }
230
231 /* There are a couple ways to do it.  The MSR route doesn't seem to work
232  * in KVM.  It's also a somewhat permanent thing
233  */
234 static inline void lapic_disable(void)
235 {
236         write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) & 0xffffefff);
237         //write_msr(IA32_APIC_BASE, read_msr(IA32_APIC_BASE) & ~MSR_APIC_ENABLE);
238 }
239
240 /* Spins until previous IPIs are delivered.  Not sure if we want it inlined
241  * Also not sure when we really need to do this. 
242  */
243 static inline void lapic_wait_to_send(void)
244 {
245         while (read_mmreg32(LAPIC_IPI_ICR_LOWER) & 0x1000)
246                 __cpu_relax();
247 }
248
249 static inline void lapic_enable(void)
250 {
251         write_mmreg32(LAPIC_SPURIOUS, read_mmreg32(LAPIC_SPURIOUS) | 0x00000100);
252 }
253
254 static inline void send_init_ipi(void)
255 {
256         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4500);
257         lapic_wait_to_send();
258 }
259
260 static inline void send_startup_ipi(uint8_t vector)
261 {
262         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4600 | vector);
263         lapic_wait_to_send();
264 }
265
266 static inline void send_self_ipi(uint8_t vector)
267 {
268         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00044000 | vector);
269         lapic_wait_to_send();
270 }
271
272 static inline void send_broadcast_ipi(uint8_t vector)
273 {
274         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00084000 | vector);
275         lapic_wait_to_send();
276 }
277
278 static inline void send_all_others_ipi(uint8_t vector)
279 {
280         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x000c4000 | vector);
281         lapic_wait_to_send();
282 }
283
284 static inline void __send_ipi(uint8_t hw_coreid, uint8_t vector)
285 {
286         write_mmreg32(LAPIC_IPI_ICR_UPPER, hw_coreid << 24);
287         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004000 | vector);
288         lapic_wait_to_send();
289 }
290
291 static inline void send_group_ipi(uint8_t hw_groupid, uint8_t vector)
292 {
293         write_mmreg32(LAPIC_IPI_ICR_UPPER, hw_groupid << 24);
294         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004800 | vector);
295         lapic_wait_to_send();
296 }
297
298 static inline void __send_nmi(uint8_t hw_coreid)
299 {
300         if (hw_coreid == 255)
301                 return;
302         write_mmreg32(LAPIC_IPI_ICR_UPPER, hw_coreid << 24);
303         write_mmreg32(LAPIC_IPI_ICR_LOWER, 0x00004400);
304         lapic_wait_to_send();
305 }
306
307 /* To change the LAPIC Base (not recommended):
308         msr_val = read_msr(IA32_APIC_BASE);
309         msr_val = msr_val & ~MSR_APIC_BASE_ADDRESS | 0xfaa00000;
310         write_msr(IA32_APIC_BASE, msr_val);
311 */
312
313 /* 
314  * This file is part of the UCB release of Plan 9. It is subject to the license
315  * terms in the LICENSE file found in the top-level directory of this
316  * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
317  * part of the UCB release of Plan 9, including this file, may be copied,
318  * modified, propagated, or distributed except according to the terms contained
319  * in the LICENSE file.
320  */
321
322 /*
323  * There are 2 flavours of APIC, Local APIC and IOAPIC,
324  * Each I/O APIC has a unique physical address,
325  * Local APICs are all at the same physical address as they can only be
326  * accessed by the local CPU.  APIC ids are unique to the
327  * APIC type, so an IOAPIC and APIC both with id 0 is ok.
328  */
329
330 struct ioapic {
331         spinlock_t lock;                        /* IOAPIC: register access */
332         uintptr_t addr;                         /* IOAPIC: register base */
333         uintptr_t paddr;                        /* register base */
334         int nrdt;                                       /* IOAPIC: size of RDT */
335         int gsib;                                       /* IOAPIC: global RDT index */
336         int ibase;                                      /* global interrupt base */
337 };
338
339 struct lapic {
340         int machno;                                     /* APIC */
341
342         uint32_t lvt[6];
343         int nlvt;
344         int ver;
345
346         int64_t hz;                                     /* APIC Timer frequency */
347         int64_t max;
348         int64_t min;
349         int64_t div;
350 };
351
352 struct apic {
353         int useable;                            /* en */
354         struct ioapic;
355         struct lapic;
356 };
357
358 enum {
359         Nbus = 256,
360         Napic = 254,    /* xAPIC architectural limit */
361         Nrdt = 64,
362 };
363
364 /*
365  * Common bits for
366  *      IOAPIC Redirection Table Entry (RDT);
367  *      APIC Local Vector Table Entry (LVT);
368  *      APIC Interrupt Command Register (ICR).
369  * [10:8] Message Type
370  * [11] Destination Mode (RW)
371  * [12] Delivery Status (RO)
372  * [13] Interrupt Input Pin Polarity (RW)
373  * [14] Remote IRR (RO)
374  * [15] Trigger Mode (RW)
375  * [16] Interrupt Mask
376  */
377 enum {
378         MTf = 0x00000000,                       /* Fixed */
379         MTlp = 0x00000100,      /* Lowest Priority */
380         MTsmi = 0x00000200,     /* SMI */
381         MTrr = 0x00000300,      /* Remote Read */
382         MTnmi = 0x00000400,     /* NMI */
383         MTir = 0x00000500,      /* INIT/RESET */
384         MTsipi = 0x00000600,    /* Startup IPI */
385         MTei = 0x00000700,      /* ExtINT */
386
387         Pm = 0x00000000,        /* Physical Mode */
388         Lm = 0x00000800,        /* Logical Mode */
389
390         Ds = 0x00001000,        /* Delivery Status */
391         IPhigh = 0x00000000,    /* IIPP High */
392         IPlow = 0x00002000,     /* IIPP Low */
393         Rirr = 0x00004000,      /* Remote IRR */
394         TMedge = 0x00000000,    /* Trigger Mode Edge */
395         TMlevel = 0x00008000,   /* Trigger Mode Level */
396         Im = 0x00010000,        /* Interrupt Mask */
397 };
398
399 extern struct apic xlapic[Napic];
400 extern struct apic xioapic[Napic];
401
402 #define l16get(p)       (((p)[1]<<8)|(p)[0])
403 #define l32get(p)       (((uint32_t)l16get(p+2)<<16)|l16get(p))
404 #define l64get(p)       (((uint64_t)l32get(p+4)<<32)|l32get(p))
405
406 #include <arch/ioapic.h>
407
408 char *apicdump(char *, char *);
409 void apictimerenab(void);
410 void apicinit(int apicno, uintptr_t pa, int isbp);
411
412 /*
413 extern int pcimsienable(Pcidev*, uint64_t);
414 extern int pcimsimask(Pcidev*, int);
415 */
416
417 #endif /* ROS_KERN_APIC_H */