usb.patch, with conflicts and some warnings fixed
[pintos-anon] / src / threads / interrupt.c
1 #include "threads/interrupt.h"
2 #include <debug.h>
3 #include <inttypes.h>
4 #include <stdint.h>
5 #include <stdio.h>
6 #include "threads/flags.h"
7 #include "threads/intr-stubs.h"
8 #include "threads/io.h"
9 #include "threads/thread.h"
10 #include "threads/vaddr.h"
11 #include "devices/timer.h"
12
13 /* Programmable Interrupt Controller (PIC) registers.
14    A PC has two PICs, called the master and slave PICs, with the
15    slave attached ("cascaded") to the master IRQ line 2. */
16 #define PIC0_CTRL       0x20    /* Master PIC control register address. */
17 #define PIC0_DATA       0x21    /* Master PIC data register address. */
18 #define PIC1_CTRL       0xa0    /* Slave PIC control register address. */
19 #define PIC1_DATA       0xa1    /* Slave PIC data register address. */
20 #define IRQ_CASCADE0   2
21 #define IRQ_CASCADE1   9
22
23 /* Number of x86 interrupts. */
24 #define INTR_CNT 256
25
26 /* The Interrupt Descriptor Table (IDT).  The format is fixed by
27    the CPU.  See [IA32-v3a] sections 5.10 "Interrupt Descriptor
28    Table (IDT)", 5.11 "IDT Descriptors", 5.12.1.2 "Flag Usage By
29    Exception- or Interrupt-Handler Procedure". */
30 static uint64_t idt[INTR_CNT];
31
32 /* Interrupt handler functions for each interrupt. */
33 static intr_handler_func *intr_handlers[INTR_CNT];
34
35 /* Names for each interrupt, for debugging purposes. */
36 static const char *intr_names[INTR_CNT];
37
38 /* cached values for PIC */
39 static uint8_t pic_mask[2];
40
41 /* External interrupts are those generated by devices outside the
42    CPU, such as the timer.  External interrupts run with
43    interrupts turned off, so they never nest, nor are they ever
44    pre-empted.  Handlers for external interrupts also may not
45    sleep, although they may invoke intr_yield_on_return() to
46    request that a new process be scheduled just before the
47    interrupt returns. */
48 static bool in_external_intr;   /* Are we processing an external interrupt? */
49 static bool yield_on_return;    /* Should we yield on interrupt return? */
50
51 /* Programmable Interrupt Controller helpers. */
52 static void pic_init (void);
53 static void pic_end_of_interrupt (int irq);
54
55 /* Interrupt Descriptor Table helpers. */
56 static uint64_t make_intr_gate (void (*) (void), int dpl);
57 static uint64_t make_trap_gate (void (*) (void), int dpl);
58 static inline uint64_t make_idtr_operand (uint16_t limit, void *base);
59
60 /* Interrupt handlers. */
61 void intr_handler (struct intr_frame *args);
62 \f
63 /* Returns the current interrupt status. */
64 enum intr_level
65 intr_get_level (void) 
66 {
67   uint32_t flags;
68
69   /* Push the flags register on the processor stack, then pop the
70      value off the stack into `flags'.  See [IA32-v2b] "PUSHF"
71      and "POP" and [IA32-v3a] 5.8.1 "Masking Maskable Hardware
72      Interrupts". */
73   asm volatile ("pushfl; popl %0" : "=g" (flags));
74
75   return flags & FLAG_IF ? INTR_ON : INTR_OFF;
76 }
77
78 /* Enables or disables interrupts as specified by LEVEL and
79    returns the previous interrupt status. */
80 enum intr_level
81 intr_set_level (enum intr_level level) 
82 {
83   return level == INTR_ON ? intr_enable () : intr_disable ();
84 }
85
86 /* Enables interrupts and returns the previous interrupt status. */
87 enum intr_level
88 intr_enable (void) 
89 {
90   enum intr_level old_level = intr_get_level ();
91   ASSERT (!intr_context ());
92
93   /* Enable interrupts by setting the interrupt flag.
94
95      See [IA32-v2b] "STI" and [IA32-v3a] 5.8.1 "Masking Maskable
96      Hardware Interrupts". */
97   asm volatile ("sti");
98
99   return old_level;
100 }
101
102 /* Disables interrupts and returns the previous interrupt status. */
103 enum intr_level
104 intr_disable (void) 
105 {
106   enum intr_level old_level = intr_get_level ();
107
108   /* Disable interrupts by clearing the interrupt flag.
109      See [IA32-v2b] "CLI" and [IA32-v3a] 5.8.1 "Masking Maskable
110      Hardware Interrupts". */
111   asm volatile ("cli" : : : "memory");
112
113   return old_level;
114 }
115 \f
116 /* Initializes the interrupt system. */
117 void
118 intr_init (void)
119 {
120   uint64_t idtr_operand;
121   int i;
122
123   /* Initialize interrupt controller. */
124   pic_init ();
125
126   /* Initialize IDT. */
127   for (i = 0; i < INTR_CNT; i++)
128     idt[i] = make_intr_gate (intr_stubs[i], 0);
129
130   /* Load IDT register.
131      See [IA32-v2a] "LIDT" and [IA32-v3a] 5.10 "Interrupt
132      Descriptor Table (IDT)". */
133   idtr_operand = make_idtr_operand (sizeof idt - 1, idt);
134   asm volatile ("lidt %0" : : "m" (idtr_operand));
135
136   /* Initialize intr_names. */
137   for (i = 0; i < INTR_CNT; i++)
138     intr_names[i] = "unknown";
139   intr_names[0] = "#DE Divide Error";
140   intr_names[1] = "#DB Debug Exception";
141   intr_names[2] = "NMI Interrupt";
142   intr_names[3] = "#BP Breakpoint Exception";
143   intr_names[4] = "#OF Overflow Exception";
144   intr_names[5] = "#BR BOUND Range Exceeded Exception";
145   intr_names[6] = "#UD Invalid Opcode Exception";
146   intr_names[7] = "#NM Device Not Available Exception";
147   intr_names[8] = "#DF Double Fault Exception";
148   intr_names[9] = "Coprocessor Segment Overrun";
149   intr_names[10] = "#TS Invalid TSS Exception";
150   intr_names[11] = "#NP Segment Not Present";
151   intr_names[12] = "#SS Stack Fault Exception";
152   intr_names[13] = "#GP General Protection Exception";
153   intr_names[14] = "#PF Page-Fault Exception";
154   intr_names[16] = "#MF x87 FPU Floating-Point Error";
155   intr_names[17] = "#AC Alignment Check Exception";
156   intr_names[18] = "#MC Machine-Check Exception";
157   intr_names[19] = "#XF SIMD Floating-Point Exception";
158 }
159
160 /* Registers interrupt VEC_NO to invoke HANDLER with descriptor
161    privilege level DPL.  Names the interrupt NAME for debugging
162    purposes.  The interrupt handler will be invoked with
163    interrupt status set to LEVEL. */
164 static void
165 register_handler (uint8_t vec_no, int dpl, enum intr_level level,
166                   intr_handler_func *handler, const char *name)
167 {
168   ASSERT (intr_handlers[vec_no] == NULL);
169   if (level == INTR_ON)
170     idt[vec_no] = make_trap_gate (intr_stubs[vec_no], dpl);
171   else
172     idt[vec_no] = make_intr_gate (intr_stubs[vec_no], dpl);
173   intr_handlers[vec_no] = handler;
174   intr_names[vec_no] = name;
175 }
176
177 /* Registers external interrupt VEC_NO to invoke HANDLER, which
178    is named NAME for debugging purposes.  The handler will
179    execute with interrupts disabled. */
180 void
181 intr_register_ext (uint8_t vec_no, intr_handler_func *handler,
182                    const char *name) 
183 {
184   ASSERT (vec_no >= 0x20 && vec_no <= 0x2f);
185   register_handler (vec_no, 0, INTR_OFF, handler, name);
186 }
187
188 /* Registers internal interrupt VEC_NO to invoke HANDLER, which
189    is named NAME for debugging purposes.  The interrupt handler
190    will be invoked with interrupt status LEVEL.
191
192    The handler will have descriptor privilege level DPL, meaning
193    that it can be invoked intentionally when the processor is in
194    the DPL or lower-numbered ring.  In practice, DPL==3 allows
195    user mode to invoke the interrupts and DPL==0 prevents such
196    invocation.  Faults and exceptions that occur in user mode
197    still cause interrupts with DPL==0 to be invoked.  See
198    [IA32-v3a] sections 4.5 "Privilege Levels" and 4.8.1.1
199    "Accessing Nonconforming Code Segments" for further
200    discussion. */
201 void
202 intr_register_int (uint8_t vec_no, int dpl, enum intr_level level,
203                    intr_handler_func *handler, const char *name)
204 {
205   ASSERT (vec_no < 0x20 || vec_no > 0x2f);
206   register_handler (vec_no, dpl, level, handler, name);
207 }
208
209 /* Returns true during processing of an external interrupt
210    and false at all other times. */
211 bool
212 intr_context (void) 
213 {
214   return in_external_intr;
215 }
216
217 /* During processing of an external interrupt, directs the
218    interrupt handler to yield to a new process just before
219    returning from the interrupt.  May not be called at any other
220    time. */
221 void
222 intr_yield_on_return (void) 
223 {
224   ASSERT (intr_context ());
225   yield_on_return = true;
226 }
227 \f
228 /* 8259A Programmable Interrupt Controller. */
229
230 /* Initializes the PICs.  Refer to [8259A] for details.
231
232    By default, interrupts 0...15 delivered by the PICs will go to
233    interrupt vectors 0...15.  Those vectors are also used for CPU
234    traps and exceptions, so we reprogram the PICs so that
235    interrupts 0...15 are delivered to interrupt vectors 32...47
236    (0x20...0x2f) instead. */
237 static void
238 pic_init (void)
239 {
240   /* Mask all interrupts on both PICs. */
241   outb (PIC0_DATA, 0xff);
242   outb (PIC1_DATA, 0xff);
243
244   /* Initialize master. */
245   outb (PIC0_CTRL, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */
246   outb (PIC0_DATA, 0x20); /* ICW2: line IR0...7 -> irq 0x20...0x27. */
247   outb (PIC0_DATA, 0x04); /* ICW3: slave PIC on line IR2. */
248   outb (PIC0_DATA, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */
249
250   /* Initialize slave. */
251   outb (PIC1_CTRL, 0x11); /* ICW1: single mode, edge triggered, expect ICW4. */
252   outb (PIC1_DATA, 0x28); /* ICW2: line IR0...7 -> irq 0x28...0x2f. */
253   outb (PIC1_DATA, 0x02); /* ICW3: slave ID is 2. */
254   outb (PIC1_DATA, 0x01); /* ICW4: 8086 mode, normal EOI, non-buffered. */
255
256   /* Unmask all interrupts. */
257   outb (PIC0_DATA, 0x00);
258   outb (PIC1_DATA, 0x00);
259   pic_mask[0] = 0;
260   pic_mask[1] = 0;
261 }
262
263 /* Sends an end-of-interrupt signal to the PIC for the given IRQ.
264    If we don't acknowledge the IRQ, it will never be delivered to
265    us again, so this is important.  */
266 static void
267 pic_end_of_interrupt (int irq) 
268 {
269   ASSERT (irq >= 0x20 && irq < 0x30);
270
271   /* Acknowledge master PIC. */
272   outb (0x20, 0x20);
273
274   /* Acknowledge slave PIC if this is a slave interrupt. */
275   if (irq >= 0x28)
276     outb (0xa0, 0x20);
277 }
278 \f
279 /* Creates an gate that invokes FUNCTION.
280
281    The gate has descriptor privilege level DPL, meaning that it
282    can be invoked intentionally when the processor is in the DPL
283    or lower-numbered ring.  In practice, DPL==3 allows user mode
284    to call into the gate and DPL==0 prevents such calls.  Faults
285    and exceptions that occur in user mode still cause gates with
286    DPL==0 to be invoked.  See [IA32-v3a] sections 4.5 "Privilege
287    Levels" and 4.8.1.1 "Accessing Nonconforming Code Segments"
288    for further discussion.
289
290    TYPE must be either 14 (for an interrupt gate) or 15 (for a
291    trap gate).  The difference is that entering an interrupt gate
292    disables interrupts, but entering a trap gate does not.  See
293    [IA32-v3a] section 5.12.1.2 "Flag Usage By Exception- or
294    Interrupt-Handler Procedure" for discussion. */
295 static uint64_t
296 make_gate (void (*function) (void), int dpl, int type)
297 {
298   uint32_t e0, e1;
299
300   ASSERT (function != NULL);
301   ASSERT (dpl >= 0 && dpl <= 3);
302   ASSERT (type >= 0 && type <= 15);
303
304   e0 = (((uint32_t) function & 0xffff)     /* Offset 15:0. */
305         | (SEL_KCSEG << 16));              /* Target code segment. */
306
307   e1 = (((uint32_t) function & 0xffff0000) /* Offset 31:16. */
308         | (1 << 15)                        /* Present. */
309         | ((uint32_t) dpl << 13)           /* Descriptor privilege level. */
310         | (0 << 12)                        /* System. */
311         | ((uint32_t) type << 8));         /* Gate type. */
312
313   return e0 | ((uint64_t) e1 << 32);
314 }
315
316 /* Creates an interrupt gate that invokes FUNCTION with the given
317    DPL. */
318 static uint64_t
319 make_intr_gate (void (*function) (void), int dpl)
320 {
321   return make_gate (function, dpl, 14);
322 }
323
324 /* Creates a trap gate that invokes FUNCTION with the given
325    DPL. */
326 static uint64_t
327 make_trap_gate (void (*function) (void), int dpl)
328 {
329   return make_gate (function, dpl, 15);
330 }
331
332 /* Returns a descriptor that yields the given LIMIT and BASE when
333    used as an operand for the LIDT instruction. */
334 static inline uint64_t
335 make_idtr_operand (uint16_t limit, void *base)
336 {
337   return limit | ((uint64_t) (uint32_t) base << 16);
338 }
339 \f
340 /* Interrupt handlers. */
341
342 /* Handler for all interrupts, faults, and exceptions.  This
343    function is called by the assembly language interrupt stubs in
344    intr-stubs.S.  FRAME describes the interrupt and the
345    interrupted thread's registers. */
346 void
347 intr_handler (struct intr_frame *frame) 
348 {
349   bool external;
350   intr_handler_func *handler;
351
352   /* External interrupts are special.
353      We only handle one at a time (so interrupts must be off)
354      and they need to be acknowledged on the PIC (see below).
355      An external interrupt handler cannot sleep. */
356   external = frame->vec_no >= 0x20 && frame->vec_no < 0x30;
357   if (external) 
358     {
359       ASSERT (intr_get_level () == INTR_OFF);
360       ASSERT (!intr_context ());
361
362       in_external_intr = true;
363       yield_on_return = false;
364     }
365
366   /* Invoke the interrupt's handler. */
367   handler = intr_handlers[frame->vec_no];
368   if (handler != NULL)
369     handler (frame);
370   else if (frame->vec_no == 0x27 || frame->vec_no == 0x2f)
371     {
372       /* There is no handler, but this interrupt can trigger
373          spuriously due to a hardware fault or hardware race
374          condition.  Ignore it. */
375     }
376   else 
377     {
378       /* No handler and not spurious.  Invoke the unexpected
379          interrupt handler. */
380       intr_dump_frame (frame);
381       PANIC ("Unexpected interrupt"); 
382     }
383
384   /* Complete the processing of an external interrupt. */
385   if (external) 
386     {
387       ASSERT (intr_get_level () == INTR_OFF);
388       ASSERT (intr_context ());
389
390       in_external_intr = false;
391       pic_end_of_interrupt (frame->vec_no); 
392
393       if (yield_on_return) 
394         thread_yield (); 
395     }
396 }
397
398 /* Dumps interrupt frame F to the console, for debugging. */
399 void
400 intr_dump_frame (const struct intr_frame *f) 
401 {
402   uint32_t cr2;
403
404   /* Store current value of CR2 into `cr2'.
405      CR2 is the linear address of the last page fault.
406      See [IA32-v2a] "MOV--Move to/from Control Registers" and
407      [IA32-v3a] 5.14 "Interrupt 14--Page Fault Exception
408      (#PF)". */
409   asm ("movl %%cr2, %0" : "=r" (cr2));
410
411   printf ("Interrupt %#04x (%s) at eip=%p\n",
412           f->vec_no, intr_names[f->vec_no], f->eip);
413   printf (" cr2=%08"PRIx32" error=%08"PRIx32"\n", cr2, f->error_code);
414   printf (" eax=%08"PRIx32" ebx=%08"PRIx32" ecx=%08"PRIx32" edx=%08"PRIx32"\n",
415           f->eax, f->ebx, f->ecx, f->edx);
416   printf (" esi=%08"PRIx32" edi=%08"PRIx32" esp=%08"PRIx32" ebp=%08"PRIx32"\n",
417           f->esi, f->edi, (uint32_t) f->esp, f->ebp);
418   printf (" cs=%04"PRIx16" ds=%04"PRIx16" es=%04"PRIx16" ss=%04"PRIx16"\n",
419           f->cs, f->ds, f->es, f->ss);
420 }
421
422 /* Returns the name of interrupt VEC. */
423 const char *
424 intr_name (uint8_t vec) 
425 {
426   return intr_names[vec];
427 }
428
429 /** masks a given IRQ */
430 void intr_irq_mask(int irq)
431 {
432        if(irq < 8){
433                pic_mask[0] |= 1 << irq;
434                outb (PIC0_DATA, pic_mask[0]);
435        }else{  
436                pic_mask[1] |= 1 << (irq - 8);
437                outb (PIC1_DATA, pic_mask[1]);
438        }
439 }
440
441 /** unmasks a given IRQ */
442 void intr_irq_unmask(int irq)
443 {
444        if(irq >= 8){
445                /* enable cascade if not enabled for pic2 */
446                if(pic_mask[1] & (1 << (IRQ_CASCADE1 - 8)))
447                        pic_mask[1] &= ~(1 << (IRQ_CASCADE1 - 8));
448
449                pic_mask[1] &= ~(1 << (irq - 8));
450                outb(PIC1_DATA, pic_mask[1]);
451
452                /* enable cascade if not enabled for pic1 */
453                if(pic_mask[0] & (1 << IRQ_CASCADE0))
454                        irq = IRQ_CASCADE0;
455        }
456
457        if(irq < 8){
458                pic_mask[0] &= ~(1 << irq);
459                outb (PIC0_DATA, pic_mask[0]);
460        }
461
462 }
463
464 /* return whether an interrupt vector is registered */
465 bool intr_is_registered(uint8_t vec_no)
466 {
467        return (intr_handlers[vec_no] != NULL);
468 }