From 7f6471121931046cef7bae1f21abce6c78d7fb5f Mon Sep 17 00:00:00 2001 From: zhangxinyu <840317537@qq.com> Date: Fri, 19 May 2023 10:00:30 +0800 Subject: [PATCH] =?UTF-8?q?trap.S=20=E4=BF=AE=E6=94=B9=E6=B3=A8=E9=87=8A?= =?UTF-8?q?=E6=A0=BC=E5=BC=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ch2/os/src/trap/trap.S | 86 +++++++++++++++++++++--------------------- 1 file changed, 44 insertions(+), 42 deletions(-) diff --git a/ch2/os/src/trap/trap.S b/ch2/os/src/trap/trap.S index 66444bd..804e782 100644 --- a/ch2/os/src/trap/trap.S +++ b/ch2/os/src/trap/trap.S @@ -1,71 +1,73 @@ +# trap进入处理函数的入口__alltraps, 以及第一次进入时的出口__restore + .altmacro .macro SAVE_GP n - sd x\n, \n*8(sp) // 将寄存器 x_n 的值保存到栈空间中 + sd x\n, \n*8(sp) # 将寄存器 x_n 的值保存到栈空间中 .endm .macro LOAD_GP n - ld x\n, \n*8(sp) // 从栈空间中加载寄存器 x_n 的值 + ld x\n, \n*8(sp) # 从栈空间中加载寄存器 x_n 的值 .endm -.section .text // 进入 .text 段 -.globl __alltraps // 声明全局符号 __alltraps -.globl __restore // 声明全局符号 __restore -.align 2 // 对齐到 2^2 = 4 字节 +.section .text # 进入 .text 段 +.globl __alltraps # 声明全局符号 __alltraps +.globl __restore # 声明全局符号 __restore +.align 2 # 对齐到 2^2 = 4 字节 -__alltraps: // __alltraps 符号的实现 - csrrw sp, sscratch, sp // 交换 sp 和 sscratch 寄存器的值 +__alltraps: # __alltraps 符号的实现 + csrrw sp, sscratch, sp # 交换 sp 和 sscratch 寄存器的值 # 现在 sp 指向内核栈,sscratch 指向用户栈 # 在内核栈上分配一个 TrapContext - addi sp, sp, -34*8 // 分配 34*8 字节的空间 + addi sp, sp, -34*8 # 分配 34*8 字节的空间 # 保存通用寄存器 - sd x1, 1*8(sp) // 保存寄存器 x1 的值 (这一步是为了跳过x0寄存器, 方便下面循环) + sd x1, 1*8(sp) # 保存寄存器 x1 的值 (这一步是为了跳过x0寄存器, 方便下面循环) # 跳过 sp(x2),后面会再次保存 - sd x3, 3*8(sp) // 保存寄存器 x3 的值 (这一步是为了跳过x4寄存器, 方便下面循环) + sd x3, 3*8(sp) # 保存寄存器 x3 的值 (这一步是为了跳过x4寄存器, 方便下面循环) # 跳过 tp(x4),应用程序不使用该寄存器 # 保存 x5~x31 - .set n, 5 // 定义变量 n 的初始值为 5 - .rept 27 // 循环 27 次 - SAVE_GP %n // 保存寄存器 x_n 的值到栈空间中 - .set n, n+1 // 将 n 加 1 - .endr // 结束指令块 + .set n, 5 # 定义变量 n 的初始值为 5 + .rept 27 # 循环 27 次 + SAVE_GP %n # 保存寄存器 x_n 的值到栈空间中 + .set n, n+1 # 将 n 加 1 + .endr # 结束指令块 # 我们可以自由使用 t0/t1/t2,因为它们已保存在内核栈上 - csrr t0, sstatus // 读取 sstatus 寄存器的值 - csrr t1, sepc // 读取 sepc 寄存器的值 - sd t0, 32*8(sp) // 保存 sstatus 寄存器的值到栈空间中 - sd t1, 33*8(sp) // 保存 sepc 寄存器的值到栈空间中 + csrr t0, sstatus # 读取 sstatus 寄存器的值 + csrr t1, sepc # 读取 sepc 寄存器的值 + sd t0, 32*8(sp) # 保存 sstatus 寄存器的值到栈空间中 + sd t1, 33*8(sp) # 保存 sepc 寄存器的值到栈空间中 # 从 sscratch 中读取用户栈,并将其保存到内核栈中 - csrr t2, sscratch // 读取 sscratch 寄存器的值 - sd t2, 2*8(sp) // 保存用户栈的地址到内核栈 trap context中 + csrr t2, sscratch # 读取 sscratch 寄存器的值 + sd t2, 2*8(sp) # 保存用户栈的地址到内核栈 trap context中 # 设置 trap_handler(cx: &mut TrapContext) 的输入参数 - mv a0, sp // 将 TrapContext 的地址赋值给 a0 - call trap_handler // 调用 trap_handler 函# 数 + mv a0, sp # 将 TrapContext 的地址赋值给 a0 + call trap_handler # 调用 trap_handler 函# 数 -__restore: // __restore 符号的实现 +__restore: # __restore 符号的实现 # case1: 开始运行应用程序 # case2: 从处理完中断后返回 U 级别 - mv sp, a0 // 将 a0 中保存的内核栈地址赋值给 sp 这个首次进入是在内核进入首次进入sp 这里会被修改为KERNEL_STACK_SIZE, 被接管 + mv sp, a0 # 将 a0 中保存的内核栈地址赋值给 sp 这个首次进入是在内核进入首次进入sp 这里会被修改为KERNEL_STACK_SIZE, 被接管 # 恢复 sstatus/sepc - ld t0, 32*8(sp) // 从栈空间中读取 sstatus 寄存器的值 - ld t1, 33*8(sp) // 从栈空间中读取 sepc 寄存器的值 - ld t2, 2*8(sp) // 从栈空间中读取用户栈的栈顶地址 - csrw sstatus, t0 // 恢复 sstatus 寄存器的值 - csrw sepc, t1 // 恢复 sepc 寄存器的值 - csrw sscratch, t2 // 将栈指针 用户栈 的值 临时保存到 sscratch 寄存器中 + ld t0, 32*8(sp) # 从栈空间中读取 sstatus 寄存器的值 + ld t1, 33*8(sp) # 从栈空间中读取 sepc 寄存器的值 + ld t2, 2*8(sp) # 从栈空间中读取用户栈的栈顶地址 + csrw sstatus, t0 # 恢复 sstatus 寄存器的值 + csrw sepc, t1 # 恢复 sepc 寄存器的值 + csrw sscratch, t2 # 将栈指针 用户栈 的值 临时保存到 sscratch 寄存器中 # 现在 sp 指向内核栈,sscratch 指向用户栈 # 恢复通用寄存器,除了 sp/tp 以外的寄存器 # 跳过x0 - ld x1, 1*8(sp) // 从栈空间中读取寄存器 x1 的值 + ld x1, 1*8(sp) # 从栈空间中读取寄存器 x1 的值 # 跳过x2 - ld x3, 3*8(sp) // 从栈空间中读取寄存器 x3 的值 + ld x3, 3*8(sp) # 从栈空间中读取寄存器 x3 的值 # 循环恢复 - .set n, 5 // 定义变量 n 的初始值为 5 - .rept 27 // 循环 27 次 - LOAD_GP %n // 从栈空间中加载寄存器 x_n 的值 - .set n, n+1 // 将 n 加 1 - .endr // 结束指令块 + .set n, 5 # 定义变量 n 的初始值为 5 + .rept 27 # 循环 27 次 + LOAD_GP %n # 从栈空间中加载寄存器 x_n 的值 + .set n, n+1 # 将 n 加 1 + .endr # 结束指令块 # 现在 sp 指向内核栈,sscratch 指向用户栈, 释放内核栈中的中的 TrapContext, 陷入已经执行完成, 即将返回用户态 不需要这个上下文了 - addi sp, sp, 34*8 // 释放 sizeof + addi sp, sp, 34*8 # 释放 sizeof - csrrw sp, sscratch, sp // 交换 sp内核栈 和 sscratch用户栈 寄存器的值, 交换之后sscratch保存的是内核栈顶, sp是用户栈 USER_STACK(栈底) 的栈顶 - sret // 返回指令, 根据sstatus(陷入/异常之前的特权级) 和 sepc(陷入/异常 之前的pc)返回 \ No newline at end of file + csrrw sp, sscratch, sp # 交换 sp内核栈 和 sscratch用户栈 寄存器的值, 交换之后sscratch保存的是内核栈顶, sp是用户栈 USER_STACK(栈底) 的栈顶 + sret # 返回指令, 根据sstatus(陷入/异常之前的特权级) 和 sepc(陷入/异常 之前的pc)返回 \ No newline at end of file