summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/drivers/plic.cc60
-rw-r--r--src/kernel/trap/handler.cc17
2 files changed, 77 insertions, 0 deletions
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)