#include "types.h" #include "defs.h" #include "param.h" #include "memlayout.h" #include "mmu.h" #include "proc.h" #include "x86.h" #include "traps.h" #include "spinlock.h" // Interrupt descriptor table (shared by all CPUs). struct gatedesc idt[256]; extern uint vectors[]; // in vectors.S: array of 256 entry pointers struct spinlock tickslock; uint ticks; void tvinit(void) { int i; for(i = 0; i < 256; i++) SETGATE(idt[i], 0, SEG_KCODE<<3, vectors[i], 0); SETGATE(idt[T_SYSCALL], 1, SEG_KCODE<<3, vectors[T_SYSCALL], DPL_USER); initlock(&tickslock, "time"); } void idtinit(void) { lidt(idt, sizeof(idt)); } //PAGEBREAK: 41 void trap(struct trapframe *tf) { if(tf->trapno == T_SYSCALL){ if(myproc()->killed) exit(); myproc()->tf = tf; syscall(); if(myproc()->killed) exit(); return; } char *mem; switch(tf->trapno){ case T_IRQ0 + IRQ_TIMER: if(cpuid() == 0){ acquire(&tickslock); ticks++; wakeup(&ticks); release(&tickslock); } if(myproc() != 0 && (tf->cs & 3) == 3){ myproc()->ticks++; // 没有alarm任务的proc, 不会进入以下if,因为alarminterval为0 if(myproc()->ticks == myproc()->alarminterval) { myproc()->ticks = 0; // 为什么不能像下面这样调用函数 //myproc()->alarmhandler(); tf->esp -= 4; // eip压栈 *(uint *)(tf->esp) = tf->eip; tf->eip = (uint)myproc()->alarmhandler; } } lapiceoi(); break; case T_IRQ0 + IRQ_IDE: ideintr(); lapiceoi(); break; case T_IRQ0 + IRQ_IDE+1: // Bochs generates spurious IDE1 interrupts. break; case T_IRQ0 + IRQ_KBD: kbdintr(); lapiceoi(); break; case T_IRQ0 + IRQ_COM1: uartintr(); lapiceoi(); break; case T_IRQ0 + 7: case T_IRQ0 + IRQ_SPURIOUS: cprintf("cpu%d: spurious interrupt at %x:%x\n", cpuid(), tf->cs, tf->eip); lapiceoi(); break; // T_PGFLT = 14 case T_PGFLT: // kallo或mappages执行失败,则继续执行下面的default. // In user space, assume process misbehaved. // cr2包含发生页面错误时的线性地址. mem = kalloc(); if(mem != 0){ uint va = PGROUNDDOWN(rcr2()); memset(mem, 0, PGSIZE); extern int mappages(pde_t *pgdir, void *va, uint size, uint pa, int perm); if(mappages(myproc()->pgdir,(void *)va, PGSIZE, V2P(mem), PTE_W|PTE_U) >= 0) { // 全部执行成功才break; break; } } //PAGEBREAK: 13 default: // tf->cs&3 不明白 if(myproc() == 0 || (tf->cs&3) == 0){ // In kernel, it must be our mistake. cprintf("unexpected trap %d from cpu %d eip %x (cr2=0x%x)\n", tf->trapno, cpuid(), tf->eip, rcr2()); panic("trap"); } // In user space, assume process misbehaved. cprintf("pid %d %s: trap %d err %d on cpu %d " "eip 0x%x addr 0x%x--kill proc\n", myproc()->pid, myproc()->name, tf->trapno, tf->err, cpuid(), tf->eip, rcr2()); myproc()->killed = 1; } // Force process exit if it has been killed and is in user space. // (If it is still executing in the kernel, let it keep running // until it gets to the regular system call return.) if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) exit(); // Force process to give up CPU on clock tick. // If interrupts were on while locks held, would need to check nlock. if(myproc() && myproc()->state == RUNNING && tf->trapno == T_IRQ0+IRQ_TIMER) yield(); // Check if the process has been killed since we yielded if(myproc() && myproc()->killed && (tf->cs&3) == DPL_USER) exit(); }