This source file includes following definitions.
- trapinit
- trapinithart
- usertrap
- usertrapret
- kerneltrap
- clockintr
- devintr
1 #include "types.h"
2 #include "param.h"
3 #include "memlayout.h"
4 #include "riscv.h"
5 #include "spinlock.h"
6 #include "proc.h"
7 #include "defs.h"
8
9 struct spinlock tickslock;
10 uint ticks;
11
12 extern char trampoline[], uservec[], userret[];
13
14
15 void kernelvec();
16
17 extern int devintr();
18
19 void
20 trapinit(void)
21 {
22 initlock(&tickslock, "time");
23 }
24
25
26 void
27 trapinithart(void)
28 {
29 w_stvec((uint64)kernelvec);
30 }
31
32
33
34
35
36 void
37 usertrap(void)
38 {
39 int which_dev = 0;
40
41 if((r_sstatus() & SSTATUS_SPP) != 0)
42 panic("usertrap: not from user mode");
43
44
45
46 w_stvec((uint64)kernelvec);
47
48 struct proc *p = myproc();
49
50
51 p->trapframe->epc = r_sepc();
52
53 if(r_scause() == 8){
54
55
56 if(killed(p))
57 exit(-1);
58
59
60
61 p->trapframe->epc += 4;
62
63
64
65 intr_on();
66
67 syscall();
68 } else if((which_dev = devintr()) != 0){
69
70 } else {
71 printf("usertrap(): unexpected scause 0x%lx pid=%d\n", r_scause(), p->pid);
72 printf(" sepc=0x%lx stval=0x%lx\n", r_sepc(), r_stval());
73 setkilled(p);
74 }
75
76 if(killed(p))
77 exit(-1);
78
79
80 if(which_dev == 2)
81 yield();
82
83 usertrapret();
84 }
85
86
87
88
89 void
90 usertrapret(void)
91 {
92 struct proc *p = myproc();
93
94
95
96
97 intr_off();
98
99
100 uint64 trampoline_uservec = TRAMPOLINE + (uservec - trampoline);
101 w_stvec(trampoline_uservec);
102
103
104
105 p->trapframe->kernel_satp = r_satp();
106 p->trapframe->kernel_sp = p->kstack + PGSIZE;
107 p->trapframe->kernel_trap = (uint64)usertrap;
108 p->trapframe->kernel_hartid = r_tp();
109
110
111
112
113
114 unsigned long x = r_sstatus();
115 x &= ~SSTATUS_SPP;
116 x |= SSTATUS_SPIE;
117 w_sstatus(x);
118
119
120 w_sepc(p->trapframe->epc);
121
122
123 uint64 satp = MAKE_SATP(p->pagetable);
124
125
126
127
128 uint64 trampoline_userret = TRAMPOLINE + (userret - trampoline);
129 ((void (*)(uint64))trampoline_userret)(satp);
130 }
131
132
133
134 void
135 kerneltrap()
136 {
137 int which_dev = 0;
138 uint64 sepc = r_sepc();
139 uint64 sstatus = r_sstatus();
140 uint64 scause = r_scause();
141
142 if((sstatus & SSTATUS_SPP) == 0)
143 panic("kerneltrap: not from supervisor mode");
144 if(intr_get() != 0)
145 panic("kerneltrap: interrupts enabled");
146
147 if((which_dev = devintr()) == 0){
148
149 printf("scause=0x%lx sepc=0x%lx stval=0x%lx\n", scause, r_sepc(), r_stval());
150 panic("kerneltrap");
151 }
152
153
154 if(which_dev == 2 && myproc() != 0)
155 yield();
156
157
158
159 w_sepc(sepc);
160 w_sstatus(sstatus);
161 }
162
163 void
164 clockintr()
165 {
166 if(cpuid() == 0){
167 acquire(&tickslock);
168 ticks++;
169 wakeup(&ticks);
170 release(&tickslock);
171 }
172
173
174
175
176 w_stimecmp(r_time() + 1000000);
177 }
178
179
180
181
182
183
184 int
185 devintr()
186 {
187 uint64 scause = r_scause();
188
189 if(scause == 0x8000000000000009L){
190
191
192
193 int irq = plic_claim();
194
195 if(irq == UART0_IRQ){
196 uartintr();
197 } else if(irq == VIRTIO0_IRQ){
198 virtio_disk_intr();
199 } else if(irq){
200 printf("unexpected interrupt irq=%d\n", irq);
201 }
202
203
204
205
206 if(irq)
207 plic_complete(irq);
208
209 return 1;
210 } else if(scause == 0x8000000000000005L){
211
212 clockintr();
213 return 2;
214 } else {
215 return 0;
216 }
217 }
218