xref: /xv6-public/trap.c (revision 4638cabf)
184eb544bSrtm #include "types.h"
2558ab49fSrsc #include "defs.h"
384eb544bSrtm #include "param.h"
49aa0337dSFrans Kaashoek #include "memlayout.h"
584eb544bSrtm #include "mmu.h"
684eb544bSrtm #include "proc.h"
784eb544bSrtm #include "x86.h"
8a4c03deaSrtm #include "traps.h"
9efc12b8eSrsc #include "spinlock.h"
1084eb544bSrtm 
1131085bb4Srsc // Interrupt descriptor table (shared by all CPUs).
12b5f17007Srsc struct gatedesc idt[256];
130cfc7290Srsc extern uint vectors[];  // in vectors.S: array of 256 entry pointers
14efc12b8eSrsc struct spinlock tickslock;
15789b508dSRobert Morris uint ticks;
1684eb544bSrtm 
1784eb544bSrtm void
tvinit(void)18c54c7926Srsc tvinit(void)
1984eb544bSrtm {
2084eb544bSrtm   int i;
2184eb544bSrtm 
220b75a8e8Srsc   for(i = 0; i < 256; i++)
230b75a8e8Srsc     SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0);
24af7366c9Srsc   SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER);
25efc12b8eSrsc 
26efc12b8eSrsc   initlock(&tickslock, "time");
27b61c2547Srtm }
28b61c2547Srtm 
29b61c2547Srtm void
idtinit(void)30c54c7926Srsc idtinit(void)
31b61c2547Srtm {
32eaea18cbSrsc   lidt(idt, sizeof(idt));
3384eb544bSrtm }
3484eb544bSrtm 
350aef8914SRuss Cox //PAGEBREAK: 41
3684eb544bSrtm void
trap(struct trapframe * tf)37b5f17007Srsc trap(struct trapframe *tf)
3884eb544bSrtm {
39dca5b5caSrsc   if(tf->trapno == T_SYSCALL){
40abf847a0SFrans Kaashoek     if(myproc()->killed)
415573c8f2Srsc       exit();
42abf847a0SFrans Kaashoek     myproc()->tf = tf;
43a4c03deaSrtm     syscall();
44abf847a0SFrans Kaashoek     if(myproc()->killed)
455573c8f2Srsc       exit();
46a4c03deaSrtm     return;
47a4c03deaSrtm   }
48a4c03deaSrtm 
49dca5b5caSrsc   switch(tf->trapno){
508b75366cSRuss Cox   case T_IRQ0 + IRQ_TIMER:
51abf847a0SFrans Kaashoek     if(cpuid() == 0){
52efc12b8eSrsc       acquire(&tickslock);
53efc12b8eSrsc       ticks++;
54efc12b8eSrsc       wakeup(&ticks);
55efc12b8eSrsc       release(&tickslock);
56b548df15Srtm     }
5721575761Srsc     lapiceoi();
58efc12b8eSrsc     break;
598b75366cSRuss Cox   case T_IRQ0 + IRQ_IDE:
6021575761Srsc     ideintr();
6121575761Srsc     lapiceoi();
620b75a8e8Srsc     break;
63cf4b1ad9SRuss Cox   case T_IRQ0 + IRQ_IDE+1:
64cf4b1ad9SRuss Cox     // Bochs generates spurious IDE1 interrupts.
65cf4b1ad9SRuss Cox     break;
668b75366cSRuss Cox   case T_IRQ0 + IRQ_KBD:
6721575761Srsc     kbdintr();
6821575761Srsc     lapiceoi();
690b75a8e8Srsc     break;
708b75366cSRuss Cox   case T_IRQ0 + IRQ_COM1:
7174afa70dSrsc     uartintr();
7274afa70dSrsc     lapiceoi();
7374afa70dSrsc     break;
748b75366cSRuss Cox   case T_IRQ0 + 7:
758b75366cSRuss Cox   case T_IRQ0 + IRQ_SPURIOUS:
76fbaa7b42Srsc     cprintf("cpu%d: spurious interrupt at %x:%x\n",
77abf847a0SFrans Kaashoek             cpuid(), tf->cs, tf->eip);
7821575761Srsc     lapiceoi();
790b75a8e8Srsc     break;
8097c74a3aSkaashoek 
81c9ee77b8SRuss Cox   //PAGEBREAK: 13
820b75a8e8Srsc   default:
83abf847a0SFrans Kaashoek     if(myproc() == 0 || (tf->cs&3) == 0){
84fbaa7b42Srsc       // In kernel, it must be our mistake.
8540889627SFrans Kaashoek       cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n",
86abf847a0SFrans Kaashoek               tf->trapno, cpuid(), tf->eip, rcr2());
8797c74a3aSkaashoek       panic("trap");
8884eb544bSrtm     }
89fbaa7b42Srsc     // In user space, assume process misbehaved.
907472b2b4SAustin Clements     cprintf("pid %d %s: trap %d err %d on cpu %d "
917472b2b4SAustin Clements             "eip 0x%x addr 0x%x--kill proc\n",
92*4638cabfSRobert Morris             myproc()->pid, myproc()->name, tf->trapno,
93*4638cabfSRobert Morris             tf->err, cpuid(), tf->eip, rcr2());
94abf847a0SFrans Kaashoek     myproc()->killed = 1;
954c917f6dSrsc   }
96fbaa7b42Srsc 
97efc12b8eSrsc   // Force process exit if it has been killed and is in user space.
98efc12b8eSrsc   // (If it is still executing in the kernel, let it keep running
99efc12b8eSrsc   // until it gets to the regular system call return.)
100abf847a0SFrans Kaashoek   if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
1015573c8f2Srsc     exit();
102efc12b8eSrsc 
1034c917f6dSrsc   // Force process to give up CPU on clock tick.
1044c917f6dSrsc   // If interrupts were on while locks held, would need to check nlock.
105*4638cabfSRobert Morris   if(myproc() && myproc()->state == RUNNING &&
106*4638cabfSRobert Morris      tf->trapno == T_IRQ0+IRQ_TIMER)
107efc12b8eSrsc     yield();
10815ce79deSkolya 
10915ce79deSkolya   // Check if the process has been killed since we yielded
110abf847a0SFrans Kaashoek   if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER)
11115ce79deSkolya     exit();
112efc12b8eSrsc }
113