trap_context.rs 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. use crate::processor::CPU;
  2. use core::arch::asm;
  3. use eonix_hal_traits::{
  4. fault::{Fault, PageFaultErrorCode},
  5. trap::{RawTrapContext, TrapType},
  6. };
  7. use eonix_mm::address::VAddr;
  8. #[derive(Clone, Copy, Default)]
  9. #[repr(C, align(16))]
  10. pub struct TrapContext {
  11. rax: u64,
  12. rbx: u64,
  13. rcx: u64,
  14. rdx: u64,
  15. rdi: u64,
  16. rsi: u64,
  17. r8: u64,
  18. r9: u64,
  19. r10: u64,
  20. r11: u64,
  21. r12: u64,
  22. r13: u64,
  23. r14: u64,
  24. r15: u64,
  25. rbp: u64,
  26. int_no: u64,
  27. errcode: u64,
  28. rip: u64,
  29. cs: u64,
  30. flags: u64,
  31. rsp: u64,
  32. ss: u64,
  33. }
  34. impl TrapContext {
  35. fn get_fault_type(&self) -> Fault {
  36. match self.int_no {
  37. 6 | 8 => Fault::InvalidOp,
  38. 13 => Fault::BadAccess,
  39. 14 => {
  40. let mut error_code = PageFaultErrorCode::empty();
  41. if self.errcode & 2 != 0 {
  42. error_code |= PageFaultErrorCode::Write;
  43. } else if self.errcode & 16 != 0 {
  44. error_code |= PageFaultErrorCode::InstructionFetch;
  45. } else {
  46. error_code |= PageFaultErrorCode::Read;
  47. }
  48. if self.errcode & 4 != 0 {
  49. error_code |= PageFaultErrorCode::UserAccess;
  50. }
  51. #[inline(always)]
  52. fn get_page_fault_address() -> VAddr {
  53. let cr2: usize;
  54. unsafe {
  55. asm!(
  56. "mov %cr2, {}",
  57. out(reg) cr2,
  58. options(att_syntax)
  59. );
  60. }
  61. VAddr::from(cr2)
  62. }
  63. Fault::PageFault {
  64. error_code,
  65. address: get_page_fault_address(),
  66. }
  67. }
  68. code @ 0..0x20 => Fault::Unknown(code as usize),
  69. _ => unreachable!(),
  70. }
  71. }
  72. }
  73. impl RawTrapContext for TrapContext {
  74. type FIrq = impl FnOnce(fn(irqno: usize));
  75. type FTimer = fn(handler: fn());
  76. fn new() -> Self {
  77. Self {
  78. ..Default::default()
  79. }
  80. }
  81. fn trap_type(&self) -> TrapType<Self::FIrq, Self::FTimer> {
  82. match self.int_no {
  83. 0..0x20 => TrapType::Fault(self.get_fault_type()),
  84. 0x40 => TrapType::Timer {
  85. callback: |handler| {
  86. CPU::local().as_mut().end_of_interrupt();
  87. handler();
  88. },
  89. },
  90. 0x80 => TrapType::Syscall {
  91. no: self.rax as usize,
  92. args: [
  93. self.rbx as usize,
  94. self.rcx as usize,
  95. self.rdx as usize,
  96. self.rsi as usize,
  97. self.rdi as usize,
  98. self.rbp as usize,
  99. ],
  100. },
  101. no => TrapType::Irq {
  102. callback: move |handler| {
  103. let irqno = no as usize - 0x20;
  104. use crate::arch::io::Port8;
  105. const PIC1_COMMAND: Port8 = Port8::new(0x20);
  106. const PIC2_COMMAND: Port8 = Port8::new(0xA0);
  107. PIC1_COMMAND.write(0x20); // EOI
  108. if irqno >= 8 {
  109. PIC2_COMMAND.write(0x20); // EOI
  110. }
  111. handler(irqno);
  112. },
  113. },
  114. }
  115. }
  116. fn get_program_counter(&self) -> usize {
  117. self.rip as usize
  118. }
  119. fn get_stack_pointer(&self) -> usize {
  120. self.rsp as usize
  121. }
  122. fn set_program_counter(&mut self, pc: usize) {
  123. self.rip = pc as u64
  124. }
  125. fn set_stack_pointer(&mut self, sp: usize) {
  126. self.rsp = sp as u64
  127. }
  128. fn is_interrupt_enabled(&self) -> bool {
  129. self.flags & 0x200 != 0
  130. }
  131. fn set_interrupt_enabled(&mut self, enabled: bool) {
  132. if enabled {
  133. self.flags |= 0x200;
  134. } else {
  135. self.flags &= !0x200;
  136. }
  137. }
  138. fn is_user_mode(&self) -> bool {
  139. self.cs & 3 == 3
  140. }
  141. fn set_user_mode(&mut self, user: bool) {
  142. self.cs = if user { 0x2b } else { 0x08 };
  143. self.ss = if user { 0x33 } else { 0x10 };
  144. }
  145. fn set_user_return_value(&mut self, retval: usize) {
  146. self.rax = retval as u64;
  147. }
  148. fn set_user_call_frame<E>(
  149. &mut self,
  150. pc: usize,
  151. sp: Option<usize>,
  152. ra: Option<usize>,
  153. args: &[usize],
  154. write_memory: impl Fn(VAddr, &[u8]) -> Result<(), E>,
  155. ) -> Result<(), E> {
  156. self.set_program_counter(pc);
  157. let mut sp = sp.unwrap_or_else(|| self.get_stack_pointer());
  158. let arg_size = args.len() * 4;
  159. sp -= arg_size;
  160. sp &= !0xf; // Align to 16 bytes
  161. for (idx, arg) in args.iter().enumerate() {
  162. write_memory(VAddr::from(sp + idx * 8), &arg.to_ne_bytes())?;
  163. }
  164. if let Some(ra) = ra {
  165. sp -= 4; // Space for return address
  166. write_memory(VAddr::from(sp), &ra.to_ne_bytes())?;
  167. }
  168. self.set_stack_pointer(sp);
  169. Ok(())
  170. }
  171. }