Linux2.6对新型CPU快速系统调用的支持

http://tech.ddvip.com   2006年11月20日    社区交流

本文详细介绍Linux2.6对新型CPU快速系统调用的支持

  由此可见,无论是静态还是动态方式,最终我们都来到了 0xffffe400 这里的一段代码,这里就是内核为我们映射的系统调用入口代码。在 gdb 中,我们可以直接反汇编来查看这里的代码。

(gdb) disassemble 0xffffe400 0xffffe414 
Dump of assembler code from 0xffffe400 to 
0xffffe414: 0xffffe400:   push  
%ecx 0xffffe401:   push  
%edx 0xffffe402:   push 
%ebp 0xffffe403:   mov  
%esp,%ebp 0xffffe405:   
sysenter 0xffffe407:   nop 0xffffe408:   
nop 0xffffe409:   nop 0xffffe40a:  
nop 0xffffe40b:   nop 0xffffe40c:   
nop 0xffffe40d:   nop 0xffffe40e:   
jmp  0xffffe403 0xffffe410:   pop  
%ebp 0xffffe411:   pop  %edx 0xffffe412: 
  pop  %ecx 0xffffe413:   ret End of assembler dump.

  这段代码正是 arch/i386/kernel/vsyscall-sysenter.S 文件中的代码。其中,在 sysenter 之前的是入口代码,在 0xffffe410 开始的是内核返回处理代码(后面提到的 SYSENTER_RETURN 即指向这里)。在入口代码中,首先是保存当前的 ecx,edx(由于 sysexit 指令需要使用这两个寄存器)以及 ebp。然后调用 sysenter 指令,跳转到内核 Ring 0 代码,也就是 sysenter_entry 入口处。

  内核中的处理和返回

  sysenter_entry 整个的实现可以参见 arch/i386/kernel/entry.S。 内核处理 SYSENTER 的代码和处理 INT 的代码不太一样。通过 sysenter 指令进入 Ring 0 之后,由于当前的 ESP 并非指向正确的内核栈,而是当前 CPU 的 TSS 结构中的一个缓冲区(参见上文),所以首先要解决的是修复 ESP,幸运的是,TSS 结构中 ESP0 成员本身就保存有 Ring 0 状态的 ESP 值,所以在这里将 TSS 结构中 ESP0 的值赋予 ESP 寄存器。将 ESP 恢复成指向正确的堆栈之后,由于 SYSENTER 不是通过调用门进入 Ring 0,所以在堆栈中的上下文和使用 INT 指令的不一样,INT 指令进入 Ring 0 后栈中会保存如下的值。

责编:豆豆技术应用

正在加载评论...