xref: /xv6-public/trap.c (revision c1b100e9)
1 #include "types.h"
2 #include "defs.h"
3 #include "param.h"
4 #include "mmu.h"
5 #include "proc.h"
6 #include "x86.h"
7 #include "traps.h"
8 #include "spinlock.h"
9 
10 // Interrupt descriptor table (shared by all CPUs).
11 struct gatedesc idt[256];
12 extern uint vectors[];  // in vectors.S: array of 256 entry pointers
13 struct spinlock tickslock;
14 int ticks;
15 
16 void
17 tvinit(void)
18 {
19   int i;
20 
21   for(i = 0; i < 256; i++)
22     SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
23   SETGATE(idt[T_SYSCALL], 0, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER);
24 
25   initlock(&tickslock, "time");
26 }
27 
28 void
29 idtinit(void)
30 {
31   lidt(idt, sizeof(idt));
32 }
33 
34 void
35 trap(struct trapframe *tf)
36 {
37   if(tf->trapno == T_SYSCALL){
38     if(cp->killed)
39       proc_exit();
40     cp->tf = tf;
41     syscall();
42     if(cp->killed)
43       proc_exit();
44     return;
45   }
46 
47   // Increment nlock to make sure interrupts stay off
48   // during interrupt handler.  Decrement before returning.
49   cpus[cpu()].nlock++;
50 
51   switch(tf->trapno){
52   case IRQ_OFFSET + IRQ_TIMER:
53     if(cpu() == 0){
54       acquire(&tickslock);
55       ticks++;
56       wakeup(&ticks);
57       release(&tickslock);
58     }
59     lapic_eoi();
60     break;
61   case IRQ_OFFSET + IRQ_IDE:
62     ide_intr();
63     lapic_eoi();
64     break;
65   case IRQ_OFFSET + IRQ_KBD:
66     kbd_intr();
67     lapic_eoi();
68     break;
69   case IRQ_OFFSET + IRQ_SPURIOUS:
70     cprintf("spurious interrupt from cpu %d eip %x\n", cpu(), tf->eip);
71     lapic_eoi();
72     break;
73 
74   default:
75     if(cp == 0) {
76       // Otherwise it's our mistake.
77       cprintf("unexpected trap %d from cpu %d eip %x\n",
78               tf->trapno, cpu(), tf->eip);
79       panic("trap");
80     }
81     // Assume process divided by zero or dereferenced null, etc.
82     cprintf("pid %d %s: trap %d err %d on cpu %d eip %x -- kill proc\n",
83             cp->pid, cp->name, tf->trapno, tf->err, cpu(), tf->eip);
84     cp->killed = 1;
85   }
86   cpus[cpu()].nlock--;
87 
88   // Force process exit if it has been killed and is in user space.
89   // (If it is still executing in the kernel, let it keep running
90   // until it gets to the regular system call return.)
91   if(cp && cp->killed && (tf->cs&3) == DPL_USER)
92     proc_exit();
93 
94   // Force process to give up CPU on clock tick.
95   // If interrupts were on while locks held, would need to check nlock.
96   if(cp && cp->state == RUNNING && tf->trapno == IRQ_OFFSET+IRQ_TIMER)
97     yield();
98 }
99