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