restructure interrupt handling to be architecture-specific

This commit is contained in:
Garen Tyler 2023-11-09 18:29:34 -07:00
parent 33e1f3d318
commit d3d9526ffa
Signed by: garentyler
GPG Key ID: D7A048C454CB7054
8 changed files with 98 additions and 53 deletions

View File

@ -0,0 +1,10 @@
//! Architecture-agnostic interrupt handling.
#[cfg(target_arch = "riscv64")]
pub use super::riscv::plic::plic_claim as handle_interrupt;
#[cfg(target_arch = "riscv64")]
pub use super::riscv::plic::plic_complete as complete_interrupt;
#[cfg(target_arch = "riscv64")]
pub use super::riscv::plic::plicinit as init;
#[cfg(target_arch = "riscv64")]
pub use super::riscv::plic::plicinithart as inithart;

View File

@ -1 +1,4 @@
#[cfg(target_arch = "riscv64")]
pub mod riscv;
pub mod interrupt;

View File

@ -23,11 +23,11 @@ pub const QEMU_POWER: u64 = 0x100000u64;
// QEMU puts UART registers here in physical memory.
pub const UART0: usize = 0x10000000;
pub const UART0_IRQ: i32 = 10;
pub const UART0_IRQ: usize = 10;
// Virtio MMIO interface
pub const VIRTIO0: u64 = 0x10001000;
pub const VIRTIO0_IRQ: i32 = 1;
pub const VIRTIO0: usize = 0x10001000;
pub const VIRTIO0_IRQ: usize = 1;
// Core Local Interrupter (CLINT), which contains the timer.
pub const CLINT: u64 = 0x2000000;
@ -36,29 +36,6 @@ pub fn clint_mtimecmp(hartid: u64) -> u64 {
CLINT + 0x4000 + (8 * hartid)
}
// QEMU puts platform-level interrupt controller (PLIC) here.
pub const PLIC: u64 = 0x0c000000;
pub const PLIC_PRIORITY: u64 = PLIC;
pub const PLIC_PENDING: u64 = PLIC + 0x1000;
pub fn plic_menable(hartid: u64) -> u64 {
PLIC + 0x2000 + (0x100 * hartid)
}
pub fn plic_senable(hartid: u64) -> u64 {
PLIC + 0x2080 + (0x100 * hartid)
}
pub fn plic_mpriority(hartid: u64) -> u64 {
PLIC + 0x200000 + (0x2000 * hartid)
}
pub fn plic_spriority(hartid: u64) -> u64 {
PLIC + 0x201000 + (0x2000 * hartid)
}
pub fn plic_mclaim(hartid: u64) -> u64 {
PLIC + 0x200004 + (0x2000 * hartid)
}
pub fn plic_sclaim(hartid: u64) -> u64 {
PLIC + 0x201004 + (0x2000 * hartid)
}
// The kernel expects there to be RAM
// for use by the kernel and user pages
// from physical address 0x80000000 to PHYSTOP.

View File

@ -1,35 +1,67 @@
//! The RISC-V Platform Level Interrupt Controller (PLIC)
use crate::{
arch::riscv::{plic_sclaim, plic_senable, plic_spriority, PLIC, UART0_IRQ, VIRTIO0_IRQ},
arch::riscv::{UART0_IRQ, VIRTIO0_IRQ},
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.
fn plic_menable(hartid: usize) -> *mut u32 {
(PLIC + 0x2000 + (0x100 * hartid)) as *mut u32
}
/// Get a pointer to the CPU-specific supervisor-mode enable register.
fn plic_senable(hartid: usize) -> *mut u32 {
(PLIC + 0x2080 + (0x100 * hartid)) as *mut u32
}
/// Get a pointer to the CPU-specific machine-mode priority register.
fn plic_mpriority(hartid: usize) -> *mut u32 {
(PLIC + 0x200000 + (0x2000 * hartid)) as *mut u32
}
/// Get a pointer to the CPU-specific supervisor-mode priority register.
fn plic_spriority(hartid: usize) -> *mut u32 {
(PLIC + 0x201000 + (0x2000 * hartid)) as *mut u32
}
/// Get a pointer to the CPU-specific machine-mode claim register.
fn plic_mclaim(hartid: usize) -> *mut u32 {
(PLIC + 0x200004 + (0x2000 * hartid)) as *mut u32
}
/// Get a pointer to the CPU-specific supervisor-mode claim register.
fn plic_sclaim(hartid: usize) -> *mut u32 {
(PLIC + 0x201004 + (0x2000 * hartid)) as *mut u32
}
pub unsafe fn plicinit() {
// Set desired IRQ priorities non-zero (otherwise disabled).
*((PLIC + UART0_IRQ as u64 * 4) as *mut u32) = 1;
*((PLIC + VIRTIO0_IRQ as u64 * 4) as *mut u32) = 1;
*(UART0_IRQ_ADDR as *mut u32) = 1;
*(VIRTIO0_IRQ_ADDR as *mut u32) = 1;
}
pub unsafe fn plicinithart() {
let hart = Cpu::current_id() as u64;
let hart = Cpu::current_id();
// Set enable bits for this hart's S-mode
// for the UART and VIRTIO disk.
*(plic_senable(hart) as *mut u32) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);
*plic_senable(hart) = (1 << UART0_IRQ) | (1 << VIRTIO0_IRQ);
// Set this hart's S-mode priority threshold to 0.
*(plic_spriority(hart) as *mut u32) = 0;
*plic_spriority(hart) = 0;
}
/// Ask the PLIC what interrupt we should serve.
pub unsafe fn plic_claim() -> i32 {
let hart = Cpu::current_id() as u64;
*(plic_sclaim(hart) as *const i32)
pub unsafe fn plic_claim() -> usize {
let hart = Cpu::current_id();
(*plic_sclaim(hart)) as usize
}
/// Tell the PLIC we've served this IRQ.
pub unsafe fn plic_complete(irq: i32) {
let hart = Cpu::current_id() as u64;
*(plic_sclaim(hart) as *mut i32) = irq;
pub unsafe fn plic_complete(irq: usize) {
let hart = Cpu::current_id();
*plic_sclaim(hart) = irq as u32;
}

View File

@ -1,8 +1,6 @@
use crate::sync::lock::Lock;
use core::ffi::{c_char, CStr};
pub use crate::panic;
pub static PRINT_LOCK: Lock = Lock::new();
/// Print out formatted text to the console.
@ -40,7 +38,7 @@ macro_rules! uprint {
// only uses the &mut reference immutably.
let uart: *const Uart = &$crate::console::uart::UART0 as *const Uart;
let uart: &mut Uart = unsafe { &mut *uart.cast_mut() };
let _ = core::write!(uart, $($arg)*);
}};
}
@ -55,7 +53,6 @@ macro_rules! uprintln {
}
pub(crate) use uprintln;
#[no_mangle]
pub extern "C" fn printint(n: i32) {
print!("{}", n);

View File

@ -24,7 +24,7 @@ mod trap;
use crate::{proc::cpu::Cpu, sync::mutex::Mutex};
use core::ffi::{c_char, CStr};
pub(crate) use crate::console::printf::{print, println, uprint, uprintln};
pub(crate) use crate::console::printf::{print, println, uprintln};
pub static mut STARTED: bool = false;
pub static PANICKED: Mutex<bool> = Mutex::new(false);
@ -65,8 +65,8 @@ pub unsafe fn main() -> ! {
mem::virtual_memory::kvminithart();
proc::process::procinit();
trap::trapinithart();
arch::riscv::plic::plicinit();
arch::riscv::plic::plicinithart();
arch::interrupt::init();
arch::interrupt::inithart();
io::bio::binit();
fs::iinit();
fs::file::fileinit();
@ -79,7 +79,7 @@ pub unsafe fn main() -> ! {
}
mem::virtual_memory::kvminithart();
trap::trapinithart();
arch::riscv::plic::plicinithart();
arch::interrupt::inithart();
}
proc::scheduler::scheduler();

View File

@ -1,7 +1,21 @@
use crate::{
arch::riscv::{
memlayout::{KERNBASE, PHYSTOP, TRAMPOLINE},
*,
memlayout::{KERNBASE, PHYSTOP, TRAMPOLINE, UART0, VIRTIO0, QEMU_POWER},
plic::PLIC,
asm,
PGSIZE,
pg_round_down,
pg_round_up,
Pagetable,
PagetableEntry,
PTE_V,
PTE_R,
PTE_W,
PTE_X,
PTE_U,
MAXVA,
pte2pa,
make_satp,
},
mem::{
kalloc::{kalloc, kfree},
@ -33,10 +47,22 @@ pub unsafe fn kvmmake() -> Pagetable {
kvmmap(pagetable, UART0 as u64, UART0 as u64, PGSIZE, PTE_R | PTE_W);
// VirtIO MMIO disk interface
kvmmap(pagetable, VIRTIO0, VIRTIO0, PGSIZE, PTE_R | PTE_W);
kvmmap(
pagetable,
VIRTIO0 as u64,
VIRTIO0 as u64,
PGSIZE,
PTE_R | PTE_W,
);
// PLIC
kvmmap(pagetable, PLIC, PLIC, 0x400000u64, PTE_R | PTE_W);
kvmmap(
pagetable,
PLIC as u64,
PLIC as u64,
0x400000u64,
PTE_R | PTE_W,
);
let etext_addr = addr_of!(etext) as usize as u64;

View File

@ -1,5 +1,5 @@
use crate::{
arch::riscv::*,
arch::{self, riscv::*},
println,
proc::{
cpu::Cpu,
@ -49,7 +49,7 @@ pub unsafe fn devintr() -> i32 {
// This is a supervisor external interrupt, via PLIC.
// IRQ indicates which device interrupted.
let irq = plic::plic_claim();
let irq = arch::interrupt::handle_interrupt();
if irq == UART0_IRQ {
crate::console::uart::UART0.interrupt();
@ -63,7 +63,7 @@ pub unsafe fn devintr() -> i32 {
// interrupt at a time; tell the PLIC the device is
// now allowed to interrupt again.
if irq > 0 {
plic::plic_complete(irq);
arch::interrupt::complete_interrupt(irq);
}
1