kernel/arch/riscv64/trap/
user.rs1use core::arch::naked_asm;
2use core::{arch::asm, mem::transmute};
3
4use super::exception::arch_exception_handler;
5use super::interrupt::arch_interrupt_handler;
6
7use crate::arch::Trapframe;
8
9#[unsafe(link_section = ".trampoline.text")]
10#[unsafe(export_name = "_user_trap_entry")]
11#[unsafe(naked)]
12pub extern "C" fn _user_trap_entry() {
13 unsafe {
14 naked_asm!("
15 .option norvc
16 .option norelax
17 .align 8
18 /* Disable the interrupt */
19 csrci sstatus, 0x2
20 /* Save the current a0 to sscratch and load the trapframe pointer */
21 csrrw a0, sscratch, a0
22 /* Save the context of the current hart */
23 sd x0, 0(a0)
24 sd x1, 8(a0)
25 sd x2, 16(a0)
26 sd x3, 24(a0)
27 sd x4, 32(a0)
28 sd x5, 40(a0)
29 sd x6, 48(a0)
30 sd x7, 56(a0)
31 sd x8, 64(a0)
32 sd x9, 72(a0)
33 // sd x10, 80(a0)
34 sd x11, 88(a0)
35 sd x12, 96(a0)
36 sd x13, 104(a0)
37 sd x14, 112(a0)
38 sd x15, 120(a0)
39 sd x16, 128(a0)
40 sd x17, 136(a0)
41 sd x18, 144(a0)
42 sd x19, 152(a0)
43 sd x20, 160(a0)
44 sd x21, 168(a0)
45 sd x22, 176(a0)
46 sd x23, 184(a0)
47 sd x24, 192(a0)
48 sd x25, 200(a0)
49 sd x26, 208(a0)
50 sd x27, 216(a0)
51 sd x28, 224(a0)
52 sd x29, 232(a0)
53 sd x30, 240(a0)
54 sd x31, 248(a0)
55 csrr t0, sepc
56 sd t0, 256(a0)
57
58 // Load and store a0 to trapframe
59 csrr t0, sscratch
60 // Restore sscratch from a0
61 csrw sscratch, a0
62
63 sd t0, 80(a0)
64
65 /* Load the satp for the kernel space from trapframe */
66 ld t0, 272(a0)
67 /* Switch to kernel memory space */
68 csrrw t0, satp, t0
69 sfence.vma zero, zero
70 /* Store the user memory space */
71 sd t0, 272(a0)
72
73 // Load kernel stack pointer
74 ld sp, 280(a0)
75
76 /* Call the user trap handler */
77 /* Load the function pointer from the trapframe */
78 ld ra, 288(a0)
79 jalr ra, 0(ra)
80
81 /* Restore the user memory space */
82 ld t0, 272(a0)
83 csrrw t0, satp, t0
84 sfence.vma zero, zero
85 /* Restore the kernel memory space to the trapframe */
86 sd t0, 272(a0)
87
88 /* Restore the context of the current hart */
89 /* epc */
90 ld t0, 256(a0)
91 csrw sepc, t0
92 /* Register */
93 ld x0, 0(a0)
94 ld x1, 8(a0)
95 ld x2, 16(a0)
96 ld x3, 24(a0)
97 ld x4, 32(a0)
98 ld x5, 40(a0)
99 ld x6, 48(a0)
100 ld x7, 56(a0)
101 ld x8, 64(a0)
102 ld x9, 72(a0)
103 // ld x10, 80(a0)
104 ld x11, 88(a0)
105 ld x12, 96(a0)
106 ld x13, 104(a0)
107 ld x14, 112(a0)
108 ld x15, 120(a0)
109 ld x16, 128(a0)
110 ld x17, 136(a0)
111 ld x18, 144(a0)
112 ld x19, 152(a0)
113 ld x20, 160(a0)
114 ld x21, 168(a0)
115 ld x22, 176(a0)
116 ld x23, 184(a0)
117 ld x24, 192(a0)
118 ld x25, 200(a0)
119 ld x26, 208(a0)
120 ld x27, 216(a0)
121 ld x28, 224(a0)
122 ld x29, 232(a0)
123 ld x30, 240(a0)
124 ld x31, 248(a0)
125
126 /* Restore a0 from trapframe */
127 csrrw zero, sscratch, a0
128 ld a0, 80(a0)
129
130 sret
131 "
132 );
133 }
134}
135
136
137#[unsafe(export_name = "arch_user_trap_handler")]
138pub extern "C" fn arch_user_trap_handler(addr: usize) -> usize {
139 let trapframe: &mut Trapframe = unsafe { transmute(addr) };
140
141 let cause: usize;
142 unsafe {
143 asm!(
144 "csrr {0}, scause",
145 out(reg) cause,
146 );
147 }
148
149 let interrupt = cause & 0x8000000000000000 != 0;
153 if interrupt {
154 arch_interrupt_handler(trapframe, cause & !0x8000000000000000);
155 } else {
156 arch_exception_handler(trapframe, cause);
157 }
158
159 addr
160}