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 %p pid=%d\n", r_scause(), p->pid);
72 printf(" sepc=%p stval=%p\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 printf("scause %p\n", scause);
149 printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
150 panic("kerneltrap");
151 }
152
153
154 if(which_dev == 2 && myproc() != 0 && myproc()->state == RUNNING)
155 yield();
156
157
158
159 w_sepc(sepc);
160 w_sstatus(sstatus);
161 }
162
163 void
164 clockintr()
165 {
166 acquire(&tickslock);
167 ticks++;
168 wakeup(&ticks);
169 release(&tickslock);
170 }
171
172
173
174
175
176
177 int
178 devintr()
179 {
180 uint64 scause = r_scause();
181
182 if((scause & 0x8000000000000000L) &&
183 (scause & 0xff) == 9){
184
185
186
187 int irq = plic_claim();
188
189 if(irq == UART0_IRQ){
190 uartintr();
191 } else if(irq == VIRTIO0_IRQ){
192 virtio_disk_intr();
193 } else if(irq){
194 printf("unexpected interrupt irq=%d\n", irq);
195 }
196
197
198
199
200 if(irq)
201 plic_complete(irq);
202
203 return 1;
204 } else if(scause == 0x8000000000000001L){
205
206
207
208 if(cpuid() == 0){
209 clockintr();
210 }
211
212
213
214 w_sip(r_sip() & ~2);
215
216 return 2;
217 } else {
218 return 0;
219 }
220 }
221