diff options
| author | Richard Qin <richard.qin.x@gmail.com> | 2025-12-31 19:00:20 +0800 |
|---|---|---|
| committer | Richard Qin <richard.qin.x@gmail.com> | 2025-12-31 19:00:20 +0800 |
| commit | 0a6815b7143a8ffd0e09777b5fbd12098d8884c2 (patch) | |
| tree | 1dc95d54891eb787b63bcaaaa842d88605de8d1c | |
| parent | 94005550703f85de9d1355dfa713d3250409d2c2 (diff) | |
| download | lume-0a6815b7143a8ffd0e09777b5fbd12098d8884c2.tar.gz lume-0a6815b7143a8ffd0e09777b5fbd12098d8884c2.tar.xz | |
dev: PILC implementation
| -rwxr-xr-x | build/kernel.elf | bin | 154536 -> 156920 bytes | |||
| -rw-r--r-- | build/src/drivers/plic.o | bin | 0 -> 13800 bytes | |||
| -rw-r--r-- | build/src/kernel/trap/handler.o | bin | 65848 -> 66984 bytes | |||
| -rw-r--r-- | include/drivers/plic.h | 17 | ||||
| -rw-r--r-- | src/drivers/plic.cc | 60 | ||||
| -rw-r--r-- | src/kernel/trap/handler.cc | 17 |
6 files changed, 94 insertions, 0 deletions
diff --git a/build/kernel.elf b/build/kernel.elf Binary files differindex 679a7bb..db7f94d 100755 --- a/build/kernel.elf +++ b/build/kernel.elf diff --git a/build/src/drivers/plic.o b/build/src/drivers/plic.o Binary files differnew file mode 100644 index 0000000..846035b --- /dev/null +++ b/build/src/drivers/plic.o diff --git a/build/src/kernel/trap/handler.o b/build/src/kernel/trap/handler.o Binary files differindex 570f268..43346a1 100644 --- a/build/src/kernel/trap/handler.o +++ b/build/src/kernel/trap/handler.o diff --git a/include/drivers/plic.h b/include/drivers/plic.h new file mode 100644 index 0000000..8e8d986 --- /dev/null +++ b/include/drivers/plic.h @@ -0,0 +1,17 @@ +#pragma once +#include "common/types.h" + +namespace PILC +{ + // Global initialization (executed only once by hart 0) + void init(); + + // Per-core initialization (executed when each CPU starts) + void inithart(); + + // Claim interrupt: Get the currently occurring interrupt number (IRQ) + int claim(); + + // End of interrupt: notify the PLIC that this IRQ has been handled + void complete(int irq); +} // namespace PILC 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<uint64>(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<uint64>(hart) * 0x2000; +} + +inline uint64 PLIC_SCLAIM(int hart) +{ + return PLIC_BASE + 0x201004 + static_cast<uint64>(hart) * 0x2000; +} + +namespace PILC +{ + void init() + { + *reinterpret_cast<uint32 *>(PLIC_PRIORITY + 10 * 4) = 1; // UART + *reinterpret_cast<uint32 *>(PLIC_PRIORITY + 1 * 4) = 1; // VirtIO 0 + } + + void inithart() + { + int hart = static_cast<int>(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<uint32 *>(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<uint32 *>(PLIC_STHRESHOLD(hart)) = 0; + } + + int claim() + { + int hart = static_cast<int>(r_tp()); + return *reinterpret_cast<uint32 *>(PLIC_SCLAIM(hart)); + } + + void complete(int irq) + { + int hart = static_cast<int>(r_tp()); + *reinterpret_cast<uint32 *>(PLIC_SCLAIM(hart)) = static_cast<uint32>(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) |
