From a9c1a6f742886a9d45e5c625cf4f9b1b5c7a8cc4 Mon Sep 17 00:00:00 2001 From: Robert Morris Date: Mon, 3 Jun 2019 14:13:07 -0400 Subject: [PATCH] takes one uart input interrupt, then panics --- memlayout.h | 5 ++++- proc.c | 16 +++++++++++++++ riscv.h | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++- trap.c | 13 +++++++++++++ uart.c | 19 ++++++++++++++---- vm.c | 5 +++++ 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);