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