diff options
| author | Robert Morris <rtm@csail.mit.edu> | 2019-06-03 14:13:07 -0400 | 
|---|---|---|
| committer | Robert Morris <rtm@csail.mit.edu> | 2019-06-03 14:13:07 -0400 | 
| commit | a9c1a6f742886a9d45e5c625cf4f9b1b5c7a8cc4 (patch) | |
| tree | ff50c8aa95dbdc5f35954e586933ad63676c69c4 | |
| parent | 50cbc7510250a64674d619d13f5912edf08b767d (diff) | |
| download | xv6-labs-a9c1a6f742886a9d45e5c625cf4f9b1b5c7a8cc4.tar.gz xv6-labs-a9c1a6f742886a9d45e5c625cf4f9b1b5c7a8cc4.tar.bz2 xv6-labs-a9c1a6f742886a9d45e5c625cf4f9b1b5c7a8cc4.zip | |
takes one uart input interrupt, then panics
| -rw-r--r-- | memlayout.h | 5 | ||||
| -rw-r--r-- | proc.c | 16 | ||||
| -rw-r--r-- | riscv.h | 56 | ||||
| -rw-r--r-- | trap.c | 13 | ||||
| -rw-r--r-- | uart.c | 19 | ||||
| -rw-r--r-- | 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 @@ -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); @@ -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 @@ -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 @@ -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 @@ -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); | 
