interrupt.rs 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. use super::mem::handle_kernel_page_fault;
  2. use super::timer::timer_interrupt;
  3. use crate::kernel::constants::EINVAL;
  4. use crate::prelude::*;
  5. use alloc::sync::Arc;
  6. use eonix_hal::processor::CPU;
  7. use eonix_hal::traits::fault::Fault;
  8. use eonix_hal::traits::trap::{RawTrapContext, TrapType};
  9. use eonix_hal::trap::TrapContext;
  10. use eonix_mm::address::{Addr as _, VAddr};
  11. use eonix_runtime::scheduler::Scheduler;
  12. use eonix_sync::SpinIrq as _;
  13. static IRQ_HANDLERS: Spin<[Option<Arc<dyn Fn() + Send + Sync>>; 16]> =
  14. Spin::new([const { None }; 16]);
  15. pub fn default_irq_handler(irqno: usize) {
  16. assert!(irqno < 16);
  17. let handler = IRQ_HANDLERS.lock()[irqno as usize].as_ref().cloned();
  18. if let Some(handler) = handler {
  19. handler();
  20. }
  21. #[cfg(target_arch = "x86_64")]
  22. {
  23. use eonix_hal::arch_exported::io::Port8;
  24. const PIC1_COMMAND: Port8 = Port8::new(0x20);
  25. const PIC2_COMMAND: Port8 = Port8::new(0xA0);
  26. PIC1_COMMAND.write(0x20); // EOI
  27. if irqno >= 8 {
  28. PIC2_COMMAND.write(0x20); // EOI
  29. }
  30. }
  31. }
  32. pub fn default_fault_handler(fault_type: Fault, trap_ctx: &mut TrapContext) {
  33. if trap_ctx.is_user_mode() {
  34. unimplemented!("Unhandled user space fault");
  35. }
  36. match fault_type {
  37. Fault::PageFault {
  38. error_code,
  39. address: vaddr,
  40. } => {
  41. let fault_pc = VAddr::from(trap_ctx.get_program_counter());
  42. if let Some(new_pc) = handle_kernel_page_fault(fault_pc, vaddr, error_code) {
  43. trap_ctx.set_program_counter(new_pc.addr());
  44. }
  45. }
  46. fault => panic!("Unhandled kernel space fault: {fault:?}"),
  47. }
  48. }
  49. #[eonix_hal::default_trap_handler]
  50. pub fn interrupt_handler(trap_ctx: &mut TrapContext) {
  51. match trap_ctx.trap_type() {
  52. TrapType::Syscall { no, .. } => unreachable!("Syscall {} in kernel space.", no),
  53. TrapType::Fault(fault) => default_fault_handler(fault, trap_ctx),
  54. TrapType::Irq(no) => default_irq_handler(no),
  55. TrapType::Timer => {
  56. timer_interrupt();
  57. if eonix_preempt::count() == 0 {
  58. // To make scheduler satisfied.
  59. eonix_preempt::disable();
  60. Scheduler::schedule();
  61. }
  62. }
  63. }
  64. }
  65. pub fn register_irq_handler<F>(irqno: i32, handler: F) -> Result<(), u32>
  66. where
  67. F: Fn() + Send + Sync + 'static,
  68. {
  69. if irqno < 0 || irqno >= 16 {
  70. return Err(EINVAL);
  71. }
  72. let old = IRQ_HANDLERS.lock_irq()[irqno as usize].replace(Arc::new(handler));
  73. assert!(old.is_none(), "IRQ handler already registered");
  74. Ok(())
  75. }
  76. pub fn end_of_interrupt() {
  77. CPU::local().as_mut().end_of_interrupt();
  78. }