Revert "simplify and test pass"

This reverts commit dd146959a6.
This commit is contained in:
ccckmit
2021-11-09 10:30:38 +08:00
parent dd146959a6
commit 05e15d2a17
9 changed files with 327 additions and 79 deletions

View File

@@ -3,11 +3,19 @@
## Build & Run
```sh
user@DESKTOP-96FRN6B MINGW64 /d/ccc109/sp/11-os/mini-riscv-os/04-TimerInterrupt (master)
$ make clean
rm -f *.elf
user@DESKTOP-96FRN6B MINGW64 /d/ccc109/sp/11-os/mini-riscv-os/04-TimerInterrupt (master)
$ make
riscv64-unknown-elf-gcc -nostdlib -fno-builtin -mcmodel=medany -march=rv32ima -mabi=ilp32 -T os.ld -o os.elf start.s sys.s lib.c timer.c os.c
riscv64-unknown-elf-gcc -nostdlib -fno-builtin -mcmodel=medany -march=rv32ima
-mabi=ilp32 -T os.ld -o os.elf start.s sys.s lib.c timer.c os.c
user@DESKTOP-96FRN6B MINGW64 /d/ccc109/sp/11-os/mini-riscv-os/04-TimerInterrupt (master)
$ make qemu
Press Ctrl-A and then X to exit QEMU
qemu-system-riscv32 -nographic -smp 4 -machine virt -bios none -kernel os.elf
qemu-system-riscv32 -nographic -smp 4 -machine virt -bios none -kernel os.elf
OS start
timer_handler: 1
timer_handler: 2

View File

@@ -4,7 +4,8 @@ int os_main(void)
{
lib_puts("OS start\n");
timer_init(); // start timer interrupt ...
while (1) {} // os : do nothing, just loop!
while (1) {} // stop here !
return 0;
}

View File

@@ -5,7 +5,8 @@
#include "lib.h"
#include "timer.h"
extern void os_loop(void);
extern void user_init();
extern void os_kernel();
extern int os_main(void);
#endif

View File

@@ -1,15 +1,163 @@
# This Code derived from xv6-riscv (64bit)
# -- https://github.com/mit-pdos/xv6-riscv/blob/riscv/kernel/swtch.S
# ============ MACRO ==================
.macro ctx_save base
sw ra, 0(\base)
sw sp, 4(\base)
sw s0, 8(\base)
sw s1, 12(\base)
sw s2, 16(\base)
sw s3, 20(\base)
sw s4, 24(\base)
sw s5, 28(\base)
sw s6, 32(\base)
sw s7, 36(\base)
sw s8, 40(\base)
sw s9, 44(\base)
sw s10, 48(\base)
sw s11, 52(\base)
.endm
.macro ctx_load base
lw ra, 0(\base)
lw sp, 4(\base)
lw s0, 8(\base)
lw s1, 12(\base)
lw s2, 16(\base)
lw s3, 20(\base)
lw s4, 24(\base)
lw s5, 28(\base)
lw s6, 32(\base)
lw s7, 36(\base)
lw s8, 40(\base)
lw s9, 44(\base)
lw s10, 48(\base)
lw s11, 52(\base)
.endm
.macro reg_save base
# save the registers.
sw ra, 0(\base)
sw sp, 4(\base)
sw gp, 8(\base)
sw tp, 12(\base)
sw t0, 16(\base)
sw t1, 20(\base)
sw t2, 24(\base)
sw s0, 28(\base)
sw s1, 32(\base)
sw a0, 36(\base)
sw a1, 40(\base)
sw a2, 44(\base)
sw a3, 48(\base)
sw a4, 52(\base)
sw a5, 56(\base)
sw a6, 60(\base)
sw a7, 64(\base)
sw s2, 68(\base)
sw s3, 72(\base)
sw s4, 76(\base)
sw s5, 80(\base)
sw s6, 84(\base)
sw s7, 88(\base)
sw s8, 92(\base)
sw s9, 96(\base)
sw s10, 100(\base)
sw s11, 104(\base)
sw t3, 108(\base)
sw t4, 112(\base)
sw t5, 116(\base)
sw t6, 120(\base)
.endm
.macro reg_load base
# restore registers.
lw ra, 0(\base)
lw sp, 4(\base)
lw gp, 8(\base)
# not this, in case we moved CPUs: lw tp, 12(\base)
lw t0, 16(\base)
lw t1, 20(\base)
lw t2, 24(\base)
lw s0, 28(\base)
lw s1, 32(\base)
lw a0, 36(\base)
lw a1, 40(\base)
lw a2, 44(\base)
lw a3, 48(\base)
lw a4, 52(\base)
lw a5, 56(\base)
lw a6, 60(\base)
lw a7, 64(\base)
lw s2, 68(\base)
lw s3, 72(\base)
lw s4, 76(\base)
lw s5, 80(\base)
lw s6, 84(\base)
lw s7, 88(\base)
lw s8, 92(\base)
lw s9, 96(\base)
lw s10, 100(\base)
lw s11, 104(\base)
lw t3, 108(\base)
lw t4, 112(\base)
lw t5, 116(\base)
lw t6, 120(\base)
.endm
# ============ Macro END ==================
# Context switch
#
# void sys_switch(struct context *old, struct context *new);
#
# Save current registers in old. Load from new.
.globl sys_switch
.align 4
sys_switch:
ctx_save a0 # a0 => struct context *old
ctx_load a1 # a1 => struct context *new
ret # pc=ra; swtch to new task (new->ra)
.globl sys_kernel
.align 4
sys_kernel:
addi sp, sp, -128 # alloc stack space
reg_save sp # save all registers
call timer_handler # call timer.c:timer_handler
reg_load sp # restore all registers
addi sp, sp, 128 # restore stack pointer
jr a7 # jump to a7=mepc , return to timer break point
.globl sys_timer
.align 4
sys_timer:
# call the C timer_handler(reg_t epc, reg_t cause)
csrr a0, mepc
csrr a1, mcause
call timer_handler
# timer_init() has set up the memory that mscratch points to:
# scratch[0,4,8] : register save area.
# scratch[12] : address of CLINT's MTIMECMP register.
# scratch[16] : desired interval between interrupts.
# timer_handler will return the return address via a0.
csrw mepc, a0
csrrw a0, mscratch, a0 # exchange(mscratch,a0)
sw a1, 0(a0)
sw a2, 4(a0)
sw a3, 8(a0)
mret # back to interrupt location (pc=mepc)
# schedule the next timer interrupt
# by adding interval to mtimecmp.
lw a1, 12(a0) # CLINT_MTIMECMP(hart)
lw a2, 16(a0) # interval
lw a3, 0(a1) # a3 = CLINT_MTIMECMP(hart)
add a3, a3, a2 # a3 += interval
sw a3, 0(a1) # CLINT_MTIMECMP(hart) = a3
csrr a7, mepc # a7 = mepc, for sys_kernel jump back to interrupted point
la a1, sys_kernel # mepc = sys_kernel
csrw mepc, a1 # mret : will jump to sys_kernel
lw a3, 8(a0)
lw a2, 4(a0)
lw a1, 0(a0)
csrrw a0, mscratch, a0 # exchange(mscratch,a0)
mret # jump to mepc (=sys_kernel)

View File

@@ -1,6 +1,9 @@
#include "timer.h"
#define interval 10000000 // cycles; about 1 second in qemu.
extern void os_kernel();
// a scratch area per CPU for machine-mode timer interrupts.
reg_t timer_scratch[NCPU][5];
void timer_init()
{
@@ -8,8 +11,18 @@ void timer_init()
int id = r_mhartid();
// ask the CLINT for a timer interrupt.
int interval = 10000000; // cycles; about 1 second in qemu.
*(reg_t*)CLINT_MTIMECMP(id) = *(reg_t*)CLINT_MTIME + interval;
// prepare information in scratch[] for timervec.
// scratch[0..2] : space for timervec to save registers.
// scratch[3] : address of CLINT MTIMECMP register.
// scratch[4] : desired interval (in cycles) between timer interrupts.
reg_t *scratch = &timer_scratch[id][0];
scratch[3] = CLINT_MTIMECMP(id);
scratch[4] = interval;
w_mscratch((reg_t)scratch);
// set the machine-mode trap handler.
w_mtvec((reg_t)sys_timer);
@@ -22,15 +35,7 @@ void timer_init()
static int timer_count = 0;
reg_t timer_handler(reg_t epc, reg_t cause)
{
reg_t return_pc = epc;
// disable machine-mode timer interrupts.
w_mie(~((~r_mie()) | (1 << 7)));
void timer_handler() {
lib_printf("timer_handler: %d\n", ++timer_count);
int id = r_mhartid();
*(reg_t *)CLINT_MTIMECMP(id) = *(reg_t *)CLINT_MTIME + interval;
// enable machine-mode timer interrupts.
w_mie(r_mie() | MIE_MTIE);
return return_pc;
// os_kernel();
}

View File

@@ -5,7 +5,7 @@
#include "sys.h"
#include "lib.h"
extern reg_t timer_handler(reg_t epc, reg_t cause);
extern void timer_handler();
extern void timer_init();
#endif