summaryrefslogtreecommitdiff
path: root/kernel/plic.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/plic.c')
-rw-r--r--kernel/plic.c63
1 files changed, 63 insertions, 0 deletions
diff --git a/kernel/plic.c b/kernel/plic.c
new file mode 100644
index 0000000..0f19ab0
--- /dev/null
+++ b/kernel/plic.c
@@ -0,0 +1,63 @@
+#include "types.h"
+#include "param.h"
+#include "memlayout.h"
+#include "riscv.h"
+#include "defs.h"
+
+//
+// the riscv Platform Level Interrupt Controller (PLIC).
+//
+
+void
+plicinit(void)
+{
+ // set uart's priority to be non-zero (otherwise disabled).
+ *(uint32*)(PLIC + UART0_IRQ*4) = 1;
+}
+
+void
+plicinithart(void)
+{
+ int hart = cpuid();
+
+ // set uart's enable bit for this hart's S-mode.
+ //*(uint32*)(PLIC + 0x2080)= (1 << UART0_IRQ);
+ *(uint32*)PLIC_SENABLE(hart)= (1 << UART0_IRQ);
+
+ // set this hart's S-mode priority threshold to 0.
+ //*(uint32*)(PLIC + 0x201000) = 0;
+ *(uint32*)PLIC_SPRIORITY(hart) = 0;
+}
+
+// return a bitmap of which IRQs are waiting
+// to be served.
+uint64
+plic_pending(void)
+{
+ uint64 mask;
+
+ //mask = *(uint32*)(PLIC + 0x1000);
+ //mask |= (uint64)*(uint32*)(PLIC + 0x1004) << 32;
+ mask = *(uint64*)PLIC_PENDING;
+
+ return mask;
+}
+
+// ask the PLIC what interrupt we should serve.
+int
+plic_claim(void)
+{
+ int hart = cpuid();
+ //int irq = *(uint32*)(PLIC + 0x201004);
+ int irq = *(uint32*)PLIC_SCLAIM(hart);
+ return irq;
+}
+
+// tell the PLIC we've served this IRQ.
+void
+plic_complete(int irq)
+{
+ int hart = cpuid();
+ //*(uint32*)(PLIC + 0x201004) = irq;
+ *(uint32*)PLIC_SCLAIM(hart) = irq;
+}