diff --git a/kernel/Makefile b/kernel/Makefile index b8adb2db..9ed8b9d7 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -318,7 +318,7 @@ ifeq ($(board), u540) .PHONY: install: $(kernel_img) @$(objcopy) -S -O binary --change-addresses -0x80000000 $< $(build_path)/bin - @sudo sh ../tools/u540/mkimg.sh $(build_path)/bin $(build_path)/sd.img + @../tools/u540/mkimg.sh $(build_path)/bin $(build_path)/sd.img endif .PHONY: diff --git a/kernel/src/arch/riscv32/board/u540/mod.rs b/kernel/src/arch/riscv32/board/u540/mod.rs new file mode 100644 index 00000000..cc538744 --- /dev/null +++ b/kernel/src/arch/riscv32/board/u540/mod.rs @@ -0,0 +1,18 @@ +use super::consts::KERNEL_OFFSET; + +/// Mask all external interrupt except serial. +pub unsafe fn init_external_interrupt() { + const HART1_S_MODE_INTERRUPT_ENABLES: *mut u64 = (KERNEL_OFFSET + 0x0C00_2100) as *mut u64; + const SERIAL: u64 = 4; + HART1_S_MODE_INTERRUPT_ENABLES.write(1 << SERIAL); +} + +/// Claim and complete external interrupt by reading and writing to +/// PLIC Interrupt Claim/Complete Register. +pub unsafe fn handle_external_interrupt() { + const HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE: *mut u32 = (KERNEL_OFFSET + 0x0C20_2004) as *mut u32; + // claim + let source = HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.read(); + // complete + HART1_S_MODE_INTERRUPT_CLAIM_COMPLETE.write(source); +} \ No newline at end of file diff --git a/kernel/src/arch/riscv32/interrupt.rs b/kernel/src/arch/riscv32/interrupt.rs index 17a0d7d2..2d952be7 100644 --- a/kernel/src/arch/riscv32/interrupt.rs +++ b/kernel/src/arch/riscv32/interrupt.rs @@ -34,14 +34,16 @@ pub fn init() { xtvec::write(trap_entry as usize, xtvec::TrapMode::Direct); // Enable IPI sie::set_ssoft(); - // Enable serial interrupt - #[cfg(feature = "m_mode")] - mie::set_mext(); - #[cfg(not(feature = "m_mode"))] - sie::set_sext(); - // NOTE: In M-mode: mie.MSIE is set by BBL. - // mie.MEIE can not be set in QEMU v3.0 - // (seems like a bug) + // Enable external interrupt + if super::cpu::id() == super::BOOT_HART_ID { + #[cfg(feature = "m_mode")] + mie::set_mext(); + #[cfg(not(feature = "m_mode"))] + sie::set_sext(); + // NOTE: In M-mode: mie.MSIE is set by BBL. + // mie.MEIE can not be set in QEMU v3.0 + // (seems like a bug) + } } info!("interrupt: init end"); } @@ -130,6 +132,9 @@ fn sbi(tf: &mut TrapFrame) { } fn external() { + #[cfg(feature = "board_u540")] + unsafe { super::board::handle_external_interrupt(); } + // true means handled, false otherwise let handlers = [try_process_serial, try_process_drivers]; for handler in handlers.iter() { diff --git a/kernel/src/arch/riscv32/memory.rs b/kernel/src/arch/riscv32/memory.rs index 48e91d46..21a84822 100644 --- a/kernel/src/arch/riscv32/memory.rs +++ b/kernel/src/arch/riscv32/memory.rs @@ -79,6 +79,10 @@ fn remap_the_kernel(dtb: usize) { ms.push(bootstack as usize, bootstacktop as usize, MemoryAttr::default(), Linear::new(offset), "stack"); ms.push(sbss as usize, ebss as usize, MemoryAttr::default(), Linear::new(offset), "bss"); ms.push(dtb, dtb + super::consts::MAX_DTB_SIZE, MemoryAttr::default().readonly(), Linear::new(offset), "dts"); + // map PLIC for HiFiveU + let offset = -(KERNEL_OFFSET as isize); + ms.push(KERNEL_OFFSET + 0x0C00_2000, KERNEL_OFFSET + 0x0C00_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic0"); + ms.push(KERNEL_OFFSET + 0x0C20_2000, KERNEL_OFFSET + 0x0C20_2000 + PAGE_SIZE, MemoryAttr::default(), Linear::new(offset), "plic1"); unsafe { ms.activate(); } unsafe { SATP = ms.token(); } mem::forget(ms); diff --git a/kernel/src/arch/riscv32/mod.rs b/kernel/src/arch/riscv32/mod.rs index 32fe8976..4b42ad0a 100644 --- a/kernel/src/arch/riscv32/mod.rs +++ b/kernel/src/arch/riscv32/mod.rs @@ -7,6 +7,9 @@ pub mod compiler_rt; pub mod consts; pub mod cpu; pub mod syscall; +#[cfg(feature = "board_u540")] +#[path = "board/u540/mod.rs"] +mod board; mod sbi; use log::*; @@ -36,6 +39,8 @@ pub extern fn rust_main(hartid: usize, dtb: usize, hart_mask: usize, functions: // FIXME: init driver on u540 #[cfg(not(feature = "board_u540"))] crate::drivers::init(dtb); + #[cfg(feature = "board_u540")] + unsafe { board::init_external_interrupt(); } crate::process::init(); unsafe { cpu::start_others(hart_mask); } diff --git a/riscv-pk b/riscv-pk index 2829915e..405ea59d 160000 --- a/riscv-pk +++ b/riscv-pk @@ -1 +1 @@ -Subproject commit 2829915ea12fba2e5fd4db2879e23311043a55b4 +Subproject commit 405ea59dd7dd2762c5883822f21d9995bea32b0c diff --git a/tools/u540/mkimg.sh b/tools/u540/mkimg.sh old mode 100644 new mode 100755