1 #include "types.h" 2 #include "defs.h" 3 #include "param.h" 4 #include "memlayout.h" 5 #include "mmu.h" 6 #include "proc.h" 7 #include "x86.h" 8 #include "traps.h" 9 #include "spinlock.h" 10 11 // Interrupt descriptor table (shared by all CPUs). 12 struct gatedesc idt[256]; 13 extern uint vectors[]; // in vectors.S: array of 256 entry pointers 14 struct spinlock tickslock; 15 uint ticks; 16 17 void 18 tvinit(void) 19 { 20 int i; 21 22 for(i = 0; i < 256; i++) 23 SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); 24 SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER); 25 26 initlock(&tickslock, "time"); 27 } 28 29 void 30 idtinit(void) 31 { 32 lidt(idt, sizeof(idt)); 33 } 34 35 //PAGEBREAK: 41 36 void 37 trap(struct trapframe *tf) 38 { 39 if(tf->trapno == T_SYSCALL){ 40 if(myproc()->killed) 41 exit(); 42 myproc()->tf = tf; 43 syscall(); 44 if(myproc()->killed) 45 exit(); 46 return; 47 } 48 49 switch(tf->trapno){ 50 case T_IRQ0 + IRQ_TIMER: 51 if(cpuid() == 0){ 52 acquire(&tickslock); 53 ticks++; 54 wakeup(&ticks); 55 release(&tickslock); 56 } 57 lapiceoi(); 58 break; 59 case T_IRQ0 + IRQ_IDE: 60 ideintr(); 61 lapiceoi(); 62 break; 63 case T_IRQ0 + IRQ_IDE+1: 64 // Bochs generates spurious IDE1 interrupts. 65 break; 66 case T_IRQ0 + IRQ_KBD: 67 kbdintr(); 68 lapiceoi(); 69 break; 70 case T_IRQ0 + IRQ_COM1: 71 uartintr(); 72 lapiceoi(); 73 break; 74 case T_IRQ0 + 7: 75 case T_IRQ0 + IRQ_SPURIOUS: 76 cprintf("cpu%d: spurious interrupt at %x:%x\n", 77 cpuid(), tf->cs, tf->eip); 78 lapiceoi(); 79 break; 80 81 //PAGEBREAK: 13 82 default: 83 if(myproc() == 0 || (tf->cs&3) == 0){ 84 // In kernel, it must be our mistake. 85 cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", 86 tf->trapno, cpuid(), tf->eip, rcr2()); 87 panic("trap"); 88 } 89 // In user space, assume process misbehaved. 90 cprintf("pid %d %s: trap %d err %d on cpu %d " 91 "eip 0x%x addr 0x%x--kill proc\n", 92 myproc()->pid, myproc()->name, tf->trapno, tf->err, cpuid(), tf->eip, 93 rcr2()); 94 myproc()->killed = 1; 95 } 96 97 // Force process exit if it has been killed and is in user space. 98 // (If it is still executing in the kernel, let it keep running 99 // until it gets to the regular system call return.) 100 if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) 101 exit(); 102 103 // Force process to give up CPU on clock tick. 104 // If interrupts were on while locks held, would need to check nlock. 105 if(myproc() && myproc()->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER) 106 yield(); 107 108 // Check if the process has been killed since we yielded 109 if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) 110 exit(); 111 } 112