mod.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  1. mod c_adapter;
  2. pub(super) mod entry;
  3. pub mod ipi;
  4. pub mod trap;
  5. use core::{
  6. arch::asm,
  7. sync::atomic::{compiler_fence, Ordering},
  8. };
  9. use system_error::SystemError;
  10. use crate::{
  11. arch::CurrentIrqArch,
  12. exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
  13. kerror,
  14. };
  15. use self::entry::setup_interrupt_gate;
  16. use super::{
  17. asm::irqflags::{local_irq_restore, local_irq_save},
  18. driver::apic::{CurrentApic, LocalAPIC},
  19. };
  20. /// @brief 关闭中断
  21. #[inline]
  22. pub fn cli() {
  23. unsafe {
  24. asm!("cli");
  25. }
  26. }
  27. /// @brief 开启中断
  28. #[inline]
  29. pub fn sti() {
  30. unsafe {
  31. asm!("sti");
  32. }
  33. }
  34. pub struct X86_64InterruptArch;
  35. impl InterruptArch for X86_64InterruptArch {
  36. #[inline(never)]
  37. unsafe fn arch_irq_init() -> Result<(), SystemError> {
  38. CurrentIrqArch::interrupt_disable();
  39. setup_interrupt_gate();
  40. CurrentApic.init_current_cpu();
  41. return Ok(());
  42. }
  43. unsafe fn interrupt_enable() {
  44. sti();
  45. }
  46. unsafe fn interrupt_disable() {
  47. cli();
  48. }
  49. fn is_irq_enabled() -> bool {
  50. let rflags: u64;
  51. unsafe {
  52. asm!("pushfq; pop {}", out(reg) rflags, options(nomem, preserves_flags));
  53. }
  54. return (rflags & (1 << 9)) != 0;
  55. }
  56. unsafe fn save_and_disable_irq() -> IrqFlagsGuard {
  57. compiler_fence(Ordering::SeqCst);
  58. let rflags = local_irq_save();
  59. let flags = IrqFlags::new(rflags);
  60. let guard = IrqFlagsGuard::new(flags);
  61. compiler_fence(Ordering::SeqCst);
  62. return guard;
  63. }
  64. unsafe fn restore_irq(flags: IrqFlags) {
  65. compiler_fence(Ordering::SeqCst);
  66. local_irq_restore(flags.flags());
  67. compiler_fence(Ordering::SeqCst);
  68. }
  69. fn probe_total_irq_num() -> u32 {
  70. // todo: 从APIC获取
  71. // 参考 https://code.dragonos.org.cn/xref/linux-6.1.9/arch/x86/kernel/apic/vector.c?r=&mo=19514&fi=704#704
  72. 256
  73. }
  74. fn ack_bad_irq(irq: IrqNumber) {
  75. kerror!("Unexpected IRQ trap at vector {}", irq.data());
  76. CurrentApic.send_eoi();
  77. }
  78. }
  79. /// 中断栈帧结构体
  80. #[repr(C)]
  81. #[derive(Debug, Copy, Clone)]
  82. pub struct TrapFrame {
  83. pub r15: ::core::ffi::c_ulong,
  84. pub r14: ::core::ffi::c_ulong,
  85. pub r13: ::core::ffi::c_ulong,
  86. pub r12: ::core::ffi::c_ulong,
  87. pub r11: ::core::ffi::c_ulong,
  88. pub r10: ::core::ffi::c_ulong,
  89. pub r9: ::core::ffi::c_ulong,
  90. pub r8: ::core::ffi::c_ulong,
  91. pub rbx: ::core::ffi::c_ulong,
  92. pub rcx: ::core::ffi::c_ulong,
  93. pub rdx: ::core::ffi::c_ulong,
  94. pub rsi: ::core::ffi::c_ulong,
  95. pub rdi: ::core::ffi::c_ulong,
  96. pub rbp: ::core::ffi::c_ulong,
  97. pub ds: ::core::ffi::c_ulong,
  98. pub es: ::core::ffi::c_ulong,
  99. pub rax: ::core::ffi::c_ulong,
  100. pub func: ::core::ffi::c_ulong,
  101. pub errcode: ::core::ffi::c_ulong,
  102. pub rip: ::core::ffi::c_ulong,
  103. pub cs: ::core::ffi::c_ulong,
  104. pub rflags: ::core::ffi::c_ulong,
  105. pub rsp: ::core::ffi::c_ulong,
  106. pub ss: ::core::ffi::c_ulong,
  107. }
  108. impl TrapFrame {
  109. pub fn new() -> Self {
  110. Self {
  111. r15: 0,
  112. r14: 0,
  113. r13: 0,
  114. r12: 0,
  115. r11: 0,
  116. r10: 0,
  117. r9: 0,
  118. r8: 0,
  119. rbx: 0,
  120. rcx: 0,
  121. rdx: 0,
  122. rsi: 0,
  123. rdi: 0,
  124. rbp: 0,
  125. ds: 0,
  126. es: 0,
  127. rax: 0,
  128. func: 0,
  129. errcode: 0,
  130. rip: 0,
  131. cs: 0,
  132. rflags: 0,
  133. rsp: 0,
  134. ss: 0,
  135. }
  136. }
  137. /// 设置中断栈帧返回值
  138. pub fn set_return_value(&mut self, value: usize) {
  139. self.rax = value as u64;
  140. }
  141. /// 判断当前中断是否来自用户模式
  142. pub fn from_user(&self) -> bool {
  143. if (self.cs & 0x3) != 0 {
  144. return true;
  145. } else {
  146. return false;
  147. }
  148. }
  149. }