diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -rw-r--r-- | defs.h | 6 | ||||
| -rw-r--r-- | entryother.S | 60 | ||||
| -rw-r--r-- | main.c | 1 | ||||
| -rw-r--r-- | memlayout.h | 1 | ||||
| -rw-r--r-- | trap.c | 57 | ||||
| -rw-r--r-- | uart.c | 2 | 
7 files changed, 48 insertions, 83 deletions
| @@ -21,7 +21,9 @@ OBJS = \    pipe.o \    ramdisk.o \    exec.o \ -  sysfile.o +  sysfile.o \ +  kernelvec.o \ +  plic.o  XXXOBJS = \  	bio.o\ @@ -191,5 +191,11 @@ int             copyout(pagetable_t, uint64, char *, uint64);  int             copyin(pagetable_t, char *, uint64, uint64);  int             copyinstr(pagetable_t pagetable, char *dst, uint64 srcva, uint64 max); +// plic.c +void            plicinit(void); +uint64          plic_pending(void); +int             plic_claim(void); +void            plic_complete(int); +  // number of elements in fixed-size array  #define NELEM(x) (sizeof(x)/sizeof((x)[0])) diff --git a/entryother.S b/entryother.S deleted file mode 100644 index dd33680..0000000 --- a/entryother.S +++ /dev/null @@ -1,60 +0,0 @@ -#include "asm.h" -#include "memlayout.h" -#include "mmu.h" -	 -# Each non-boot CPU ("AP") is started up in response to a STARTUP -# IPI from the boot CPU.  Section B.4.2 of the Multi-Processor -# Specification says that the AP will start in real mode with CS:IP -# set to XY00:0000, where XY is an 8-bit value sent with the -# STARTUP. Thus this code must start at a 4096-byte boundary. -# -# Because this code sets DS to zero, it must sit -# at an address in the low 2^16 bytes. -# -# Startothers (in main.c) sends the STARTUPs one at a time. -# It copies this code (start) at 0x7000.  It puts the address of -# a newly allocated per-core stack in start-12,the address of the -# place to jump to (apstart32) in start-4, and the physical address -# of entrypgdir in start-12. - -.code16            -.globl start -start: -  cli             - -  # Zero data segment registers DS, ES, and SS. -  xorw    %ax,%ax -  movw    %ax,%ds -  movw    %ax,%es -  movw    %ax,%ss - -  # Switch from real to protected mode.  Use a bootstrap GDT that makes -  # virtual addresses map directly to physical addresses so that the -  # effective memory map doesn't change during the transition. -  lgdt    gdtdesc -  movl    %cr0, %eax -  orl     $CR0_PE, %eax -  movl    %eax, %cr0 - -  # Complete the transition to 32-bit protected mode by using a long jmp -  # to reload %cs and %eip.  The segment descriptors are set up with no -  # translation, so that the mapping is still the identity mapping. -  ljmpl    $(SEG_KCODE32), $start32 - -.code32 -start32: - movl $start-12, %esp - movl start-4, %ecx - jmp *%ecx - -.align 4 -gdt: -  SEG_NULLASM -  SEG_ASM(0xa, 0, 0xffffffff) -  SEG_ASM(0x2, 0, 0xffffffff) - -.align  16 -gdtdesc: -  .word   0x17 # sizeof(gdt)-1 -  .long   gdt - @@ -17,6 +17,7 @@ main()    kvminit();       // kernel page table    procinit();      // process table    trapinit();      // trap vectors +  plicinit();      // set up interrupt controller    binit();         // buffer cache    fileinit();      // file table    ramdiskinit();   // disk diff --git a/memlayout.h b/memlayout.h index 9782ff1..1a6b200 100644 --- a/memlayout.h +++ b/memlayout.h @@ -15,6 +15,7 @@  // qemu puts UART registers here in physical memory.  #define UART0 0x10000000L +#define UART0_IRQ 10  // qemu puts programmable interrupt controller here.  #define PLIC 0x0c000000L @@ -11,28 +11,16 @@ uint ticks;  extern char trampout[], trampin[]; -void kerneltrap(); +// in kernelvec.S, calls kerneltrap(). +void kernelvec();  void  trapinit(void)  {    int i; -  // send interrupts and exceptions to kerneltrap(). -  w_stvec((uint64)kerneltrap); - -  // set up the riscv Platform Level Interrupt Controller -  // to send uart interrupts to hart 0 S-Mode. - -  // 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); - -  // set hart 0 S-mode priority threshold to 0. -  *(uint*)0x0c201000 = 0; +  // set up to take exceptions and traps while in the kernel. +  w_stvec((uint64)kernelvec);    initlock(&tickslock, "time");  } @@ -49,7 +37,7 @@ usertrap(void)    // send interrupts and exceptions to kerneltrap(),    // since we're now in the kernel. -  w_stvec((uint64)kerneltrap); +  w_stvec((uint64)kernelvec);    struct proc *p = myproc(); @@ -83,8 +71,9 @@ usertrapret(void)  {    struct proc *p = myproc(); -  // XXX turn off interrupts, since we're switching +  // turn off interrupts, since we're switching    // now from kerneltrap() to usertrap(). +  intr_off();    // send interrupts and exceptions to trampoline.S    w_stvec(TRAMPOLINE + (trampin - trampout)); @@ -101,6 +90,7 @@ usertrapret(void)    // set S Previous Privilege mode to User.    unsigned long x = r_sstatus();    x &= ~SSTATUS_SPP; // clear SPP to 0 for user mode +  x |= SSTATUS_SPIE; // enable interrupts in user mode    w_sstatus(x);    // set S Exception Program Counter to the saved user pc. @@ -121,11 +111,34 @@ usertrapret(void)  void __attribute__ ((aligned (4)))  kerneltrap()  { -  if((r_sstatus() & SSTATUS_SPP) == 0) +  uint64 sstatus = r_sstatus(); +  uint64 scause = r_scause(); +   +  if((sstatus & SSTATUS_SPP) == 0)      panic("kerneltrap: not from supervisor mode"); -  printf("scause 0x%x\n", r_scause()); -  printf("sepc=%p stval=%p\n", r_sepc(), r_stval()); +  if((scause & 0x8000000000000000L) && +     (scause & 0xff) == 9){ +    // supervisor external interrupt, via PLIC. +    int irq = plic_claim(); + +    if(irq == UART0_IRQ){ +      uartintr(); +    } else { +      printf("stray interrupt irq=%d\n", irq); +    } + +    plic_complete(irq); +  } else { +    printf("scause 0x%p\n", scause); +    printf("sepc=%p stval=%p\n", r_sepc(), r_stval()); +    panic("kerneltrap"); +  } + +  // turn off interrupts to ensure we +  // return with the correct sstatus. +  intr_off(); -  panic("kerneltrap"); +  // restore previous interrupt status. +  w_sstatus(sstatus);  } @@ -59,4 +59,6 @@ uartgetc(void)  void  uartintr(void)  { +  int c = uartgetc(); +  printf("%x ", c & 0xff);  } | 
