xref: /xv6-public/trap.c (revision 5efca905)
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 uint 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], 1, 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 //PAGEBREAK: 41
35 void
36 trap(struct trapframe *tf)
37 {
38   if(tf->trapno == T_SYSCALL){
39     if(proc->killed)
40       exit();
41     proc->tf = tf;
42     syscall();
43     if(proc->killed)
44       exit();
45     return;
46   }
47 
48   switch(tf->trapno){
49   case T_IRQ0 + IRQ_TIMER:
50     if(cpu->id == 0){
51       acquire(&tickslock);
52       ticks++;
53       wakeup(&ticks);
54       release(&tickslock);
55     }
56     lapiceoi();
57     break;
58   case T_IRQ0 + IRQ_IDE:
59     ideintr();
60     lapiceoi();
61     break;
62   case T_IRQ0 + IRQ_KBD:
63     kbdintr();
64     lapiceoi();
65     break;
66   case T_IRQ0 + IRQ_COM1:
67     uartintr();
68     lapiceoi();
69     break;
70   case T_IRQ0 + 7:
71   case T_IRQ0 + IRQ_SPURIOUS:
72     cprintf("cpu%d: spurious interrupt at %x:%x\n",
73             cpu->id, tf->cs, tf->eip);
74     lapiceoi();
75     break;
76 
77   //PAGEBREAK: 13
78   default:
79     if(proc == 0 || (tf->cs&3) == 0){
80       // In kernel, it must be our mistake.
81       cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
82               tf->trapno, cpu->id, tf->eip, rcr2());
83       panic("trap");
84     }
85     // In user space, assume process misbehaved.
86     cprintf("pid %d %s: trap %d err %d on cpu %d "
87             "eip 0x%x addr 0x%x--kill proc\n",
88             proc->pid, proc->name, tf->trapno, tf->err, cpu->id, tf->eip,
89             rcr2());
90     proc->killed = 1;
91   }
92 
93   // Force process exit if it has been killed and is in user space.
94   // (If it is still executing in the kernel, let it keep running
95   // until it gets to the regular system call return.)
96   if(proc && proc->killed && (tf->cs&3) == DPL_USER)
97     exit();
98 
99   // Force process to give up CPU on clock tick.
100   // If interrupts were on while locks held, would need to check nlock.
101   if(proc && proc->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER)
102     yield();
103 
104   // Check if the process has been killed since we yielded
105   if(proc && proc->killed && (tf->cs&3) == DPL_USER)
106     exit();
107 }
108