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