我要使用SYSCALL / SYSRET指令的Intel实现。如果我正确地阅读their documentation,与SYSCALL的AMD's implmenetation不同,则只能从64位长模式调用Intel的版本。正确吗?
但是如果我阅读了随附说明SYSRET的英特尔文档,它有两种形式:
SYSRET 0F 07
=“从快速系统调用返回到兼容模式”
SYSRETQ 48 0F 07
=“从快速系统调用返回到64位模式”
因此,我只是想了解它,如果无法从SYSRET
调用0F 07
(SYSCALL
),将在什么时候返回兼容模式?
答案 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位任务,甚至恢复通过其他某种方式进入内核的任务。