From 0a6815b7143a8ffd0e09777b5fbd12098d8884c2 Mon Sep 17 00:00:00 2001 From: Richard Qin Date: Wed, 31 Dec 2025 19:00:20 +0800 Subject: dev: PILC implementation --- src/drivers/plic.cc | 60 ++++++++++++++++++++++++++++++++++++++++++++++ src/kernel/trap/handler.cc | 17 +++++++++++++ 2 files changed, 77 insertions(+) create mode 100644 src/drivers/plic.cc (limited to 'src') diff --git a/src/drivers/plic.cc b/src/drivers/plic.cc new file mode 100644 index 0000000..a13537c --- /dev/null +++ b/src/drivers/plic.cc @@ -0,0 +1,60 @@ +#include "common/types.h" +#include "kernel/riscv.h" +#include "drivers/plic.h" + +// QEMU Virt PLIC address constants +constexpr uint64 PLIC_BASE = 0x0c000000L; +constexpr uint64 PLIC_PRIORITY = PLIC_BASE + 0x0; +constexpr uint64 PLIC_PENDING = PLIC_BASE + 0x1000; + +// S-Mode interrupt enable register: each Hart occupies 0x100 bytes +// Context 1 is Hart 0 S-Mode, Context 3 is Hart 1 S-Mode... +inline uint64 PLIC_SENABLE(int hart) +{ + return PLIC_BASE + 0x2080 + static_cast(hart) * 0x100; +} + +// S-Mode priority threshold and claim register: 0x2000 bytes per Hart +inline uint64 PLIC_STHRESHOLD(int hart) +{ + return PLIC_BASE + 0x201000 + static_cast(hart) * 0x2000; +} + +inline uint64 PLIC_SCLAIM(int hart) +{ + return PLIC_BASE + 0x201004 + static_cast(hart) * 0x2000; +} + +namespace PILC +{ + void init() + { + *reinterpret_cast(PLIC_PRIORITY + 10 * 4) = 1; // UART + *reinterpret_cast(PLIC_PRIORITY + 1 * 4) = 1; // VirtIO 0 + } + + void inithart() + { + int hart = static_cast(r_tp()); // 获取当前 hartid + + // Enable UART and VirtIO interrupts for the current Hart's S-Mode + // Set bit 10 and bit 1 in the register bitmap + *reinterpret_cast(PLIC_SENABLE(hart)) = (1 << 10) | (1 << 1); + + // Set the current Hart's S-Mode priority threshold to 0 + // Only interrupts with a priority higher than this threshold will be delivered + *reinterpret_cast(PLIC_STHRESHOLD(hart)) = 0; + } + + int claim() + { + int hart = static_cast(r_tp()); + return *reinterpret_cast(PLIC_SCLAIM(hart)); + } + + void complete(int irq) + { + int hart = static_cast(r_tp()); + *reinterpret_cast(PLIC_SCLAIM(hart)) = static_cast(irq); + } +} // namespace PILC diff --git a/src/kernel/trap/handler.cc b/src/kernel/trap/handler.cc index f7f8725..d7f78de 100644 --- a/src/kernel/trap/handler.cc +++ b/src/kernel/trap/handler.cc @@ -5,6 +5,7 @@ #include "kernel/syscall.h" #include "kernel/mm.h" #include "kernel/timer.h" +#include "drivers/plic.h" #include "lib/string.h" @@ -58,6 +59,22 @@ namespace Trap if (is_interrupt && code == 9) { // Supervisor External Interrupt (IRQ 9) + int irq = PILC::claim(); + + if (irq == 10) + { + // uart_intr(); + } + else if (irq >= 1 && irq <= 8) + { + // virtio_disk_intr(); + } + + if (irq > 0) + { + PILC::complete(irq); + } + return 1; } else if (is_interrupt && code == 5) -- cgit v1.2.3