takes one uart input interrupt, then panics

This commit is contained in:
Robert Morris 2019-06-03 14:13:07 -04:00
parent 50cbc75102
commit a9c1a6f742
6 changed files with 108 additions and 6 deletions

View file

@ -13,9 +13,12 @@
// end -- start of kernel page allocation area // end -- start of kernel page allocation area
// PHYSTOP -- end RAM used by the kernel // PHYSTOP -- end RAM used by the kernel
// registers start here in physical memory. // qemu puts UART registers here in physical memory.
#define UART0 0x10000000L #define UART0 0x10000000L
// qemu puts programmable interrupt controller here.
#define PLIC 0x0c000000L
#define RAMDISK 0x88000000 #define RAMDISK 0x88000000
// the kernel expects there to be RAM // the kernel expects there to be RAM

16
proc.c
View file

@ -365,6 +365,22 @@ scheduler(void)
// Enable interrupts on this processor. // Enable interrupts on this processor.
// XXX riscv // XXX riscv
//sti(); //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. // Loop over process table looking for process to run.
acquire(&ptable.lock); acquire(&ptable.lock);

56
riscv.h
View file

@ -30,7 +30,11 @@ w_mepc(uint64 x)
// Supervisor Status Register, sstatus // 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 static inline uint64
r_sstatus() r_sstatus()
@ -46,6 +50,33 @@ w_sstatus(uint64 x)
asm("csrw sstatus, %0" : : "r" (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 // machine exception program counter, holds the
// instruction address to which a return from // instruction address to which a return from
// exception will go. // exception will go.
@ -147,6 +178,29 @@ r_stval()
return x; 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 PGSIZE 4096 // bytes per page
#define PGSHIFT 12 // bits of offset within a page #define PGSHIFT 12 // bits of offset within a page

13
trap.c
View file

@ -42,6 +42,19 @@ usertrap(void)
// save user program counter. // save user program counter.
p->tf->epc = r_sepc(); 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){ if(r_scause() == 8){
// system call // system call

19
uart.c
View file

@ -1,4 +1,10 @@
#include "types.h"
#include "param.h"
#include "memlayout.h" #include "memlayout.h"
#include "riscv.h"
#include "proc.h"
#include "spinlock.h"
#include "defs.h"
// //
// qemu -machine virt has a 16550a UART // qemu -machine virt has a 16550a UART
@ -9,12 +15,12 @@
// //
// address of one of the registers // address of one of the registers
#define R(reg) ((unsigned int*)(UART0 + 4*(reg))) #define R(reg) ((volatile unsigned char *)(UART0 + reg))
void void
uartinit(void) uartinit(void)
{ {
// disable interrupts // disable interrupts -- IER
*R(1) = 0x00; *R(1) = 0x00;
// special mode to set baud rate // special mode to set baud rate
@ -30,8 +36,11 @@ uartinit(void)
// and set word length to 8 bits, no parity. // and set word length to 8 bits, no parity.
*R(3) = 0x03; *R(3) = 0x03;
// reset and enable FIFOs. // reset and enable FIFOs -- FCR.
*R(2) = 0x07; *R(2) = 0x07;
// enable receive interrupts -- IER.
*R(1) = 0x01;
} }
void void
@ -40,9 +49,11 @@ uartputc(int c)
*R(0) = c; *R(0) = c;
} }
static int uint
uartgetc(void) uartgetc(void)
{ {
// XXX this isn't right, must check there's data in the FIFO.
return *R(0);
} }
void void

5
vm.c
View file

@ -30,6 +30,11 @@ kvminit()
mappages(kernel_pagetable, UART0, PGSIZE, mappages(kernel_pagetable, UART0, PGSIZE,
UART0, PTE_R | PTE_W); UART0, PTE_R | PTE_W);
// PLIC
mappages(kernel_pagetable, PLIC, 0x4000000,
PLIC, PTE_R | PTE_W);
// map kernel text executable and read-only. // map kernel text executable and read-only.
mappages(kernel_pagetable, KERNBASE, (uint64)etext-KERNBASE, mappages(kernel_pagetable, KERNBASE, (uint64)etext-KERNBASE,
KERNBASE, PTE_R | PTE_X); KERNBASE, PTE_R | PTE_X);