"scopeguard",
]
+[[package]]
+name = "plic"
+version = "0.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2ad606bf31d67b0e10a161b7df7d6a97dda7be22ce4bebcff889476e867c9b7a"
+
[[package]]
name = "raw-cpuid"
version = "10.7.0"
version = "0.1.0"
dependencies = [
"buddy_system_allocator",
+ "plic",
"spinning_top",
"uart_16550",
]
buddy_system_allocator = "0.9.1"
spinning_top = "0.3.0"
uart_16550 = "0.3.0"
+plic = { version = "0.0.2", features = ["primitive-id"] }
# We need to turn off panic unwinding
# so we set the panic behavior to abort
"csrw mtvec, t2",
trap_frame = in(reg)(&raw mut trap::TRAP_FRAME as usize)
);
+
+ // We're now good to take interrupts
+ trap::init_interrupts();
}
println!("Kernel init complete");
+use core::arch::asm;
+use plic::Plic;
+
#[repr(C)]
#[derive(Clone, Copy)]
pub struct TrapFrame {
pub static mut TRAP_FRAME: TrapFrame = TrapFrame::new();
+// unsafe: call only once!
+pub unsafe fn init_interrupts() {
+ asm!("csrsi mstatus, 0b1000", "li t2, 0xaaa", "csrw mie, t2");
+ let plic = get_plic();
+ // Enable interrupts of any priority on the PLIC
+ plic.set_threshold(0, 0);
+ // PLIC interrupt 10 is the UART on qemu
+ plic.set_priority(10, 1);
+ plic.enable(10, 0);
+}
+
+unsafe fn get_plic() -> &'static Plic {
+ return &*(0xc000000 as *const Plic);
+}
+
#[no_mangle]
extern "C" fn m_trap(
epc: usize,
},
11 => {
// Machine external (interrupt from Platform Interrupt Controller (PLIC))
- println!("Machine external interrupt CPU#{}", hart);
+ // Since we have only the UART to deal with, this one's pretty easy.
+ unsafe {
+ let plic = get_plic();
+ match plic.claim(0) {
+ Some(int) => {
+ let uart = 0x1000_0000 as *mut u8;
+ let data = uart.read_volatile();
+ print!("{}", data as char);
+ plic.complete(0, int);
+ }
+ _ => {
+ println!("No interrupt pending?!")
+ }
+ }
+ }
}
_ => {
panic!("Unhandled async trap CPU#{} -> {}\n", hart, cause_num);