[root@centos7 04_interrupt]# cat src/head.s .section .text.init .align 3 .globl _start .extern start_kernel .extern stack_top .extern _strap .extern bss_start .extern bss_end .equ MTIMR, 0x200bff8 .equ MTIMECMP, 0x2004000 _start: csrci mstatus,8 li t0,0x1800 csrc mstatus,t0 li t0,0x800 csrs mstatus,t0 li t0,0x888 csrc mie,t0 la t0,fail1 csrw mtvec,t0 la t0,super csrw mepc,t0 lean_bss: la t0, bss_start la t1, bss_end li t2,0 clean_loop: sw t2, 0(t0) addi t0, t0, 1 bne t0, t1, clean_loop init_mtimecpp: li t2,MTIMR /* mtimecpp=mtimr+100000 */ ld t0,0(t2) li t1,0x100000 add t0, t0, t1 li t1, MTIMECMP sd t0, 0(t1) open_interupt: li t0,0x0A /* set [m/s]staus & [m/s]ie & mideleg */ csrs mstatus, t0 li t0,0x0A0 csrs mie, t0 li t0,0x20 csrs mideleg, t0 mret # 转入super super: la t0,st_reg csrw stvec,t0 la sp,stack_top call t0,start_kernel fail1: csrr a1,mcause li t0,0x8000000000000007 /* check the mcause to see if it's a time trap*/ beq a1,t0,is_a_trap //中断委托代理 li t2,MTIMECMP /* ecall from S so mtimecpp+=fff000/enable mie/disable mip */ ld t0,0(t2) li t1,0xfff000 add t0, t0, t1 sd t0, 0(t2) li t0,0x80 csrs mie, t0 li t0,0x20 csrc mip,t1 csrr t0,mepc ##更新mepc addi t0, t0, 4 csrw mepc,t0 mret is_a_trap: li t0,0x80 /* time trap so enable mip/disable mie */ csrc mie, t0 li t0,0x20 csrs mip,t0 mret
csrci mstatus,8 #MPIE清零 li t0,0x1800 csrc mstatus,t0 #MPP=00 li t0,0x800 csrs mstatus,t0 #MPP=01 s模式 li t0,0x888 csrc mie,t0 la t0,fail1 csrw mtvec,t0 la t0,super csrw mepc,t0
-
machine mode处理函数分析异常原因,判断为时钟中断,为了将时钟中断委托给supervisor mode,于是将mip[stip]置位,并且为了防止在supervisor mode处理时钟中断时继续触发machine mode时钟中断,于是同时将mie[mtie]清零。
is_a_trap: li t0,0x80 /* time trap so enable mip/disable mie */ csrc mie, t0 #disable mie time li t0,0x20 csrs mip,t0 #enable sTIP mret
当处理同步异常时应该在退出前给mepc+4,当处理中断时则不需要,请解释为什么要这样做。
mepc储存返回地址。出现同步异常后,返回地址更新为当前发生异常指令的地址,但是真正的返回地址应该是异常指令的下一条指令,故要执行mepc=mepc+4。处理中断时,mepc已储存下一条指令地址,故不需要自增。
csrr t0,mepc ##更新mepc addi t0, t0, 4 csrw mepc,t0 mret
整个代码没有设置xepc等价于
mip
寄存器
mip
寄存器指示了何种类型的中断正在传入 (pending),与它相同功能的寄存器有 sip
和 uip
。
在该寄存器中,只有低特权级别的软件中断位 (USIP, SSIP)、时钟中断 (UTIP, STIP) 、外部中断 (UEIP, SEIP) 是可以通过 CSR 指令写入的,其他都是只读的。若有中断委托给了权限级别 x
,被委托的中断所对应的位(在 xie
和 xip
寄存器中)就可以使用了,否则,相应的位接地变 0 。
xSIP: software interrupts in x mode 软件中断
xEIP: external interrupt 外部中断
请注意,MTIP
、STIP
、UTIP
位分别对应机器模式、监管者模式、用户模式的时钟中断信号。MTIP
位是只读的,而 UTIP
和 STIP
位在机器模式下可以写入,这就是将时钟中断处理下放给低级权限的方式。
mie
寄存器
mie
寄存器包含了相应的中断使能位,sie
和 uie
功能相似。注意观察 mcause
寄存器编码,可以发现,若 bit i
在 mie
和 mip
寄存器都置位,且全局中断位打开,那么中断 i
就会视作发生,并被处理。一般情况下,在低权限运行时,机器模式的中断一直有效。
xSIE: software interrupt-enable in x mode 软件中断使能位
xEIE: external interrupt-enable in x mode 外部中断使能位
xIE: Interrupt Enable in x mode 中断使能
xPIE: Previous Interrupt Enable in x mode 之前的中断使能
xPP: Previous Privilege mode up to x mode 之前的特权级别
在中断使能方面,MIE
、SIE
、UIE
分别提供了 machine mode 、supervisor mode 、user mode 的全局中断使能位,若一个 hart 运行在特权级别 x
下,当 xIE = 1
时中断全局打开,反之则关闭。在 hart 于 x
运行时,无论 wIE
为何值,低权限中断 w < x
总是无效的,而无论 yIE
为何值,高权限中断 y > x
总是有效。
mcause
寄存器
mcause
寄存器的作用是记录中断/异常事件的类型/起因。在当 trap 进入机器模式后,将异常/中断事件产生的起因(或者称之为谁导致了异常/中断事件)写入到该寄存器中。
fail1: csrr a1,mcause li t0,0x8000000000000007 /* check the mcause to see if it's a time trap*/ beq a1,t0,is_a_trap ##相等 li t2,MTIMECMP /* ecall from S so mtimecpp+=fff000/enable mie/disable mip */ ld t0,0(t2) li t1,0xfff000 add t0, t0, t1 sd t0, 0(t2) li t0,0x80 csrs mie, t0 li t0,0x20 csrc mip,t1 csrr t0,mepc addi t0, t0, 4 csrw mepc,t0 mret is_a_trap: li t0,0x80 /* time trap so enable mip/disable mie */ csrc mie, t0 #disable mie time li t0,0x20 csrs mip,t0 #enable sTIP mret
[root@centos7 04_interrupt]# riscv64-unknown-elf-gdb -x debug.txt GNU gdb (GDB) 11.1 Copyright (C) 2021 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=aarch64-unknown-linux-gnu --target=riscv64-unknown-elf". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". warning: Can not parse XML target description; XML support was disabled at compile time 0x0000000000001000 in ?? () (gdb) b _start Breakpoint 1 at 0x80000000: file src/head.s, line 12. (gdb) b lean_bss Breakpoint 2 at 0x8000003a: file src/head.s, line 25. (gdb) b clean_loop Breakpoint 3 at 0x8000004c: file src/head.s, line 29. (gdb) b init_mtimecpp Breakpoint 4 at 0x80000056: file src/head.s, line 34. (gdb) b open_interupt Breakpoint 5 at 0x8000006e: file src/head.s, line 41. (gdb) b super Breakpoint 6 at 0x80000088: file src/head.s, line 50. (gdb) b fail1 Breakpoint 7 at 0x800000a0: file src/head.s, line 56. (gdb) b is_a_trap Breakpoint 8 at 0x800000e0: file src/head.s, line 75. (gdb) c Continuing. Breakpoint 1, _start () at src/head.s:12 12 csrci mstatus,8 (gdb) c Continuing. Breakpoint 2, lean_bss () at src/head.s:25 25 la t0, bss_start (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 4, init_mtimecpp () at src/head.s:34 34 li t2,MTIMR /* mtimecpp=mtimr+100000 */ (gdb) c Continuing. Breakpoint 5, open_interupt () at src/head.s:41 41 li t0,0x0A /* set [m/s]staus & [m/s]ie & mideleg */ (gdb) c Continuing. Breakpoint 6, super () at src/head.s:50 50 la t0,st_reg (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 8, is_a_trap () at src/head.s:75 75 li t0,0x80 /* time trap so enable mip/disable mie */ (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 7, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) cc
[root@centos7 04_interrupt]# cat src/entry.s .section .text.entry .align 3 .global st_reg .global ld_reg .global myentry .extern strap_c st_reg: sd sp, -8(sp) sd ra, -16(sp) sd gp, -24(sp) sd tp, -32(sp) sd t0, -40(sp) sd t1, -48(sp) sd t2, -56(sp) sd s0, -64(sp) sd s1, -72(sp) sd a0, -80(sp) sd a1, -88(sp) sd a2, -96(sp) sd a3, -104(sp) sd a4, -112(sp) sd a5, -120(sp) sd a6, -128(sp) sd a7, -136(sp) sd s2, -144(sp) sd s3, -152(sp) sd s4, -160(sp) sd s5, -168(sp) sd s6, -176(sp) sd s7, -184(sp) sd s8, -192(sp) sd s9, -200(sp) sd s10, -208(sp) sd s11, -216(sp) sd t3, -224(sp) sd t4, -232(sp) sd t5, -240(sp) sd t6, -248(sp) addi sp, sp, -248 myentry: call strap_c ecall ld_reg: ld t6, 0(sp) ld t5, 8(sp) ld t4, 16(sp) ld t3, 24(sp) ld s11, 32(sp) ld s10, 40(sp) ld s9, 48(sp) ld s8, 56(sp) ld s7, 64(sp) ld s6, 72(sp) ld s5, 80(sp) ld s4, 88(sp) ld s3, 96(sp) ld s2, 104(sp) ld a7, 112(sp) ld a6, 120(sp) ld a5, 128(sp) ld a4, 136(sp) ld a3, 144(sp) ld a2, 152(sp) ld a1, 160(sp) ld a0, 168(sp) ld s1, 176(sp) ld s0, 184(sp) ld t2, 192(sp) ld t1, 200(sp) ld t0, 208(sp) ld tp, 216(sp) ld gp, 224(sp) ld ra, 232(sp) ld sp, 240(sp) sret
[root@centos7 04_interrupt]# qemu-system-riscv64 -M virt -kernel kernel.img -bios none -serial stdio -s -S VNC server running on ::1:5900 ZJU OS LAB 2 GROUP-05 [S] Supervisor Mode Timer Interrupt [S] Supervisor Mode Timer Interrupt [S] Supervisor Mode Timer Interrupt [S] Supervisor Mode Timer Interrupt qemu-system-riscv64: terminating on signal 2
[root@centos7 04_interrupt]# cat debug.txt file kernel.elf target remote :1234 b _start b lean_bss b clean_loop b init_mtimecpp b open_interupt b super b st_reg b myentry b strap_c b ld_reg b fail1 b is_a_trap
[root@centos7 04_interrupt]# riscv64-unknown-elf-gdb -x debug.txt GNU gdb (GDB) 11.1 Copyright (C) 2021 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "--host=aarch64-unknown-linux-gnu --target=riscv64-unknown-elf". Type "show configuration" for configuration details. For bug reporting instructions, please see: <https://www.gnu.org/software/gdb/bugs/>. Find the GDB manual and other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. For help, type "help". Type "apropos word" to search for commands related to "word". warning: Can not parse XML target description; XML support was disabled at compile time 0x0000000000001000 in ?? () Breakpoint 1 at 0x80000000: file src/head.s, line 12. Breakpoint 2 at 0x8000003a: file src/head.s, line 25. Breakpoint 3 at 0x8000004c: file src/head.s, line 29. Breakpoint 4 at 0x80000056: file src/head.s, line 34. Breakpoint 5 at 0x8000006e: file src/head.s, line 41. Breakpoint 6 at 0x80000088: file src/head.s, line 50. Breakpoint 7 at 0x800000f8: file src/entry.s, line 9. Breakpoint 8 at 0x80000178: file src/entry.s, line 43. Breakpoint 9 at 0x8000031c: file src/strap.c, line 6. Breakpoint 10 at 0x80000180: file src/entry.s, line 47. Breakpoint 11 at 0x800000a0: file src/head.s, line 56. Breakpoint 12 at 0x800000e0: file src/head.s, line 75. (gdb) c Continuing. Breakpoint 1, _start () at src/head.s:12 12 csrci mstatus,8 (gdb) c Continuing. Breakpoint 2, lean_bss () at src/head.s:25 25 la t0, bss_start (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 3, clean_loop () at src/head.s:29 29 sw t2, 0(t0) (gdb) c Continuing. Breakpoint 4, init_mtimecpp () at src/head.s:34 34 li t2,MTIMR /* mtimecpp=mtimr+100000 */ (gdb) c Continuing. Breakpoint 5, open_interupt () at src/head.s:41 41 li t0,0x0A /* set [m/s]staus & [m/s]ie & mideleg */ (gdb) c Continuing. Breakpoint 6, super () at src/head.s:50 50 la t0,st_reg (gdb) c Continuing. Breakpoint 11, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 12, is_a_trap () at src/head.s:75 75 li t0,0x80 /* time trap so enable mip/disable mie */ (gdb) c Continuing. Breakpoint 7, st_reg () at src/entry.s:9 9 sd sp, -8(sp) (gdb) c Continuing. Breakpoint 8, myentry () at src/entry.s:43 43 call strap_c (gdb) c Continuing. Breakpoint 9, strap_c () at src/strap.c:6 6 count0++; (gdb) c Continuing. Breakpoint 11, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 10, ld_reg () at src/entry.s:47 47 ld t6, 0(sp) (gdb) c Continuing. Breakpoint 7, st_reg () at src/entry.s:9 9 sd sp, -8(sp) (gdb) c Continuing. Breakpoint 8, myentry () at src/entry.s:43 43 call strap_c (gdb) c Continuing. Breakpoint 9, strap_c () at src/strap.c:6 6 count0++; (gdb) c Continuing. Breakpoint 11, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 10, ld_reg () at src/entry.s:47 47 ld t6, 0(sp) (gdb) c Continuing. Breakpoint 7, st_reg () at src/entry.s:9 9 sd sp, -8(sp) (gdb) c Continuing. Breakpoint 8, myentry () at src/entry.s:43 43 call strap_c (gdb) c Continuing. Breakpoint 9, strap_c () at src/strap.c:6 6 count0++; (gdb) c Continuing. Breakpoint 11, fail1 () at src/head.s:56 56 csrr a1,mcause (gdb) c Continuing. Breakpoint 10, ld_reg () at src/entry.s:47 47 ld t6, 0(sp) (gdb) c Continuing. Breakpoint 7, st_reg () at src/entry.s:9 9 sd sp, -8(sp) (gdb) cc Undefined command: "cc". Try "help". (gdb) q A debugging session is active. Inferior 1 [process 1] will be detached. Quit anyway? (y or n) y
0x0000000000001000 in ?? () Breakpoint 1 at 0x80000000: file src/head.s, line 12. Breakpoint 2 at 0x8000003a: file src/head.s, line 25. Breakpoint 3 at 0x8000004c: file src/head.s, line 29. Breakpoint 4 at 0x80000056: file src/head.s, line 34. Breakpoint 5 at 0x8000006e: file src/head.s, line 41. Breakpoint 6 at 0x80000088: file src/head.s, line 50. Breakpoint 7 at 0x800000f8: file src/entry.s, line 9. Breakpoint 8 at 0x800001ce: file src/main.c, line 7. Breakpoint 9 at 0x80000178: file src/entry.s, line 43. Breakpoint 10 at 0x8000031c: file src/strap.c, line 6. Breakpoint 11 at 0x80000180: file src/entry.s, line 46. Breakpoint 12 at 0x800000a0: file src/head.s, line 56. Breakpoint 13 at 0x800000e0: file src/head.s, line 75. (gdb) b src/entry.s:77 Breakpoint 14 at 0x800001be: file src/entry.s, line 77. (gdb) c
fail mret
ld_reg ret返回
is_a_trap mret返回
更改 is_a_trap
is_a_trap:
li t0,0x80 /* time trap so enable mip/disable mie */
csrc mie, t0 #disable mie time
li t0,0x20
csrs mip,t0 #enable sTIP
mret