x86: PICs for everyone!
[akaros.git] / kern / arch / x86 / apic.c
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 #ifdef __SHARC__
8 #pragma nosharc
9 #define SINIT(x) x
10 #endif
11
12 #include <arch/mmu.h>
13 #include <arch/x86.h>
14 #include <arch/arch.h>
15 #include <arch/apic.h>
16 #include <time.h>
17 #include <assert.h>
18 #include <stdio.h>
19 #include <bitmask.h>
20 #include <arch/coreid.h>
21
22 system_timing_t RO system_timing = {0, 0, 0xffff, 0};
23 bool core_id_ready = FALSE;
24 spinlock_t piclock = SPINLOCK_INITIALIZER_IRQSAVE;
25
26 /* * Remaps the Programmable Interrupt Controller to use IRQs 32-47
27  * http://wiki.osdev.org/PIC
28  * Check osdev for a more thorough explanation/implementation.
29  * http://bochs.sourceforge.net/techspec/PORTS.LST  */
30 void pic_remap(void)
31 {
32         spin_lock_irqsave(&piclock);
33         /* start initialization (ICW1) */
34         outb(PIC1_CMD, 0x11);
35         outb(PIC2_CMD, 0x11);
36         /* set new offsets (ICW2) */
37         outb(PIC1_DATA, PIC1_OFFSET);
38         outb(PIC2_DATA, PIC2_OFFSET);
39         /* set up cascading (ICW3) */
40         outb(PIC1_DATA, 0x04);
41         outb(PIC2_DATA, 0x02);
42         /* other stuff (put in 8086/88 mode, or whatever) (ICW4) */
43         outb(PIC1_DATA, 0x01);
44         outb(PIC2_DATA, 0x01);
45         /* Init done, further data R/W access the interrupt mask */
46         /* set masks, defaulting to all masked for now */
47         outb(PIC1_DATA, 0xff);
48         outb(PIC2_DATA, 0xff);
49         spin_unlock_irqsave(&piclock);
50 }
51
52 void pic_mask_irq(int trap_nr)
53 {
54         int irq = trap_nr - PIC1_OFFSET;
55         spin_lock_irqsave(&piclock);
56         if (irq > 7)
57                 outb(PIC2_DATA, inb(PIC2_DATA) | (1 << (irq - 8)));
58         else
59                 outb(PIC1_DATA, inb(PIC1_DATA) | (1 << irq));
60         spin_unlock_irqsave(&piclock);
61 }
62
63 void pic_unmask_irq(int trap_nr)
64 {
65         int irq = trap_nr - PIC1_OFFSET;
66         spin_lock_irqsave(&piclock);
67         if (irq > 7) {
68                 outb(PIC2_DATA, inb(PIC2_DATA) & ~(1 << (irq - 8)));
69                 outb(PIC1_DATA, inb(PIC1_DATA) & 0xfb); // make sure irq2 is unmasked
70         } else
71                 outb(PIC1_DATA, inb(PIC1_DATA) & ~(1 << irq));
72         spin_unlock_irqsave(&piclock);
73 }
74
75 void pic_mask_all(void)
76 {
77         for (int i = 0 + PIC1_OFFSET; i < 16 + PIC1_OFFSET; i++)
78                 pic_mask_irq(i);
79 }
80
81 /* Aka, the IMR.  Simply reading the data port are OCW1s. */
82 uint16_t pic_get_mask(void)
83 {
84         uint16_t ret;
85         spin_lock_irqsave(&piclock);
86         ret = (inb(PIC2_DATA) << 8) | inb(PIC1_DATA);
87         spin_unlock_irqsave(&piclock);
88         return ret;
89 }
90
91 static uint16_t __pic_get_irq_reg(int ocw3)
92 {
93         uint16_t ret;
94         spin_lock_irqsave(&piclock);
95         /* OCW3 to PIC CMD to get the register values.  PIC2 is chained, and
96          * represents IRQs 8-15.  PIC1 is IRQs 0-7, with 2 being the chain */
97         outb(PIC1_CMD, ocw3);
98         outb(PIC2_CMD, ocw3);
99         ret = (inb(PIC2_CMD) << 8) | inb(PIC1_CMD);
100         spin_unlock_irqsave(&piclock);
101         return ret;
102 }
103
104 /* Returns the combined value of the cascaded PICs irq request register */
105 uint16_t pic_get_irr(void)
106 {
107         return __pic_get_irq_reg(PIC_READ_IRR);
108 }
109
110 /* Returns the combined value of the cascaded PICs irq service register */
111 uint16_t pic_get_isr(void)
112 {
113         return __pic_get_irq_reg(PIC_READ_ISR);
114 }
115
116 /* Takes a raw vector/trap number (32-47), not a device IRQ (0-15) */
117 bool pic_check_spurious(int trap_nr)
118 {
119         /* the PIC may send spurious irqs via one of the chips irq 7.  if the isr
120          * doesn't show that irq, then it was spurious, and we don't send an eoi.
121          * Check out http://wiki.osdev.org/8259_PIC#Spurious_IRQs */
122         if ((trap_nr == PIC1_SPURIOUS) && !(pic_get_isr() & (1 << 7))) {
123                 printd("Spurious PIC1 irq!\n"); /* want to know if this happens */
124                 return TRUE;
125         }
126         if ((trap_nr == PIC2_SPURIOUS) && !(pic_get_isr() & (1 << 15))) {
127                 printd("Spurious PIC2 irq!\n"); /* want to know if this happens */
128                 /* for the cascaded PIC, we *do* need to send an EOI to the master's
129                  * cascade irq (2). */
130                 pic_send_eoi(2 + PIC1_OFFSET);
131                 return TRUE;
132         }
133         return FALSE;
134 }
135
136 void pic_send_eoi(int trap_nr)
137 {
138         int irq = trap_nr - PIC1_OFFSET;
139         spin_lock_irqsave(&piclock);
140         // all irqs beyond the first seven need to be chained to the slave
141         if (irq > 7)
142                 outb(PIC2_CMD, PIC_EOI);
143         outb(PIC1_CMD, PIC_EOI);
144         spin_unlock_irqsave(&piclock);
145 }
146
147 bool lapic_check_spurious(int trap_nr)
148 {
149         /* FYI: lapic_spurious is 255 on qemu and 15 on the nehalem..  We actually
150          * can set bits 4-7, and P6s have 0-3 hardwired to 0.  YMMV.
151          *
152          * The SDM recommends not using the spurious vector for any other IRQs (LVT
153          * or IOAPIC RTE), since the handlers don't send an EOI.  However, our check
154          * here allows us to use the vector since we can tell the diff btw a
155          * spurious and a real IRQ. */
156         uint8_t lapic_spurious = read_mmreg32(LAPIC_SPURIOUS) & 0xff;
157         /* Note the lapic's vectors are not shifted by an offset. */
158         if ((trap_nr == lapic_spurious) && !lapic_get_isr_bit(lapic_spurious)) {
159                 /* i'm still curious about these */
160                 printk("Spurious LAPIC irq %d, core %d!\n", lapic_spurious, core_id());
161                 lapic_print_isr();
162                 return TRUE;
163         }
164         return FALSE;
165 }
166
167 /* Debugging helper.  Note the ISR/IRR are 32 bits at a time, spaced every 16
168  * bytes in the LAPIC address space. */
169 void lapic_print_isr(void)
170 {
171         printk("LAPIC ISR on core %d\n--------------\n", core_id());
172         for (int i = 7; i >= 0; i--)
173                 printk("%3d-%3d: %p\n", (i + 1) * 32 - 1, i * 32,
174                        *(uint32_t*)(LAPIC_ISR + i * 0x10));
175         printk("LAPIC IRR on core %d\n--------------\n", core_id());
176         for (int i = 7; i >= 0; i--)
177                 printk("%3d-%3d: %p\n", (i + 1) * 32 - 1, i * 32,
178                        *(uint32_t*)(LAPIC_IRR + i * 0x10));
179 }
180
181 /* Returns TRUE if the bit 'vector' is set in the LAPIC ISR or IRR (whatever you
182  * pass in.  These registers consist of 8, 32 byte registers spaced every 16
183  * bytes from the base in the LAPIC. */
184 static bool __lapic_get_isrr_bit(unsigned long base, uint8_t vector)
185 {
186         int which_reg = vector >> 5;    /* 32 bits per reg */
187         uint32_t *lapic_reg = (uint32_t*)(base + which_reg * 0x10);     /* offset 16 */
188         return (*lapic_reg & (1 << (vector % 32)) ? 1 : 0);
189 }
190
191 bool lapic_get_isr_bit(uint8_t vector)
192 {
193         return __lapic_get_isrr_bit(LAPIC_ISR, vector);
194 }
195
196 bool lapic_get_irr_bit(uint8_t vector)
197 {
198         return __lapic_get_isrr_bit(LAPIC_IRR, vector);
199 }
200
201 /* This works for any interrupt that goes through the LAPIC, but not things like
202  * ExtInts.  To prevent abuse, we'll use it just for IPIs for now (which only
203  * come via the APIC).
204  *
205  * We only check the ISR, due to how we send EOIs.  Since we don't send til
206  * after handlers return, the ISR will show pending for the current IRQ.  It is
207  * the EOI that clears the bit from the ISR. */
208 bool ipi_is_pending(uint8_t vector)
209 {
210         return lapic_get_isr_bit(vector);
211 }
212
213 /*
214  * Sets the LAPIC timer to go off after a certain number of ticks.  The primary
215  * clock freq is actually the bus clock, which we figure out during timer_init
216  * Unmasking is implied.  Ref SDM, 3A, 9.6.4
217  */
218 void __lapic_set_timer(uint32_t ticks, uint8_t vec, bool periodic, uint8_t div)
219 {
220 #ifdef CONFIG_LOUSY_LAPIC_TIMER
221         /* qemu without kvm seems to delay timer IRQs on occasion, and needs extra
222          * IRQs from any source to get them delivered.  periodic does the trick. */
223         periodic = TRUE;
224 #endif
225         // clears bottom bit and then set divider
226         write_mmreg32(LAPIC_TIMER_DIVIDE, (read_mmreg32(LAPIC_TIMER_DIVIDE) &~0xf) |
227                       (div & 0xf));
228         // set LVT with interrupt handling information
229         write_mmreg32(LAPIC_LVT_TIMER, vec | (periodic << 17));
230         write_mmreg32(LAPIC_TIMER_INIT, ticks);
231         // For debugging when we expand this
232         //cprintf("LAPIC LVT Timer: 0x%08x\n", read_mmreg32(LAPIC_LVT_TIMER));
233         //cprintf("LAPIC Init Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_INIT));
234         //cprintf("LAPIC Current Count: 0x%08x\n", read_mmreg32(LAPIC_TIMER_CURRENT));
235 }
236
237 void lapic_set_timer(uint32_t usec, bool periodic)
238 {
239         /* If we overflowed a uint32, send in the max timer possible.  The lapic can
240          * only handle a 32 bit.  We could muck with changing the divisor, but even
241          * then, we might not be able to match 4000 sec (based on the bus speed).
242          * The kernel alarm code can handle spurious timer interrupts, so we just
243          * set the timer for as close as we can get to the desired time. */
244         uint64_t ticks64 = (usec * system_timing.bus_freq) / LAPIC_TIMER_DIVISOR_VAL
245                             / 1000000;
246         uint32_t ticks32 = ((ticks64 >> 32) ? 0xffffffff : ticks64);
247         assert(ticks32 > 0);
248         __lapic_set_timer(ticks32, LAPIC_TIMER_DEFAULT_VECTOR, periodic,
249                           LAPIC_TIMER_DIVISOR_BITS);
250 }
251
252 void set_core_timer(uint32_t usec, bool periodic)
253 {
254         if (usec)
255                 lapic_set_timer(usec, periodic);
256         else
257                 lapic_disable_timer();
258 }
259
260 uint32_t lapic_get_default_id(void)
261 {
262         uint32_t ebx;
263         cpuid(0x1, 0x0, 0, &ebx, 0, 0);
264         // p6 family only uses 4 bits here, and 0xf is reserved for the IOAPIC
265         return (ebx & 0xFF000000) >> 24;
266 }
267
268 // timer init calibrates both tsc timer and lapic timer using PIT
269 void timer_init(void){
270         /* some boards have this unmasked early on. */
271         pic_mask_irq(0 + PIC1_OFFSET);
272         uint64_t tscval[2];
273         long timercount[2];
274         pit_set_timer(0xffff, TIMER_RATEGEN);
275         // assume tsc exist
276         tscval[0] = read_tsc();
277         udelay_pit(1000000);
278         tscval[1] = read_tsc();
279         system_timing.tsc_freq = SINIT(tscval[1] - tscval[0]);
280         cprintf("TSC Frequency: %llu\n", system_timing.tsc_freq);
281         __lapic_set_timer(0xffffffff, LAPIC_TIMER_DEFAULT_VECTOR, FALSE,
282                           LAPIC_TIMER_DIVISOR_BITS);
283         // Mask the LAPIC Timer, so we never receive this interrupt (minor race)
284         mask_lapic_lvt(LAPIC_LVT_TIMER);
285         timercount[0] = read_mmreg32(LAPIC_TIMER_CURRENT);
286         udelay_pit(1000000);
287         timercount[1] = read_mmreg32(LAPIC_TIMER_CURRENT);
288         system_timing.bus_freq = (timercount[0] - timercount[1])
289                                  * LAPIC_TIMER_DIVISOR_VAL;
290         /* The time base for the timer is derived from the processor's bus clock,
291          * divided by the value specified in the divide configuration register.
292          * Note we mult and div by the divisor, saving the actual freq (even though
293          * we don't use it yet). */
294         cprintf("Bus Frequency: %llu\n", system_timing.bus_freq);
295 }
296
297 void pit_set_timer(uint32_t divisor, uint32_t mode)
298 {
299         if (divisor & 0xffff0000)
300                 warn("Divisor too large!");
301         mode = TIMER_SEL0|TIMER_16BIT|mode;
302         outb(TIMER_MODE, mode); 
303         outb(TIMER_CNTR0, divisor & 0xff);
304         outb(TIMER_CNTR0, (divisor >> 8) );
305         system_timing.pit_mode = SINIT(mode);
306         system_timing.pit_divisor = SINIT(divisor);
307         // cprintf("timer mode set to %d, divisor %d\n",mode, divisor);
308 }
309
310 static int getpit()
311 {
312     int high, low;
313         // TODO: need a lock to protect access to PIT
314
315     /* Select counter 0 and latch counter value. */
316     outb(TIMER_MODE, TIMER_SEL0 | TIMER_LATCH);
317     
318     low = inb(TIMER_CNTR0);
319     high = inb(TIMER_CNTR0);
320
321     return ((high << 8) | low);
322 }
323
324 // forces cpu to relax for usec miliseconds.  declared in kern/include/time.h
325 void udelay(uint64_t usec)
326 {
327         #if !defined(__BOCHS__)
328         if (system_timing.tsc_freq != 0)
329         {
330                 uint64_t start, end, now;
331
332                 start = read_tsc();
333         end = start + usec2tsc(usec);
334         //cprintf("start %llu, end %llu\n", start, end);
335                 if (end == 0) cprintf("This is terribly wrong \n");
336                 do {
337             cpu_relax();
338             now = read_tsc();
339                         //cprintf("now %llu\n", now);
340                 } while (now < end || (now > start && end < start));
341         return;
342
343         } else
344         #endif
345         {
346                 udelay_pit(usec);
347         }
348 }
349
350 void udelay_pit(uint64_t usec)
351 {
352         
353         int64_t delta, prev_tick, tick, ticks_left;
354         prev_tick = getpit();
355         /*
356          * Calculate (n * (i8254_freq / 1e6)) without using floating point
357          * and without any avoidable overflows.
358          */
359         if (usec <= 0)
360                 ticks_left = 0;
361         // some optimization from bsd code
362         else if (usec < 256)
363                 /*
364                  * Use fixed point to avoid a slow division by 1000000.
365                  * 39099 = 1193182 * 2^15 / 10^6 rounded to nearest.
366                  * 2^15 is the first power of 2 that gives exact results
367                  * for n between 0 and 256.
368                  */
369                 ticks_left = ((uint64_t)usec * 39099 + (1 << 15) - 1) >> 15;
370         else
371                 // round up the ticks left
372                 ticks_left = ((uint64_t)usec * (long long)PIT_FREQ+ 999999)
373                              / 1000000; 
374         while (ticks_left > 0) {
375                 tick = getpit();
376                 delta = prev_tick - tick;
377                 prev_tick = tick;
378                 if (delta < 0) {
379                         // counter looped around during the delta time period
380                         delta += system_timing.pit_divisor; // maximum count 
381                         if (delta < 0)
382                                 delta = 0;
383                 }
384                 ticks_left -= delta;
385         }
386 }
387
388 uint64_t gettimer(void)
389 {
390         return read_tsc();      
391 }
392
393 uint64_t getfreq(void)
394 {
395         return system_timing.tsc_freq;
396 }