-
Notifications
You must be signed in to change notification settings - Fork 13
/
trap.c
106 lines (96 loc) · 2.7 KB
/
trap.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
#include "types.h"
#include "defs.h"
#include "param.h"
#include "memlayout.h"
#include "mmu.h"
#include "proc.h"
#include "mips.h"
#include "traps.h"
#include "spinlock.h"
// Interrupt descriptor table (shared by all CPUs).
extern uint vectors[]; // in vectors.S: array of 256 entry pointers
struct spinlock tickslock;
uint ticks;
void
tvinit(void)
{
// Set vector base address.
write_cop0_status(read_cop0_status() & ~STATUS_BEV);
// TLB refill
memmove((void *)EV_TLBREFILL, tlbrefill, ((uint)tlbrefill_end - (uint)tlbrefill));
// general traps
memmove((void *)EV_OTHERS, gentraps, ((uint)gentraps_end - (uint)gentraps));
initlock(&tickslock, "time");
}
//PAGEBREAK: 41
void
trap(struct trapframe *tf)
{
uint exccode = tf->cause & CAUSE_EXC;
if(exccode == EXC_SYSCALL){
if(proc->killed)
exit();
proc->tf = tf;
proc->tf->epc += 4; // Just increase epc. Assume the syscall NOT to be in a delay slot.
syscall();
if(proc->killed)
exit();
return;
}
if(exccode == EXC_INT){
uint irq = picgetirq();
switch(irq){
case IRQ_TIMER:
if(cpu->id == 0){
acquire(&tickslock);
ticks++;
wakeup(&ticks);
release(&tickslock);
}
break;
case IRQ_IDE:
ideintr();
break;
case IRQ_IDE+1:
// Bochs generates spurious IDE1 interrupts.
break;
case IRQ_KBD:
kbdintr();
break;
case IRQ_COM1:
uartintr();
break;
case IRQ_SPURIOUS_MS:
case IRQ_SPURIOUS_SL:
cprintf("cpu%d: spurious interrupt at %x\n",
cpu->id, tf->epc);
break;
}
picsendeoi(irq);
} else {
if(proc == 0 || (tf->status & STATUS_KSU) == 0){
// In kernel, it must be our mistake.
cprintf("unexpected trap %d from cpu %d eip %x (bad=0x%x)\n",
tf->cause, cpu->id, tf->epc, read_cop0_bad());
panic("trap");
}
// In user space, assume process misbehaved.
cprintf("pid %d %s: trap %d on cpu %d "
"eip 0x%x addr 0x%x--kill proc\n",
proc->pid, proc->name, tf->cause, cpu->id, tf->epc,
read_cop0_bad());
proc->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(proc && proc->killed && (tf->status & STATUS_KSU))
exit();
// Force process to give up CPU on clock tick.
// If interrupts were on while locks held, would need to check nlock.
if(proc && proc->state == RUNNING && tf->cause == T_IRQ0+IRQ_TIMER)
yield();
// Check if the process has been killed since we yielded
if(proc && proc->killed && (tf->status & STATUS_KSU))
exit();
}