push/pop all registers when handling interrupt from kernel
This commit is contained in:
parent
e630e0743b
commit
6eae1be755
4
Makefile
4
Makefile
|
@ -21,7 +21,9 @@ OBJS = \
|
|||
pipe.o \
|
||||
ramdisk.o \
|
||||
exec.o \
|
||||
sysfile.o
|
||||
sysfile.o \
|
||||
kernelvec.o \
|
||||
plic.o
|
||||
|
||||
XXXOBJS = \
|
||||
bio.o\
|
||||
|
|
6
defs.h
6
defs.h
|
@ -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]))
|
||||
|
|
60
entryother.S
60
entryother.S
|
@ -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
|
||||
|
1
main.c
1
main.c
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
57
trap.c
57
trap.c
|
@ -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();
|
||||
|
||||
panic("kerneltrap");
|
||||
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();
|
||||
|
||||
// restore previous interrupt status.
|
||||
w_sstatus(sstatus);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue