xref: /xv6-public/trap.c (revision 5be0039c)
1 #include "types.h"
2 #include "param.h"
3 #include "mmu.h"
4 #include "proc.h"
5 #include "defs.h"
6 #include "x86.h"
7 #include "traps.h"
8 #include "syscall.h"
9 
10 struct gatedesc idt[256];
11 extern uint vectors[]; /* vectors.S, array of 256 entry point addresses */
12 
13 extern void trapenter(void);
14 extern void trapenter1(void);
15 
16 void
17 tvinit(void)
18 {
19   int i;
20 
21   for(i = 0; i < 256; i++){
22     SETGATE(idt[i], 1, SEG_KCODE << 3, vectors[i], 0);
23   }
24   SETGATE(idt[T_SYSCALL], 1, SEG_KCODE << 3, vectors[48], 3);
25 }
26 
27 void
28 idtinit(void)
29 {
30   lidt(idt, sizeof idt);
31 }
32 
33 void
34 trap(struct trapframe *tf)
35 {
36   int v = tf->trapno;
37 
38   if(cpus[cpu()].nlock){
39     cprintf("trap v %d eip %x cpu %d nlock %d\n",
40             v, tf->eip, cpu(), cpus[cpu()].nlock);
41     panic("interrupt while holding a lock");
42   }
43 
44   if(cpu() == 1 && curproc[cpu()] == 0){
45     if(&tf < cpus[cpu()].mpstack || &tf > cpus[cpu()].mpstack + 512){
46       cprintf("&tf %x mpstack %x\n", &tf, cpus[cpu()].mpstack);
47       panic("trap cpu stack");
48     }
49   } else if(curproc[cpu()]){
50     if(&tf < curproc[cpu()]->kstack){
51       panic("trap kstack");
52     }
53   }
54 
55   if(v == T_SYSCALL){
56     struct proc *cp = curproc[cpu()];
57     int num = cp->tf->eax;
58     if((read_eflags() & FL_IF) == 0)
59       panic("syscall but interrupts now disabled");
60     if(cp == 0)
61       panic("syscall with no proc");
62     if(cp->killed)
63       proc_exit();
64     cp->tf = tf;
65     syscall();
66     if(cp != curproc[cpu()])
67       panic("trap ret wrong curproc");
68     if(cp->state != RUNNING)
69       panic("trap ret but not RUNNING");
70     if(tf != cp->tf)
71       panic("trap ret wrong tf");
72     if(cpus[cpu()].nlock){
73       cprintf("num=%d\n", num);
74       panic("syscall returning locks held");
75     }
76     if((read_eflags() & FL_IF) == 0)
77       panic("syscall returning but FL_IF clear");
78     if(read_esp() < (uint)cp->kstack ||
79        read_esp() >= (uint)cp->kstack + KSTACKSIZE)
80       panic("trap ret esp wrong");
81     if(cp->killed)
82       proc_exit();
83     // XXX probably ought to lgdt on trap return
84     return;
85   }
86 
87   //if(read_eflags() & FL_IF)
88   //panic("interrupt but interrupts enabled");
89 
90   if(v == (IRQ_OFFSET + IRQ_TIMER)){
91     struct proc *cp = curproc[cpu()];
92     lapic_timerintr();
93     if(cp){
94       // Force process exit if it has been killed
95       // and the interrupt came from user space.
96       // (If the kernel was executing at time of interrupt,
97       // don't kill the process.  Let the process get back
98       // out to its regular system call return.)
99       if((tf->cs&3) == 3 && cp->killed)
100         proc_exit();
101 
102       // Force process to give up CPU and let others run.
103       if(cp->state == RUNNING)
104         yield();
105     }
106     return;
107   }
108 
109   if(v == (IRQ_OFFSET + IRQ_IDE)){
110     ide_intr();
111     if(cpus[cpu()].nlock)
112       panic("ide_intr returned while holding a lock");
113     cli(); // prevent a waiting interrupt from overflowing stack
114     lapic_eoi();
115     return;
116   }
117 
118   if(v == (IRQ_OFFSET + IRQ_KBD)){
119     kbd_intr();
120     if(cpus[cpu()].nlock){
121       panic("kbd_intr returned while holding a lock");
122     }
123     cli(); // prevent a waiting interrupt from overflowing stack
124     lapic_eoi();
125     return;
126   }
127 
128   cprintf("trap %d\n", v);
129 
130   return;
131 }
132