summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--memlayout.h5
-rw-r--r--proc.c16
-rw-r--r--riscv.h56
-rw-r--r--trap.c13
-rw-r--r--uart.c19
-rw-r--r--vm.c5
6 files changed, 108 insertions, 6 deletions
diff --git a/memlayout.h b/memlayout.h
index 9bc9c5d..9782ff1 100644
--- a/memlayout.h
+++ b/memlayout.h
@@ -13,9 +13,12 @@
// end -- start of kernel page allocation area
// PHYSTOP -- end RAM used by the kernel
-// registers start here in physical memory.
+// qemu puts UART registers here in physical memory.
#define UART0 0x10000000L
+// qemu puts programmable interrupt controller here.
+#define PLIC 0x0c000000L
+
#define RAMDISK 0x88000000
// the kernel expects there to be RAM
diff --git a/proc.c b/proc.c
index 909b88d..36b767d 100644
--- a/proc.c
+++ b/proc.c
@@ -365,6 +365,22 @@ scheduler(void)
// Enable interrupts on this processor.
// XXX riscv
//sti();
+
+ if(0){ uint x = * (uint*) 0xc001000;
+ if(x != 0){
+ printf("pending %x\n", x);
+ }
+ x = *(uint*)0xc001004;
+ if(x != 0)
+ printf("pending %x\n", x);
+ }
+
+ if(0){
+ uint uartgetc(void);
+ uint x = uartgetc();
+ if(x != 0)
+ printf("%x ", x);
+ }
// Loop over process table looking for process to run.
acquire(&ptable.lock);
diff --git a/riscv.h b/riscv.h
index 5e54935..6ecee84 100644
--- a/riscv.h
+++ b/riscv.h
@@ -30,7 +30,11 @@ w_mepc(uint64 x)
// Supervisor Status Register, sstatus
-#define SSTATUS_SPP (1L << 8) // 1=Supervisor, 0=User
+#define SSTATUS_SPP (1L << 8) // Previous mode, 1=Supervisor, 0=User
+#define SSTATUS_SPIE (1L << 5) // Supervisor Previous Interrupt Enable
+#define SSTATUS_UPIE (1L << 4) // User Previous Interrupt Enable
+#define SSTATUS_SIE (1L << 1) // Supervisor Interrupt Enable
+#define SSTATUS_UIE (1L << 0) // User Interrupt Enable
static inline uint64
r_sstatus()
@@ -46,6 +50,33 @@ w_sstatus(uint64 x)
asm("csrw sstatus, %0" : : "r" (x));
}
+// Supervisor Interrupt Pending
+static inline uint64
+r_sip()
+{
+ uint64 x;
+ asm("csrr %0, sip" : "=r" (x) );
+ return x;
+}
+
+// Supervisor Interrupt Enable
+#define SIE_SEIE (1L << 9) // external
+#define SIE_STIE (1L << 5) // timer
+#define SIE_SSIE (1L << 1) // software
+static inline uint64
+r_sie()
+{
+ uint64 x;
+ asm("csrr %0, sie" : "=r" (x) );
+ return x;
+}
+
+static inline void
+w_sie(uint64 x)
+{
+ asm("csrw sie, %0" : : "r" (x));
+}
+
// machine exception program counter, holds the
// instruction address to which a return from
// exception will go.
@@ -147,6 +178,29 @@ r_stval()
return x;
}
+// enable interrupts
+static inline void
+intr_on()
+{
+ w_sie(r_sie() | SIE_SEIE | SIE_STIE | SIE_SSIE);
+ w_sstatus(r_sstatus() | SSTATUS_SIE);
+}
+
+// disable interrupts
+static inline void
+intr_off()
+{
+ w_sstatus(r_sstatus() & ~SSTATUS_SIE);
+}
+
+// are interrupts enabled?
+static inline int
+intr_get()
+{
+ uint64 x = r_sstatus();
+ return (x & SSTATUS_SIE) != 0;
+}
+
#define PGSIZE 4096 // bytes per page
#define PGSHIFT 12 // bits of offset within a page
diff --git a/trap.c b/trap.c
index 74f3456..2b8fd41 100644
--- a/trap.c
+++ b/trap.c
@@ -42,6 +42,19 @@ usertrap(void)
// save user program counter.
p->tf->epc = r_sepc();
+
+ // PLIC setup
+ // qemu makes UART0 be interrupt number 10.
+ int irq = 10;
+ // set uart's priority to be non-zero (otherwise disabled).
+ *(uint*)(0x0c000000L + irq*4) = 1;
+ // set uart's enable bit for hart 0 s-mode.
+ *(uint*)0x0c002080 = (1 << irq);
+
+ // hart 0 S-mode priority threshold.
+ *(uint*)0x0c201000 = 0;
+
+ intr_on();
if(r_scause() == 8){
// system call
diff --git a/uart.c b/uart.c
index 9a77c5a..807c46e 100644
--- a/uart.c
+++ b/uart.c
@@ -1,4 +1,10 @@
+#include "types.h"
+#include "param.h"
#include "memlayout.h"
+#include "riscv.h"
+#include "proc.h"
+#include "spinlock.h"
+#include "defs.h"
//
// qemu -machine virt has a 16550a UART
@@ -9,12 +15,12 @@
//
// address of one of the registers
-#define R(reg) ((unsigned int*)(UART0 + 4*(reg)))
+#define R(reg) ((volatile unsigned char *)(UART0 + reg))
void
uartinit(void)
{
- // disable interrupts
+ // disable interrupts -- IER
*R(1) = 0x00;
// special mode to set baud rate
@@ -30,8 +36,11 @@ uartinit(void)
// and set word length to 8 bits, no parity.
*R(3) = 0x03;
- // reset and enable FIFOs.
+ // reset and enable FIFOs -- FCR.
*R(2) = 0x07;
+
+ // enable receive interrupts -- IER.
+ *R(1) = 0x01;
}
void
@@ -40,9 +49,11 @@ uartputc(int c)
*R(0) = c;
}
-static int
+uint
uartgetc(void)
{
+ // XXX this isn't right, must check there's data in the FIFO.
+ return *R(0);
}
void
diff --git a/vm.c b/vm.c
index 791f78f..7f9ef14 100644
--- a/vm.c
+++ b/vm.c
@@ -30,6 +30,11 @@ kvminit()
mappages(kernel_pagetable, UART0, PGSIZE,
UART0, PTE_R | PTE_W);
+ // PLIC
+ mappages(kernel_pagetable, PLIC, 0x4000000,
+ PLIC, PTE_R | PTE_W);
+
+
// map kernel text executable and read-only.
mappages(kernel_pagetable, KERNBASE, (uint64)etext-KERNBASE,
KERNBASE, PTE_R | PTE_X);