提交 817223fa 编写于 作者: Z Zihao Yu

riscv64-nemu: reuse more code from riscv32-nemu

上级 45374f11
...@@ -2,8 +2,10 @@ include $(AM_HOME)/am/arch/isa/riscv64.mk ...@@ -2,8 +2,10 @@ include $(AM_HOME)/am/arch/isa/riscv64.mk
include $(AM_HOME)/am/arch/platform/nemu.mk include $(AM_HOME)/am/arch/platform/nemu.mk
AM_SRCS += nemu/isa/riscv/trm.c \ AM_SRCS += nemu/isa/riscv/trm.c \
nemu/isa/riscv/cte64.c \ nemu/isa/riscv/cte.c \
nemu/isa/riscv/trap.S \ nemu/isa/riscv/trap.S \
nemu/isa/riscv/cte64.c \
nemu/isa/riscv/mtime.S \
nemu/isa/riscv/vme.c \ nemu/isa/riscv/vme.c \
nemu/isa/riscv/boot/start.S nemu/isa/riscv/boot/start.S
......
#ifndef __ARCH_H__ #include "riscv32-nemu.h"
#define __ARCH_H__
struct _Context {
union {
void *pdir;
uint64_t gpr[32];
};
uint64_t mcause;
uint64_t mstatus;
uint64_t mepc;
};
#define GPR1 gpr[17] // a7
#define GPR2 gpr[10] // a0
#define GPR3 gpr[11] // a1
#define GPR4 gpr[12] // a2
#define GPRx gpr[10] // a0
#endif
...@@ -7,13 +7,21 @@ static _Context* (*user_handler)(_Event, _Context*) = NULL; ...@@ -7,13 +7,21 @@ static _Context* (*user_handler)(_Event, _Context*) = NULL;
void __am_get_cur_as(_Context *c); void __am_get_cur_as(_Context *c);
void __am_switch(_Context *c); void __am_switch(_Context *c);
#define INTR_BIT (1ul << (sizeof(uintptr_t) * 8 - 1))
_Context* __am_irq_handle(_Context *c) { _Context* __am_irq_handle(_Context *c) {
__am_get_cur_as(c); __am_get_cur_as(c);
if (user_handler) { if (user_handler) {
_Event ev = {0}; _Event ev = {0};
switch (c->scause) { switch (c->scause) {
case 0x80000005: ev.event = _EVENT_IRQ_TIMER; break; #if __riscv_xlen == 64
// SSIP, which is set at mtime.S
case 0x1 | INTR_BIT: asm volatile ("csrwi sip, 0");
#else
case 0x5 | INTR_BIT:
#endif
ev.event = _EVENT_IRQ_TIMER; break;
case 9: case 9:
ev.event = (c->GPR1 == -1) ? _EVENT_YIELD : _EVENT_SYSCALL; ev.event = (c->GPR1 == -1) ? _EVENT_YIELD : _EVENT_SYSCALL;
c->sepc += 4; c->sepc += 4;
...@@ -41,6 +49,11 @@ int _cte_init(_Context*(*handler)(_Event, _Context*)) { ...@@ -41,6 +49,11 @@ int _cte_init(_Context*(*handler)(_Event, _Context*)) {
// register event handler // register event handler
user_handler = handler; user_handler = handler;
#if __riscv_xlen == 64
extern void __am_init_cte64();
__am_init_cte64();
#endif
return 0; return 0;
} }
......
#include <am.h> #include <riscv.h>
#include <nemu.h>
#include <klib.h>
#define CLINT_MMIO 0xa2000000 #define CLINT_MMIO 0xa2000000
#define CLINT_MTIMECMP (CLINT_MMIO + 0x4000) #define CLINT_MTIMECMP (CLINT_MMIO + 0x4000)
#define CLINT_MTIME (CLINT_MMIO + 0xbff8)
#define TIME_INC 0x800 #define TIME_INC 0x800
static inline void inc_mtimecmp(uint64_t this) {
outd(CLINT_MTIMECMP, this + TIME_INC);
}
static _Context* (*user_handler)(_Event, _Context*) = NULL;
void __am_get_cur_as(_Context *c);
void __am_switch(_Context *c);
#define INTR_BIT (1ULL << 63)
_Context* __am_irq_handle(_Context *c) {
__am_get_cur_as(c);
_Context *next = c; extern void __am_timervec(void);
if (user_handler) {
_Event ev = {0};
switch (c->cause) {
case (0x7 | INTR_BIT):
inc_mtimecmp(ind(CLINT_MTIME));
ev.event = _EVENT_IRQ_TIMER;
break;
case 9:
ev.event = (c->GPR1 == -1) ? _EVENT_YIELD : _EVENT_SYSCALL;
c->epc += 4;
break;
default: ev.event = _EVENT_ERROR; break;
}
next = user_handler(ev, c); static void init_timer() {
if (next == NULL) { static struct {
next = c; uintptr_t mtimecmp;
} uintptr_t time_inc;
} uintptr_t temp[3];
} handle;
__am_switch(next); handle.mtimecmp = CLINT_MTIMECMP;
handle.time_inc = TIME_INC;
return next; asm volatile("csrw mscratch, %0" : : "r"(&handle));
}
extern void __am_asm_trap(void);
int _cte_init(_Context*(*handler)(_Event, _Context*)) {
// initialize exception entry
asm volatile("csrw stvec, %0" : : "r"(__am_asm_trap));
// register event handler // set M-mode exception entry to handle machine timer interrupt
user_handler = handler; asm volatile("csrw mtvec, %0" : : "r"(__am_timervec));
// set machine timer interrupt // set machine timer interrupt
inc_mtimecmp(0); asm volatile("csrs mie, %0" : : "r"((1 << 7) | (1 << 1)));
asm volatile("csrs mie, %0" : : "r"(1 << 7)); outd(CLINT_MTIMECMP, 0);
}
void __am_init_cte64() {
// set delegation // set delegation
asm volatile("csrw mideleg, %0" : : "r"(0xffff)); asm volatile("csrw mideleg, %0" : : "r"(0xffff));
asm volatile("csrw medeleg, %0" : : "r"(0xffff)); asm volatile("csrw medeleg, %0" : : "r"(0xffff));
init_timer();
// enter S-mode // enter S-mode
uintptr_t status = MSTATUS_MXR | MSTATUS_SUM | MSTATUS_SPP(MODE_S); uintptr_t status = MSTATUS_SPP(MODE_S);
extern char _here; extern char _here;
asm volatile( asm volatile(
"csrw sstatus, %0;" "csrw sstatus, %0;"
...@@ -72,26 +42,4 @@ int _cte_init(_Context*(*handler)(_Event, _Context*)) { ...@@ -72,26 +42,4 @@ int _cte_init(_Context*(*handler)(_Event, _Context*)) {
"sret;" "sret;"
"_here:" "_here:"
: : "r"(status), "r"(&_here)); : : "r"(status), "r"(&_here));
return 0;
}
_Context *_kcontext(_Area stack, void (*entry)(void *), void *arg) {
_Context *c = (_Context*)stack.end - 1;
c->epc = (uintptr_t)entry;
uintptr_t mprotect = MSTATUS_MXR | MSTATUS_SUM;
c->status = mprotect | MSTATUS_SPP(MODE_S) | MSTATUS_PIE(MODE_S);
return c;
}
void _yield() {
asm volatile("li a7, -1; ecall");
}
int _intr_read() {
return 0;
}
void _intr_write(int enable) {
} }
# machine-mode timer interrupt handler from xv6 code
.globl __am_timervec
.align 4
__am_timervec:
csrrw a0, mscratch, a0
sd a1, 16(a0)
sd a2, 24(a0)
sd a3, 32(a0)
# schedule the next timer interrupt
# by adding interval to mtimecmp.
ld a1, 0(a0) # CLINT_MTIMECMP(hart)
ld a2, 8(a0) # interval
ld a3, 0(a1)
add a3, a3, a2
sd a3, 0(a1)
# raise a supervisor software interrupt.
csrwi sip, 2
ld a3, 32(a0)
ld a2, 24(a0)
ld a1, 16(a0)
csrrw a0, mscratch, a0
mret
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册