1 回答
TA贡献1951条经验 获得超3个赞
usergs指的是x86-64 swapgs指令,该指令gs
与内部保存的GS值交换给内核,以从syscall入口点查找内核堆栈。交换也交换缓存的gsbase段信息,而不是根据gs
值本身从GDT重新加载。(wrgsbase
可以独立于GDT / LDT更改GS基础)
AMD的设计是syscall
不更改RSP以指向内核堆栈,并且不读取/写入任何内存,因此syscall
它本身可以很快。但是随后您进入内核,其中所有寄存器都保存着它们的用户空间值。请参阅为什么Windows64使用与x86-64上所有其他操作系统不同的调用约定?在2000年左右内核开发人员和AMD架构师之间讨论邮件列表讨论的一些链接,在出售任何AMD64 CPU之前调整其设计syscall
并swapgs
使其可用。
显然,要跟踪GS当前是内核还是用户值对于错误处理是很棘手的:没有办法说“我现在要kernelgs”。您必须知道是否swapgs
在任何错误处理路径中运行。唯一的指令是交换,而不是将其设置为一个与另一个。
阅读arch/x86/entry/entry_64.S
例如https://github.com/torvalds/linux/blob/9fb71c2f230df44bdd237e9a4457849a3909017d/arch/x86/entry/entry_64.S#L1267(来自当前Linux)中的注释,其中提到了usergs,下一个注释块描述了swapgs
在执行之前使用内核gsbase跳转到一些错误处理代码。
IIRC,Linux内核[gs:0]
在该线程的内核堆栈的最低地址处拥有一个线程信息块。该块包括内核堆栈指针(作为绝对地址,而不是相对于gs
)。
如果此错误基本上是在诱使内核rsp
从用户控制的gsbase加载内核,或者搞砸了死胡同,swapgs
从而使它gs
在某些时候出现错误,我不会感到惊讶。
- 1 回答
- 0 关注
- 330 浏览
添加回答
举报