atmos/kernel/
interrupt.rs1#![allow(static_mut_refs)]
2use crate::kernel::fifo::Fifo;
3use spin::Mutex;
4
5pub static KBD_FIFO: Mutex<Fifo<16>> = Mutex::new(Fifo::new());
7pub static MOUSE_FIFO: Mutex<Fifo<128>> = Mutex::new(Fifo::new());
8pub static UART_FIFO: Mutex<Fifo<128>> = Mutex::new(Fifo::new());
9
10const UART0_BASE: usize = 0x3F20_1000;
11const UART0_DR: *mut u32 = UART0_BASE as *mut u32;
12const UART0_FR: *mut u32 = (UART0_BASE + 0x18) as *mut u32;
13const UART0_IMSC: *mut u32 = (UART0_BASE + 0x38) as *mut u32;
14const UART0_MIS: *mut u32 = (UART0_BASE + 0x40) as *mut u32;
15const UART0_ICR: *mut u32 = (UART0_BASE + 0x44) as *mut u32;
16
17const ENABLE_IRQS_2: *mut u32 = 0x3F00_B214 as *mut u32;
18const IRQ_PENDING_2: *mut u32 = 0x3F00_B208 as *mut u32;
19
20const LOCAL_CONTROL_BASE: usize = 0x4000_0000;
22const CORE_TIMER_INT_CTRL_BASE: usize = LOCAL_CONTROL_BASE + 0x40;
23const CORE_INT_SRC_BASE: usize = LOCAL_CONTROL_BASE + 0x60;
24
25const UART0_IRQ_BIT: u32 = 1 << 25; #[inline]
28fn core_id() -> usize {
29 let mpidr: u64;
30 unsafe {
31 core::arch::asm!("mrs {}, mpidr_el1", out(reg) mpidr);
32 }
33 (mpidr & 0xFF) as usize
34}
35
36pub fn init() {
37 unsafe {
38 core::ptr::write_volatile(ENABLE_IRQS_2, UART0_IRQ_BIT);
40
41 core::ptr::write_volatile(UART0_IMSC, 0x10);
43
44 core::ptr::write_volatile(UART0_ICR, 0x10);
46
47 let ctrl_ptr = CORE_TIMER_INT_CTRL_BASE as *mut u32; core::ptr::write_volatile(ctrl_ptr, 1 << 1);
50 }
51}
52
53pub fn init_secondary() {
54 unsafe {
55 let cid = core_id();
56 let ctrl_ptr = (CORE_TIMER_INT_CTRL_BASE + (cid * 4)) as *mut u32;
57 core::ptr::write_volatile(ctrl_ptr, 1 << 1);
58 }
59}
60
61pub fn enable_interrupts() {
63 unsafe {
64 core::arch::asm!("msr daifclr, #2", options(nomem, nostack));
65 }
66}
67
68pub fn disable_interrupts() {
70 unsafe {
71 core::arch::asm!("msr daifset, #2", options(nomem, nostack));
72 }
73}
74
75#[no_mangle]
76pub extern "C" fn rust_irq_handler() {
77 unsafe {
78 let cid = core_id();
79 let src_ptr = (CORE_INT_SRC_BASE + (cid * 4)) as *mut u32;
80 let int_src = core::ptr::read_volatile(src_ptr);
81
82 let mut timer_fired = false;
83
84 if (int_src & (1 << 1)) != 0 {
86 crate::kernel::timer::handle_timer_irq();
87 timer_fired = true;
88 }
89
90 if cid == 0
93 && (core::ptr::read_volatile(IRQ_PENDING_2) & UART0_IRQ_BIT) != 0
94 && (core::ptr::read_volatile(UART0_MIS) & 0x10) != 0
95 {
96 while (core::ptr::read_volatile(UART0_FR) & 0x10) == 0 {
97 let data = core::ptr::read_volatile(UART0_DR) & 0xFF;
98 let _ = UART_FIFO.lock().push(data);
99 }
100 core::ptr::write_volatile(UART0_ICR, 0x10);
101 }
102
103 if timer_fired {
105 crate::kernel::scheduler::decrement_wait_ticks();
106 crate::kernel::scheduler::scheduler_tick();
107 }
108
109 if crate::kernel::scheduler::should_preempt() {
111 crate::kernel::scheduler::schedule();
112 }
113 }
114}