Skip to content

Commit

Permalink
🐞 fix: bug fix
Browse files Browse the repository at this point in the history
  • Loading branch information
SaZiKK committed Jul 24, 2024
1 parent 0675682 commit 8e46b1e
Showing 1 changed file with 4 additions and 4 deletions.
8 changes: 4 additions & 4 deletions _posts/2024-05-14-【开发日志】chaos开发日志.md
Original file line number Diff line number Diff line change
Expand Up @@ -265,21 +265,21 @@ rCore原先的逻辑是为内核的页表分配各个进程的内核栈,因为

首先是发现在刚刚进入用户进程的时候,fork结束后的那次时钟中断会调度到初始进程然后panic,由于错误是 `InstructionPageFault` ,所以常规想法没有思路,只能开始gdb。因为是进程调度时取指报错,所以优先跟踪跳转地址,也就是 `ra` 寄存器以及保存 `ra` 寄存器的 `task_cx` 即任务上下文。`ra` 与任务上下文的交换只发生在汇编函数 `__switch` 中,因此断点也设在该符号处。

![](..\assets\figures\gdb.jpg)
![](../assets/figures/gdb.jpg)

第一轮gdb之后,发现最后的跳转地址会进入 `suspend_current_and_run` ,并且在返回时报错,认为是 `task_cx``ra` 的维护出错导致问题。但是在仔细观察了rCore的处理和gdb结果后发现跳转流程实际上并没有问题。

rCore设计的进程切换方式非常巧妙,具体流程如下图所示。之所以会跳转进入 `suspend_current_and_run` ,是因为经过了时间片中断,在 `suspend_current_and_run` 调用的 `__switch` 中把当前 `ra` 的值保存到 `idle` 进程的上下文中,下一次 `__switch` 时又会恢复这个 `ra`,所以函数返回时会跳转到 `suspend_current_and_run` ,这是完全正常的。

![](..\assets\figures\rCore进程调度流程.png)
![](../assets/figures/rCore进程调度流程.png)

继续仔细观察跳转出错的原因发现,返回进入 `suspend_current_and_run` 后的第一条指令是按照栈指针加偏移量设置 `ra` 的值。

![](..\assets\figures\suspend_current.png)
![](../assets/figures/suspend_current.png)

由此,猜测是栈指针遭到修改,继续进行gdb,观察栈指针的变化。

![](..\assets\figures\gdb2.jpg)
![](../assets/figures/gdb2.jpg)

通过gdb很快发现栈指针遭到异常修改,看起来是一个非常地狱的bug,但是非常幸运的是,栈指针异常的数字是一个非常好的数字:正常情况下,进入异常前的栈指针是: `0xffffffc088008e50`, 但是在引发异常的那次跳转中,栈指针 sp 被修改成了 `0xffffffc088011e50`,相差 `0x9000`,这是什么?这恰好是一个进程内核栈的大小!!(8页内核栈加上一页 guard page )从这里我就可以绝对的肯定是 trap 上下文的维护有问题,因为用户内核栈的基址和内核栈的分配都只与 trap 上下文相关,而非之前关注的任务上下文 `task_cx`

Expand Down

0 comments on commit 8e46b1e

Please sign in to comment.