LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1655|回复: 3

sysenter系统调用的疑问

[复制链接]
发表于 2006-2-1 22:52:32 | 显示全部楼层 |阅读模式
在执行INT指令时,实际完成了以下几条操作:
1.由于INT指令发生了不同优先级之间的控制转移,所以首先从TSS(任务状态段)中获取高优先级的核心堆栈信息(SS和ESP);2.把低优先级堆栈信息(SS和ESP)保留到高优先级堆栈(即核心栈)中;
3.把EFLAGS,外层CS,EIP推入高优先级堆栈(核心栈)中。
4.通过IDT加载CS,EIP(控制转移至中断处理函数)
5.然后就进入了中断0x80的处理函数system_call了

在5的处理函数被调用时用struct pt_regs regs作参数就可以访问内核栈,进而可以获得用户态的CS、EIP、SS、ESP。然而
在 Ring3 的代码调用了 sysenter 指令之后,CPU 会做出如下的操作:
1.将 SYSENTER_CS_MSR 的值装载到 cs 寄存器
2.将 SYSENTER_EIP_MSR 的值装载到 eip 寄存器
3.将 SYSENTER_CS_MSR 的值加 8(Ring0 的堆栈段描述符)装载到 ss 寄存器。
4.将 SYSENTER_ESP_MSR 的值装载到 esp 寄存器
5.将特权级切换到 Ring0
6.如果 EFLAGS 寄存器的 VM 标志被置位,则清除该标志
7.开始执行指定的 Ring0 处理函数
那么,处理函数被调用前sysenter的内核栈的结构和INT的内核栈结构相同吗?
返回原程序时用户态的CS、EIP、SS、ESP如何得到?
发表于 2006-6-28 16:47:03 | 显示全部楼层
在此处,系统调用必然需要由Ring3进入Ring0,权限提升前的级别是固定的,CPL必定是3,而门描述府的CPL也是3,因而级别检验完全没有必要,而两个内核栈的结构相同,故也没有压栈的操作
回复 支持 反对

使用道具 举报

发表于 2006-6-28 17:03:47 | 显示全部楼层
在 Ring0 代码执行完毕,调用 SYSEXIT 指令退回 Ring3 时,CPU 会做出如下操作:

  1.将 SYSENTER_CS_MSR 的值加 16(Ring3 的代码段描述符)装载到 cs 寄存器

  2.将寄存器 edx 的值装载到 eip 寄存器

  3.将 SYSENTER_CS_MSR 的值加 24(Ring3 的堆栈段描述符)装载到 ss 寄存器

  4.将寄存器 ecx 的值装载到 esp 寄存器

  5.将特权级切换到 Ring3

  6.继续执行 Ring3 的代码

  由此可知,在调用 SYSENTER 进入 Ring0 之前,一定需要通过 wrmsr 指令设置好 Ring0 代码的相关信息,在调用 SYSEXIT 之前,还要保证寄存器edx、ecx 的正确性。
回复 支持 反对

使用道具 举报

发表于 2006-6-29 15:44:40 | 显示全部楼层
这个问题请看Kernel/sys_call.s的
system_call代码就知道了!

它在进入RING0处理前会把原先的寄存器内容压栈(SAVE_ALL)!从RING0返回前会执行
(RESTORE_ALL),弹出先前被保护的寄存器值!

注:我用的核心是1.0版本!(高版本的核心我机器没有,不过原理应该是一样的)
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表