From 6ef6ed2dea917008c71b5bfdcc8e96af98f5c046 Mon Sep 17 00:00:00 2001 From: ccckmit Date: Tue, 9 Nov 2021 10:32:07 +0800 Subject: [PATCH] Revert "Revert "simplify and test pass"" This reverts commit 05e15d2a179998ad19277a2844bc489a27867b48. --- 04-TimerInterrupt/README.md | 12 +-- 04-TimerInterrupt/os.c | 3 +- 04-TimerInterrupt/os.h | 3 +- 04-TimerInterrupt/sys.s | 162 ++--------------------------- 04-TimerInterrupt/timer.c | 27 ++--- 04-TimerInterrupt/timer.h | 2 +- 04-TimerInterrupt2.zip | Bin 0 -> 23921 bytes 04-TimerInterrupt3.zip | Bin 0 -> 23690 bytes doc/tw/04-TimerInterrupt.md | 197 ++++++++++-------------------------- 9 files changed, 79 insertions(+), 327 deletions(-) create mode 100644 04-TimerInterrupt2.zip create mode 100644 04-TimerInterrupt3.zip diff --git a/04-TimerInterrupt/README.md b/04-TimerInterrupt/README.md index 245df9e..cdc756b 100644 --- a/04-TimerInterrupt/README.md +++ b/04-TimerInterrupt/README.md @@ -3,19 +3,11 @@ ## 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 - -user@DESKTOP-96FRN6B MINGW64 /d/ccc109/sp/11-os/mini-riscv-os/04-TimerInterrupt (master) +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 $ 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 diff --git a/04-TimerInterrupt/os.c b/04-TimerInterrupt/os.c index 00a8b8b..a8c6884 100644 --- a/04-TimerInterrupt/os.c +++ b/04-TimerInterrupt/os.c @@ -4,8 +4,7 @@ int os_main(void) { lib_puts("OS start\n"); timer_init(); // start timer interrupt ... - - while (1) {} // stop here ! + while (1) {} // os : do nothing, just loop! return 0; } diff --git a/04-TimerInterrupt/os.h b/04-TimerInterrupt/os.h index 4058445..2e8389e 100644 --- a/04-TimerInterrupt/os.h +++ b/04-TimerInterrupt/os.h @@ -5,8 +5,7 @@ #include "lib.h" #include "timer.h" -extern void user_init(); -extern void os_kernel(); +extern void os_loop(void); extern int os_main(void); #endif diff --git a/04-TimerInterrupt/sys.s b/04-TimerInterrupt/sys.s index afcfaef..a4d46b1 100644 --- a/04-TimerInterrupt/sys.s +++ b/04-TimerInterrupt/sys.s @@ -1,163 +1,15 @@ # 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: - # 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. + # call the C timer_handler(reg_t epc, reg_t cause) + csrr a0, mepc + csrr a1, mcause + call timer_handler - csrrw a0, mscratch, a0 # exchange(mscratch,a0) - sw a1, 0(a0) - sw a2, 4(a0) - sw a3, 8(a0) + # timer_handler will return the return address via a0. + csrw mepc, a0 - # 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) + mret # back to interrupt location (pc=mepc) diff --git a/04-TimerInterrupt/timer.c b/04-TimerInterrupt/timer.c index ed34982..e188cd3 100644 --- a/04-TimerInterrupt/timer.c +++ b/04-TimerInterrupt/timer.c @@ -1,9 +1,6 @@ #include "timer.h" -extern void os_kernel(); - -// a scratch area per CPU for machine-mode timer interrupts. -reg_t timer_scratch[NCPU][5]; +#define interval 10000000 // cycles; about 1 second in qemu. void timer_init() { @@ -11,18 +8,8 @@ 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); @@ -35,7 +22,15 @@ void timer_init() static int timer_count = 0; -void timer_handler() { +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))); lib_printf("timer_handler: %d\n", ++timer_count); - // os_kernel(); + 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; } diff --git a/04-TimerInterrupt/timer.h b/04-TimerInterrupt/timer.h index 73b9f3a..2c15d29 100644 --- a/04-TimerInterrupt/timer.h +++ b/04-TimerInterrupt/timer.h @@ -5,7 +5,7 @@ #include "sys.h" #include "lib.h" -extern void timer_handler(); +extern reg_t timer_handler(reg_t epc, reg_t cause); extern void timer_init(); #endif diff --git a/04-TimerInterrupt2.zip b/04-TimerInterrupt2.zip new file mode 100644 index 0000000000000000000000000000000000000000..5b8697c19fbc09451c081848f90596cea052c84a GIT binary patch literal 23921 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 J_=iA1{|_~9ocI6$ literal 0 HcmV?d00001 diff --git a/04-TimerInterrupt3.zip b/04-TimerInterrupt3.zip new file mode 100644 index 0000000000000000000000000000000000000000..9f946db81fdf7b1584350092436d488ff9c65357 GIT binary patch literal 23690 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