timer interrupts -> supervisor software interrupt
This commit is contained in:
parent
cff3ce6e04
commit
a82772594e
4
fs.c
4
fs.c
|
@ -182,10 +182,6 @@ iinit(int dev)
|
|||
readsb(dev, &sb);
|
||||
if(sb.magic != FSMAGIC)
|
||||
panic("invalid file system");
|
||||
printf("sb: size %d nblocks %d ninodes %d nlog %d logstart %d\
|
||||
inodestart %d bmap start %d\n", sb.size, sb.nblocks,
|
||||
sb.ninodes, sb.nlog, sb.logstart, sb.inodestart,
|
||||
sb.bmapstart);
|
||||
}
|
||||
|
||||
static struct inode* iget(uint dev, uint inum);
|
||||
|
|
13
memlayout.h
13
memlayout.h
|
@ -1,7 +1,10 @@
|
|||
// Physical memory layout
|
||||
|
||||
// qemu -machine virt is set up like this:
|
||||
// qemu -machine virt is set up like this,
|
||||
// based on qemu's hw/riscv/virt.c:
|
||||
//
|
||||
// 00001000 -- boot ROM, provided by qemu
|
||||
// 02000000 -- CLINT
|
||||
// 0C000000 -- PLIC
|
||||
// 10000000 -- uart0 registers
|
||||
// 80000000 -- boot ROM jumps here in machine mode
|
||||
|
@ -18,10 +21,16 @@
|
|||
#define UART0 0x10000000L
|
||||
#define UART0_IRQ 10
|
||||
|
||||
// local interrupt controller, which contains the timer.
|
||||
#define CLINT 0x2000000L
|
||||
#define CLINT_MSIP0 (CLINT + 0x0)
|
||||
#define CLINT_MTIMECMP0 (CLINT + 0x4000)
|
||||
#define CLINT_MTIME (CLINT + 0xBFF8)
|
||||
|
||||
// qemu puts programmable interrupt controller here.
|
||||
#define PLIC 0x0c000000L
|
||||
|
||||
#define RAMDISK 0x88000000
|
||||
#define RAMDISK 0x88000000L
|
||||
|
||||
// the kernel expects there to be RAM
|
||||
// for use by the kernel and user pages
|
||||
|
|
62
riscv.h
62
riscv.h
|
@ -4,6 +4,7 @@
|
|||
#define MSTATUS_MPP_M (3L << 11)
|
||||
#define MSTATUS_MPP_S (1L << 11)
|
||||
#define MSTATUS_MPP_U (0L << 11)
|
||||
#define MSTATUS_MIE (1L << 3)
|
||||
|
||||
static inline uint64
|
||||
r_mstatus()
|
||||
|
@ -59,6 +60,12 @@ r_sip()
|
|||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_sip(uint64 x)
|
||||
{
|
||||
asm("csrw sip, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Supervisor Interrupt Enable
|
||||
#define SIE_SEIE (1L << 9) // external
|
||||
#define SIE_STIE (1L << 5) // timer
|
||||
|
@ -77,6 +84,24 @@ w_sie(uint64 x)
|
|||
asm("csrw sie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Machine-mode Interrupt Enable
|
||||
#define MIE_MEIE (1L << 11) // external
|
||||
#define MIE_MTIE (1L << 7) // timer
|
||||
#define MIE_MSIE (1L << 3) // software
|
||||
static inline uint64
|
||||
r_mie()
|
||||
{
|
||||
uint64 x;
|
||||
asm("csrr %0, mie" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_mie(uint64 x)
|
||||
{
|
||||
asm("csrw mie, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// machine exception program counter, holds the
|
||||
// instruction address to which a return from
|
||||
// exception will go.
|
||||
|
@ -140,6 +165,13 @@ r_stvec()
|
|||
return x;
|
||||
}
|
||||
|
||||
// Machine-mode interrupt vector
|
||||
static inline void
|
||||
w_mtvec(uint64 x)
|
||||
{
|
||||
asm("csrw mtvec, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// use riscv's sv39 page table scheme.
|
||||
#define SATP_SV39 (8L << 60)
|
||||
|
||||
|
@ -168,6 +200,12 @@ w_sscratch(uint64 x)
|
|||
asm("csrw sscratch, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline void
|
||||
w_mscratch(uint64 x)
|
||||
{
|
||||
asm("csrw mscratch, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
// Supervisor Trap Cause
|
||||
static inline uint64
|
||||
r_scause()
|
||||
|
@ -186,6 +224,30 @@ r_stval()
|
|||
return x;
|
||||
}
|
||||
|
||||
// Machine-mode Counter-Enable
|
||||
static inline void
|
||||
w_mcounteren(uint64 x)
|
||||
{
|
||||
asm("csrw mcounteren, %0" : : "r" (x));
|
||||
}
|
||||
|
||||
static inline uint64
|
||||
r_mcounteren()
|
||||
{
|
||||
uint64 x;
|
||||
asm("csrr %0, mcounteren" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// machine-mode cycle counter
|
||||
static inline uint64
|
||||
r_time()
|
||||
{
|
||||
uint64 x;
|
||||
asm("csrr %0, time" : "=r" (x) );
|
||||
return x;
|
||||
}
|
||||
|
||||
// enable interrupts
|
||||
static inline void
|
||||
intr_on()
|
||||
|
|
24
start.c
24
start.c
|
@ -8,6 +8,19 @@ void main();
|
|||
// entry.S uses this as the initial stack.
|
||||
__attribute__ ((aligned (16))) char stack0[4096];
|
||||
|
||||
// assembly code in kernelvec for machine-mode timer interrupt.
|
||||
extern void machinevec();
|
||||
|
||||
// scratch area for timer interrupt.
|
||||
uint64 mscratch0[8];
|
||||
|
||||
__attribute__ ((aligned (16)))
|
||||
void
|
||||
xyzzy()
|
||||
{
|
||||
uartputc('I');
|
||||
}
|
||||
|
||||
// entry.S jumps here in machine mode on stack0.
|
||||
void
|
||||
mstart()
|
||||
|
@ -28,7 +41,16 @@ mstart()
|
|||
// delegate all interrupts and exceptions to supervisor mode.
|
||||
w_medeleg(0xffff);
|
||||
w_mideleg(0xffff);
|
||||
|
||||
|
||||
// set up to receive timer interrupts in machine mode.
|
||||
*(uint64*)CLINT_MTIMECMP0 = *(uint64*)CLINT_MTIME + 10000;
|
||||
mscratch0[4] = CLINT_MTIMECMP0;
|
||||
mscratch0[5] = 10000000;
|
||||
w_mscratch((uint64)mscratch0);
|
||||
w_mtvec((uint64)machinevec);
|
||||
w_mstatus(r_mstatus() | MSTATUS_MIE);
|
||||
w_mie(r_mie() | MIE_MTIE);
|
||||
|
||||
// jump to main in supervisor mode.
|
||||
asm("mret");
|
||||
}
|
||||
|
|
65
trap.c
65
trap.c
|
@ -14,6 +14,8 @@ extern char trampout[], trampin[];
|
|||
// in kernelvec.S, calls kerneltrap().
|
||||
void kernelvec();
|
||||
|
||||
extern int devintr();
|
||||
|
||||
void
|
||||
trapinit(void)
|
||||
{
|
||||
|
@ -22,6 +24,8 @@ trapinit(void)
|
|||
// set up to take exceptions and traps while in the kernel.
|
||||
w_stvec((uint64)kernelvec);
|
||||
|
||||
// time, cycle, instret CSRs
|
||||
|
||||
initlock(&tickslock, "time");
|
||||
}
|
||||
|
||||
|
@ -39,6 +43,10 @@ usertrap(void)
|
|||
// since we're now in the kernel.
|
||||
w_stvec((uint64)kernelvec);
|
||||
|
||||
//printf("mtimecmp %x mtime %x\n", *(uint64*)CLINT_MTIMECMP0, *(uint64*)CLINT_MTIME);
|
||||
|
||||
*(uint64*)CLINT_MTIMECMP0 = *(uint64*)CLINT_MTIME + 10000;
|
||||
|
||||
struct proc *p = myproc();
|
||||
|
||||
// save user program counter.
|
||||
|
@ -54,8 +62,10 @@ usertrap(void)
|
|||
p->tf->epc += 4;
|
||||
|
||||
syscall();
|
||||
} else if(devintr()){
|
||||
// ok
|
||||
} else {
|
||||
printf("usertrap(): unexpected scause 0x%x pid=%d\n", r_scause(), p->pid);
|
||||
printf("usertrap(): unexpected scause 0x%p pid=%d\n", r_scause(), p->pid);
|
||||
printf(" sepc=%p stval=%p\n", r_sepc(), r_stval());
|
||||
p->killed = 1;
|
||||
}
|
||||
|
@ -120,19 +130,7 @@ kerneltrap()
|
|||
if((sstatus & SSTATUS_SPP) == 0)
|
||||
panic("kerneltrap: not from supervisor mode");
|
||||
|
||||
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 {
|
||||
if(devintr() == 0){
|
||||
printf("scause 0x%p\n", scause);
|
||||
printf("sepc=%p stval=%p\n", r_sepc(), r_stval());
|
||||
panic("kerneltrap");
|
||||
|
@ -145,3 +143,42 @@ kerneltrap()
|
|||
// restore previous interrupt status.
|
||||
w_sstatus(sstatus);
|
||||
}
|
||||
|
||||
// check if it's an external interrupt or software interrupt,
|
||||
// and handle it.
|
||||
// returns 1 if handled, 0 if not recognized.
|
||||
int
|
||||
devintr()
|
||||
{
|
||||
uint64 scause = r_scause();
|
||||
|
||||
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);
|
||||
return 1;
|
||||
} else if(scause == 0x8000000000000001){
|
||||
// software interrupt from a machine-mode timer interrupt.
|
||||
|
||||
acquire(&tickslock);
|
||||
ticks++;
|
||||
wakeup(&ticks);
|
||||
release(&tickslock);
|
||||
|
||||
// acknowledge.
|
||||
w_sip(r_sip() & ~2);
|
||||
|
||||
return 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue