ax_cpu/loongarch64/
uspace.rs1use core::ops::{Deref, DerefMut};
4
5use ax_memory_addr::VirtAddr;
6use loongArch64::register::{
7 badi, badv,
8 estat::{self, Exception, Trap},
9};
10
11pub use crate::uspace_common::{ExceptionKind, ReturnReason};
12use crate::{TrapFrame, trap::PageFaultFlags};
13
14#[derive(Debug, Clone, Copy)]
16#[repr(C)]
17pub struct UserContext(TrapFrame);
18
19impl UserContext {
20 pub fn new(entry: usize, ustack_top: VirtAddr, arg0: usize) -> Self {
23 let mut trap_frame = TrapFrame::default();
24 const PPLV_UMODE: usize = 0b11;
25 const PIE: usize = 1 << 2;
26 trap_frame.regs.sp = ustack_top.as_usize();
27 trap_frame.era = entry;
28 trap_frame.prmd = PPLV_UMODE | PIE;
29 trap_frame.regs.a0 = arg0;
30 Self(trap_frame)
31 }
32
33 pub fn run(&mut self) -> ReturnReason {
40 extern "C" {
41 fn enter_user(uctx: &mut UserContext);
42 }
43
44 crate::asm::disable_irqs();
45 unsafe { enter_user(self) };
46
47 let estat = estat::read();
48 let badv = badv::read().vaddr();
49 let badi = badi::read().inst();
50
51 let ret = match estat.cause() {
52 Trap::Interrupt(_) => {
53 let irq_num: usize = estat.is().trailing_zeros() as usize;
54 crate::trap::irq_handler(irq_num);
55 ReturnReason::Interrupt
56 }
57 Trap::Exception(Exception::Syscall) => {
58 self.era += 4;
59 ReturnReason::Syscall
60 }
61 Trap::Exception(Exception::LoadPageFault)
62 | Trap::Exception(Exception::PageNonReadableFault) => {
63 ReturnReason::PageFault(va!(badv), PageFaultFlags::READ | PageFaultFlags::USER)
64 }
65 Trap::Exception(Exception::StorePageFault)
66 | Trap::Exception(Exception::PageModifyFault) => {
67 ReturnReason::PageFault(va!(badv), PageFaultFlags::WRITE | PageFaultFlags::USER)
68 }
69 Trap::Exception(Exception::FetchPageFault)
70 | Trap::Exception(Exception::PageNonExecutableFault) => {
71 ReturnReason::PageFault(va!(badv), PageFaultFlags::EXECUTE | PageFaultFlags::USER)
72 }
73 Trap::Exception(e) => ReturnReason::Exception(ExceptionInfo { e, badv, badi }),
74 _ => ReturnReason::Unknown,
75 };
76
77 crate::asm::enable_irqs();
78 ret
79 }
80}
81
82impl Deref for UserContext {
83 type Target = TrapFrame;
84
85 fn deref(&self) -> &Self::Target {
86 &self.0
87 }
88}
89
90impl DerefMut for UserContext {
91 fn deref_mut(&mut self) -> &mut Self::Target {
92 &mut self.0
93 }
94}
95
96#[derive(Debug, Clone, Copy)]
98pub struct ExceptionInfo {
99 pub e: Exception,
101 pub badv: usize,
103 pub badi: u32,
105}
106
107impl ExceptionInfo {
108 pub fn kind(&self) -> ExceptionKind {
110 match self.e {
111 Exception::Breakpoint => ExceptionKind::Breakpoint,
112 Exception::InstructionNotExist | Exception::InstructionPrivilegeIllegal => {
113 ExceptionKind::IllegalInstruction
114 }
115 Exception::AddressNotAligned => ExceptionKind::Misaligned,
116 _ => ExceptionKind::Other,
117 }
118 }
119}