mirror of
https://github.com/SmallPond/MIT6.828_OS.git
synced 2026-04-26 11:49:51 +08:00
149 lines
3.6 KiB
C
149 lines
3.6 KiB
C
#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();
|
||
}
|