使用 SYSENTER 和 SYSEXIT 指令执行对系统过程的快速调用

SYSENTER 和 SYSEXIT 指令被引入奔腾 II 处理器的 IA-32 体系结构中,目的是为调用操作系统或执行程序提供一种快速(低开销)机制。

SYSENTER 供以权限级别 3 运行的用户代码使用以访问以权限级别 0 运行的操作系统或执行程序。SYSEXIT 供权限级别 0 操作系统或执行程序使用以快速返回权限级别 3 用户 代码。SYSENTER 可以从权限级别 3、2、1 或 0 执行;SYSEXIT 只能从权限级别 0 执行。

SYSENTER 和 SYSEXIT 指令是伴随指令,但它们不构成调用/返回对。这是因为 SYSENTER 不保存任何状态信息供 SYSEXIT 在返回时使用。

这些指令的目标指令和堆栈指针不是通过指令操作数指定的。相反,它们是通过在 MSR 和通用寄存器中输入的参数来指定的。

对于 SYSENTER,目标字段是使用以下源生成的:


  • 目标代码段:从 IA32_SYSENTER_CS 读取。

  • 目标指令:从 IA32_SYSENTER_EIP 读取。

  • 堆栈段:通过将 8 添加到 IA32_SYSENTER_CS 中的值来计算。

  • 堆栈指针:从 IA32_SYSENTER_ESP 中读取。


对于 SYSEXIT,目标字段是使用以下源生成的:


  • 目标代码段:通过将 16 添加到 IA32_SYSENTER_CS 中的值来计算。

  • 目标指令:从 EDX 读取。

  • 堆栈段:通过将 24 添加到 IA32_SYSENTER_CS 中的值来计算。

  • 堆栈指针:从 ECX 读取。


SYSENTER 和 SYSEXIT 指令执行“快速”调用和返回,因为它们在执行 SYSENTER 时强制处理器进入预定义的权限级别 0 状态,并在执行 SYSEXIT 时强制处理器进入预定义的权限级别 3 状态。通过强制预定义和一致的处理器状态,通常执行对另一个特权级别的远程调用所需的特权检查数量大大减少。此外,通过在 MSR (会有单独一篇讲述MSR寄存器)和通用寄存器中预定义目标上下文状态,消除了除获取目标代码之外的所有内存访问。

任何需要保存以允许返回调用过程的附加状态必须由调用过程显式保存或通过编程约定进行预定义。

IA-32e 模式下的 SYSENTER 和 SYSEXIT 指令


对于 Intel 64 位处理器,SYSENTER 和 SYSEXIT 指令得到增强,以允许从以权限级别 3(兼容模式或 64 位模式)运行的用户代码到以权限级别 0 运行的 64 位执行程序的快速系统调用。IA32_SYSENTER_EIP MSR 和 IA32_SYSENTER_ESP MSR 被扩展以保存 64 位地址。如果 IA-32e 模式未激活,则仅使用存储在这些 MSR 中的低 32 位地址。WRMSR 指令确保存储在这些 MSR 中的地址是规范的。请注意,在 64 位模式下,IA32_SYSENTER_CS 不得包含 NULL 选择器。

32bit模式不做过多讲解,感兴趣请参考《Intel® 64 and IA-32 Architectures Software Developer’s Manual》。

64 位模式下的快速系统调用


SYSCALL 和 SYSRET 指令是为使用平面内存模型(不使用分段)的操作系统设计的。这些指令与 SYSENTER 和 SYSEXIT 一起适用于 IA-32e 模式操作。但是,兼容模式(或保护模式)不支持 SYSCALL 和 SYSRET。使用 CPUID 检查 SYSCALL 和 SYSRET 是否可用(CPUID.80000001H.EDX[bit 11] = 1)。

SYSCALL 旨在供以特权级别 3 运行的用户代码用于访问以特权级别 0 运行的操作系统或执行过程。SYSRET 旨在供特权级别 0 操作系统或执行过程使用以快速返回到特权级别 3 用户 代码。

SYSCALL/SYSRET 的堆栈指针不是通过特定于模型的寄存器指定的。RFLAGS 中位的清除是可编程的,而不是固定的。SYSCALL/SYSRET 保存和恢复 RFLAGS 寄存器。

对于SYSCALL,处理器将RFLAGS存入R11,将下一条指令的RIP存入RCX;然后它获取特权级 0 目标代码段、指令指针、堆栈段和标志,如下所示:


  • 目标代码段:从 IA32_STAR[47:32] 读取一个非 NULL 选择器。

  • 目标指令指针:从IA32_LSTAR读取64位地址。(WRMSR 指令确保 IA32_LSTAR MSR 的值是规范的。)

  • 堆栈段:通过将 8 添加到 IA32_STAR[47:32] 中的值来计算。

  • 标志:处理器将 RFLAGS 设置为其当前值与 IA32_FMASK MSR 中值的补码的逻辑与。

当 SYSRET 使用 REX.W 将控制权转移到 64 位模式用户代码时,处理器获取特权级别 3 目标代码段、指令指针、堆栈段和标志如下:

  • 目标代码段:从 IA32_STAR[63:48] + 16 读取一个非 NULL 选择器。

  • 目标指令指针:将 RCX 中的值复制到 RIP 中。

  • 堆栈段:IA32_STAR[63:48] + 8。

  • EFLAGS:从 R11 加载。

当 SYSRET 使用 32 位操作数大小将控制权转移到 32 位模式用户代码时,处理器获取特权级别 3 目标代码段、指令指针、堆栈段和标志如下:

  • 目标代码段:从 IA32_STAR[63:48] 读取一个非 NULL 选择器。

  • 目标指令指针:将ECX中的值复制到EIP中。

  • 堆栈段:IA32_STAR[63:48] + 8。

  • EFLAGS :从 R11 加载。

操作系统有责任确保 GDT/LDT 中的描述符对应于 SYSCALL/SYSRET 加载的选择器(与指令强制的基值、限制值和属性值一致)。

IA32_STAR、IA32_LSTAR、IA32_FMASK 的布局见下图。



SYSCALL 指令不保存堆栈指针,SYSRET 指令不恢复它。操作系统系统调用处理程序很可能会将堆栈指针从用户堆栈更改为操作系统堆栈。如果是这样,首先保存用户堆栈指针是软件的责任。这可能在执行 SYSCALL 之前由用户代码完成,或者在 SYSCALL 之后由操作系统系统调用处理程序完成。

由于 SYSRET 指令不修改堆栈指针,因此需要软件切换回用户堆栈。操作系统可能会在执行 SYSRET 之前加载用户堆栈指针(如果它是在 SYSCALL 之后保存的);或者,用户代码可以在收到来自 SYSRET 的控制后加载堆栈指针(如果它在 SYSCALL 之前保存)。

如果操作系统在执行 SYSRET 之前加载堆栈指针,它必须确保在恢复堆栈指针和成功执行 SYSRET 之间传递的任何中断或异常的处理程序不被用户堆栈调用。它可以使用以下方法来做到这一点:


  • 外部中断:操作系统可以通过在加载用户堆栈指针之前清除 EFLAGS.IF 来防止传递外部中断。

  • 不可屏蔽中断 (NMI):操作系统可以通过使用 IDT 中的门 2 (NMI) 的中断堆栈表 (IST) 机制来确保使用正确的堆栈调用 NMI 处理程序。

  • 一般保护例外 (#GP):如果 RCX 的值不规范,SYSRET 指令会生成 #GP(0)。操作系统可以使用以下一种或多种方法来解决这种可能性:

    • 在执行 SYSRET 之前确认 RCX 的值是规范的。

    • 使用分页来确保 SYSCALL 指令永远不会将非规范值保存到 RCX 中。

    • 对 IDT 中的 13 号门 (#GP) 使用 IST 机制。

参考


《Intel® 64 and IA-32 Architectures Software Developer’s Manual》

CPL,RPL和DPL:这三个级别你搞懂了吗?

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 系统调用位的指令是一种特殊的指令,用于将控制权从用户态转换到内核态,并请求内核执行一些特殊操作,例如读取文件、创建进程、打开网络连接等。这些指令通常由操作系统提供,并且只能在特权模式下执行。在x86架构中,系统调用位的指令是int 0x80或syscall指令。在其他架构中,可能存在不同的指令用于实现系统调用。 ### 回答2: 属于系统调用位的指令是一种可以让用户程序访问操作系统功能的特殊指令。在计算机运行过程中,用户程序和操作系统是分开运行的,用户程序无法直接访问操作系统的底层功能。而系统调用位的指令可以在用户程序中引发软中断,将控制权交给操作系统,并请求执行特定的操作。 系统调用位的指令的形式一般为软中断指令,如INT、SYSENTERSYSCALL等。当用户程序遇到这类指令时,会触发软中断,将控制权交给操作系统,操作系统会根据不同的指令执行相应的系统调用。系统调用提供了一系列接口,包括文件操作、进程管理、内存管理等功能,用户程序可以通过系统调用使用这些操作系统提供的功能。 属于系统调用位的指令有助于实现用户程序与操作系统的交互,提供了一种安全可靠的方式来访问操作系统功能。通过系统调用,用户程序可以请求操作系统执行某些敏感的、特权级别高的操作,如文件读写、网络通信等。系统调用还可以实现进程间通信和资源共享,在多任务操作系统中发挥重要作用。 总之,属于系统调用位的指令是一种重要的机制,它使得用户程序能够使用操作系统的底层功能,实现更复杂、更强大的计算机应用。同时,系统调用还能够保护操作系统的安全性,防止用户程序对操作系统进行非法操作。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值