diff --git a/kernel/rustkernel/src/arch/riscv/hardware.rs b/kernel/rustkernel/src/arch/riscv/hardware.rs index 25ddb0c..1387e8a 100644 --- a/kernel/rustkernel/src/arch/riscv/hardware.rs +++ b/kernel/rustkernel/src/arch/riscv/hardware.rs @@ -1,7 +1,3 @@ -// QEMU puts UART registers here in physical memory. -pub const UART0: usize = 0x10000000; -pub const UART0_IRQ: usize = 10; - // Virtio MMIO interface pub const VIRTIO0: usize = 0x10001000; pub const VIRTIO0_IRQ: usize = 1; diff --git a/kernel/rustkernel/src/arch/riscv/plic.rs b/kernel/rustkernel/src/arch/riscv/plic.rs index e12551e..650b4b3 100644 --- a/kernel/rustkernel/src/arch/riscv/plic.rs +++ b/kernel/rustkernel/src/arch/riscv/plic.rs @@ -1,13 +1,12 @@ //! The RISC-V Platform Level Interrupt Controller (PLIC) -use super::hardware::{UART0_IRQ, VIRTIO0_IRQ}; +use super::hardware::VIRTIO0_IRQ; use crate::proc::cpu::Cpu; // QEMU puts platform-level interrupt controller (PLIC) here. pub const PLIC: usize = 0x0c000000; const PLIC_PRIORITY: usize = PLIC; const PLIC_PENDING: usize = PLIC + 0x1000; -const UART0_IRQ_ADDR: usize = PLIC + UART0_IRQ * 4; const VIRTIO0_IRQ_ADDR: usize = PLIC + VIRTIO0_IRQ * 4; /// Get a pointer to the CPU-specific machine-mode enable register. @@ -37,7 +36,9 @@ fn plic_sclaim(hartid: usize) -> *mut u32 { pub unsafe fn plicinit() { // Set desired IRQ priorities non-zero (otherwise disabled). - *(UART0_IRQ_ADDR as *mut u32) = 1; + for (uart_irq, _) in &crate::hardware::UARTS { + *((PLIC + uart_irq * 4) as *mut u32) = 1; + } *(VIRTIO0_IRQ_ADDR as *mut u32) = 1; } @@ -46,7 +47,12 @@ pub unsafe fn plicinithart() { // Set enable bits for this hart's S-mode // for the UART and VIRTIO disk. - *plic_senable(hart) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ); + let mut enable_bits = 0; + for (uart_irq, _) in &crate::hardware::UARTS { + enable_bits |= 1 << uart_irq; + } + enable_bits |= 1 << VIRTIO0_IRQ; + *plic_senable(hart) = enable_bits; // Set this hart's S-mode priority threshold to 0. *plic_spriority(hart) = 0; diff --git a/kernel/rustkernel/src/arch/riscv/trap.rs b/kernel/rustkernel/src/arch/riscv/trap.rs index eefa7a9..1605611 100644 --- a/kernel/rustkernel/src/arch/riscv/trap.rs +++ b/kernel/rustkernel/src/arch/riscv/trap.rs @@ -1,7 +1,7 @@ use super::{asm, mem::make_satp, SSTATUS_SPIE, SSTATUS_SPP}; use crate::{ arch::{ - hardware::{UART0_IRQ, VIRTIO0_IRQ}, + hardware::VIRTIO0_IRQ, interrupt, mem::{PAGE_SIZE, TRAMPOLINE}, }, @@ -55,13 +55,21 @@ pub unsafe fn devintr() -> i32 { // IRQ indicates which device interrupted. let irq = interrupt::handle_interrupt(); - - if irq == UART0_IRQ { - crate::hardware::uart::UART0.interrupt(); - } else if irq == VIRTIO0_IRQ { - virtio_disk_intr(); - } else if irq > 0 { - println!("unexpected interrupt irq={}", irq); + + let mut uart_interrupt = false; + for (uart_irq, uart) in &crate::hardware::UARTS { + if irq == *uart_irq { + uart_interrupt = true; + uart.interrupt(); + } + } + + if !uart_interrupt { + if irq == VIRTIO0_IRQ { + virtio_disk_intr(); + } else if irq > 0 { + println!("unexpected interrupt irq={}", irq); + } } // The PLIC allows each device to raise at most one diff --git a/kernel/rustkernel/src/arch/riscv/virtual_memory.rs b/kernel/rustkernel/src/arch/riscv/virtual_memory.rs index 9fc9aa9..ccae751 100644 --- a/kernel/rustkernel/src/arch/riscv/virtual_memory.rs +++ b/kernel/rustkernel/src/arch/riscv/virtual_memory.rs @@ -7,7 +7,7 @@ use super::{ use crate::{ arch::{ self, - hardware::{UART0, VIRTIO0}, + hardware::VIRTIO0, mem::{ round_down_page, round_up_page, Pagetable, PagetableEntry, KERNEL_BASE, PAGE_SIZE, PHYSICAL_END, PTE_R, PTE_U, PTE_V, PTE_W, PTE_X, TRAMPOLINE, VIRTUAL_MAX, @@ -46,13 +46,15 @@ pub unsafe fn kvmmake() -> Pagetable { ); // UART registers - kvmmap( - pagetable, - UART0 as u64, - UART0 as u64, - PAGE_SIZE as u64, - PTE_R | PTE_W, - ); + for (_, uart) in &crate::hardware::UARTS { + kvmmap( + pagetable, + uart.base_address as u64, + uart.base_address as u64, + PAGE_SIZE as u64, + PTE_R | PTE_W, + ); + } // VirtIO MMIO disk interface kvmmap( diff --git a/kernel/rustkernel/src/console/mod.rs b/kernel/rustkernel/src/console/mod.rs index 5accd3c..c9ae4da 100644 --- a/kernel/rustkernel/src/console/mod.rs +++ b/kernel/rustkernel/src/console/mod.rs @@ -12,12 +12,12 @@ pub mod printf; use crate::{ fs::file::{devsw, CONSOLE}, - hardware::uart::UART0, proc::{ process::{procdump, Process}, scheduler::wakeup, }, sync::mutex::Mutex, + hardware::uart::Uart, }; use core::{ffi::c_void, ptr::addr_of_mut}; @@ -26,6 +26,8 @@ extern "C" { fn either_copyout(user_dst: i32, dst: u64, src: *mut c_void, len: u64) -> i32; } +pub static UART0: &'static Uart = &crate::hardware::UARTS[0].1; + pub const BACKSPACE: u8 = 0x00; pub const INPUT_BUF_SIZE: usize = 128; diff --git a/kernel/rustkernel/src/console/printf.rs b/kernel/rustkernel/src/console/printf.rs index 071a70e..8ba62bf 100644 --- a/kernel/rustkernel/src/console/printf.rs +++ b/kernel/rustkernel/src/console/printf.rs @@ -36,7 +36,7 @@ macro_rules! uprint { // Do some casts to get a mutable reference. // Safe because Uart's core::fmt::Write implementation // only uses the &mut reference immutably. - let uart: *const Uart = &$crate::hardware::uart::UART0 as *const Uart; + let uart: *const Uart = &$crate::hardware::UARTS[0].1 as *const Uart; let uart: &mut Uart = unsafe { &mut *uart.cast_mut() }; let _ = core::write!(uart, $($arg)*); diff --git a/kernel/rustkernel/src/hardware/mod.rs b/kernel/rustkernel/src/hardware/mod.rs index d4db234..53332ca 100644 --- a/kernel/rustkernel/src/hardware/mod.rs +++ b/kernel/rustkernel/src/hardware/mod.rs @@ -3,3 +3,9 @@ pub mod ramdisk; pub mod uart; pub mod virtio_disk; + +use uart::Uart; + +pub static UARTS: [(usize, Uart); 1] = [ + (10, Uart::new(0x1000_0000)), +]; diff --git a/kernel/rustkernel/src/hardware/uart.rs b/kernel/rustkernel/src/hardware/uart.rs index 8540962..b055efd 100644 --- a/kernel/rustkernel/src/hardware/uart.rs +++ b/kernel/rustkernel/src/hardware/uart.rs @@ -25,8 +25,6 @@ const LSR_RX_READY: u8 = 1 << 0; /// THR can accept another character to send const LSR_TX_IDLE: u8 = 1 << 5; -pub static UART0: Uart = Uart::new(crate::arch::hardware::UART0); - enum Register { ReceiveHolding, TransmitHolding,