SYSRET与SYSRETQ的区别和兼容模式

时间:2018-08-02 20:17:38

标签: assembly x86 x86-64 intel cpu-architecture

我要使用SYSCALL / SYSRET指令的Intel实现。如果我正确地阅读their documentation,与SYSCALL的AMD's implmenetation不同,则只能从64位长模式调用Intel的版本。正确吗?

但是如果我阅读了随附说明SYSRET的英特尔文档,它有两种形式:

  • SYSRET 0F 07 =“从快速系统调用返回到兼容模式”

  • SYSRETQ 48 0F 07 =“从快速系统调用返回到64位模式”

因此,我只是想了解它,如果无法从SYSRET调用0F 07SYSCALL),将在什么时候返回兼容模式?

1 个答案:

答案 0 :(得分:4)

虽然英特尔版本的SYSCALL不能在兼容模式下使用,但是SYSRET指令可以从64位模式使用以“返回”兼容模式。 SYSRET指令不需要前面的SYSCALL指令即可工作,就像RET指令不需要前面的CALL指令一样。

《英特尔64和IA-32体系结构软件开发人员手册》记录了SYSRET指令的操作,如下所示:

  

IF(CS.L≠1)或(IA32_EFER.LMA≠1)或(IA32_EFER.SCE≠1)(*不在   IA32_EFER中未启用64位模式或SYSCALL / SYSRET *)
  然后#UD; FI;
  如果(CPL≠0)或(RCX不规范)THEN #GP(0); FI;
  IF(操作数大小为64位)
  然后(*返回64位模式*)
  RIP←RCX;
  ELSE(*返回兼容模式*)
  RIP←ECX;
  FI;
  RFLAGS←(R11和3C7FD7H)| 2; (*清除RF,VM,保留位;将位2设置为*)

     

IF(操作数大小为64位)
  THEN CS.Selector←IA32_STAR [63:48] +16;
  ELSE CS。选择器←IA32_STAR [63:48];
  FI;
  CS.Selector←CS.Selector或3; (* RPL强制为3 *)
  (*将CS的其余部分设置为固定值*)
  CS.Base>←0; (*扁平段*)
  CS.Limit←FFFFFH; (*具有4 KB的粒度,表示限制为4 GB *)
  CS.Type←11; (*执行/读取代码,已访问*)
  CS.S←1;
  CS.DPL←3;
  CS.P←1;
  IF(操作数大小为> 64位)
  然后(*返回64位模式*)
  CS.L←1; (* 64位代码段*)
  CS.D←0; (*如果CS.L = 1 *,则为必需)
  ELSE(*返回兼容模式*)
  CS.L←0; (*兼容模式*)
  CS.D←1; (* 32位代码段*)
  FI;
  CS.G←1; (* 4 KB粒度*)
  CPL←3;
  [...]

您可以看到,根据操作数的大小,运算之间存在差异。值得注意的是,使用32位操作数时,CS.L和CS.D标志设置为0和1,这意味着CPU在32位兼容模式下从ECX给定的地址开始执行指令。不管如何输入内核(特权级别0),它都会这样做。

虽然在Intel CPU上不能以最明显的方式使用SYSRET的32位操作数大小版本,以恢复执行使用SYSCALL进入内核的32位兼容模式任务,它可能还有其他用途。例如开始执行新的32位任务,甚至恢复通过其他某种方式进入内核的任务。