summaryrefslogtreecommitdiff
path: root/kernel/src/arch/riscv64/interrupts.rs
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/src/arch/riscv64/interrupts.rs')
-rw-r--r--kernel/src/arch/riscv64/interrupts.rs82
1 files changed, 82 insertions, 0 deletions
diff --git a/kernel/src/arch/riscv64/interrupts.rs b/kernel/src/arch/riscv64/interrupts.rs
new file mode 100644
index 0000000..302fc4f
--- /dev/null
+++ b/kernel/src/arch/riscv64/interrupts.rs
@@ -0,0 +1,82 @@
+use crate::{
+ drivers::riscv_timer::{set_timer, Instant},
+ prelude::*,
+};
+use core::{
+ arch::{asm, global_asm},
+ time::Duration,
+};
+
+/// Sets up the timer interrupt.
+#[inline(never)]
+pub(crate) fn example_timer() {
+ let now = Instant::now();
+ info!("now = {now:?}");
+
+ let in_a_sec = now + Duration::from_secs(1);
+ info!("in_a_sec = {in_a_sec:?}");
+ info!("setting a timer for 1s...");
+ set_timer(in_a_sec);
+
+ enable_interrupts();
+}
+
+/// Disables interrupts.
+pub fn disable_interrupts() {
+ // Set SSTATUS.SIE to 0, which disables interrupts.
+ //
+ // SAFETY: Not running interrupts shouldn't be able to compromise safety.
+ unsafe {
+ asm!(
+ "csrc sstatus, {sie}",
+ sie = in(reg) (1 << 1),
+ options(nomem, nostack)
+ );
+ }
+}
+
+/// Enables interrupts.
+pub fn enable_interrupts() {
+ // Set STVEC.BASE to the handler function, and STVEC.MODE to Direct. Since the trap_handler_asm
+ // has a `.align 4` before it, the lower two bits of its address should already be zero.
+ //
+ // SAFETY: Even if interrupts were already enabled, this is a valid handler.
+ unsafe {
+ asm!(
+ "csrw stvec, {stvec}",
+ stvec = in(reg) trap_handler_asm,
+ options(nomem, nostack)
+ );
+ }
+
+ // Set SSTATUS.SIE to 1, which enables interrupts.
+ //
+ // SAFETY: We just initialized STVEC, so it should be able to handle interrupts.
+ unsafe {
+ asm!(
+ "csrs sstatus, {sie}",
+ sie = in(reg) (1 << 1),
+ options(nomem, nostack)
+ );
+ }
+}
+
+fn trap_handler() {
+ todo!("trap_handler")
+}
+
+// The assembly code that calls the Rust trap handler, after saving all caller-save registers
+// to the stack.
+global_asm! {
+ // Declare the handler's symbol.
+ ".align 4",
+ "trap_handler_asm:",
+ // TODO
+ "nop",
+ "call {trap_handler}",
+ trap_handler = sym trap_handler
+}
+
+extern "C" {
+ fn trap_handler_asm();
+}