SYSRET

从快速系统调用返回

stableVMJITAOTinstruction

编码

操作码指令Op/En64 位兼容/传统说明
0F 07SYSRETZO有效无效从快速系统调用返回兼容模式 。
REX.W + 0F 07SYSRETZO有效无效从快速系统调用返回到64位模式.

实测开销

未实测:不在 64 位处理器上运行。

说明

SYSRET是SYSCALL指令的伴奏指令. 它从OS系统调用处理器返回到特权级别3的用户代码. 它这样做的方式是从RCX装入RIP,从R11.1装入RFLAGS,带有64位的操作数大小,SYSRET仍然处于64位模式;否则,它进入兼容模式,只有低位的32位登记器被装入.

SYSRET用IA32 STAR MSR中的位数63:48来加载CS和SS选择器. 然而,CS和SS的描述缓存并没有从这些选择者引用的描述符(在GDT或LDT)中加载. 相反,描述符缓存被装入固定值. 详情见行动科。 OS软件有责任确保这些选择器值引用的描述符(在GDT或LDT中)与装入描述符缓存的固定值相对应;SYSRET指令不保证这种对应.

SYSRET指令不修改栈指针(ESP或RSP). 为此,软件必须切换到用户堆栈. OS可以在执行SYSRET之前加载用户栈指针(如果它是在SYSCALL之后保存的);或者,用户代码可以在从SYSRET接收控制后加载栈指针(如果是在SYSCALL之前保存的).

如果OS在执行SYSRET前加载了栈指针,它必须确保在恢复栈指针与成功执行SYSRET之间发送的任何中断或例外的处理器不会与用户堆栈一起被引用. 它可以采用以下方法:

在装入用户 栈指针 之前。

使用IDT中闸门2(NMI)的中断堆栈表(IST)机制(见7.14.5节,"中断堆栈表",Intel(R)64和IA-32架构软件开发者手册,第3A卷).

犬齿. 监督办可采用以下一种或多种办法处理这种可能性:

-- 使用 page 来保证 SYSCALL 指令永远不会将一个非卡通值保存到 RCX 中.

当在特权级别3启用阴影堆栈时,指令加载SSP,其值来自IA32 PL3 SSP MSR. 参考英特尔(R)64和IA-32架构软件开发者手册第1卷第6章"程序调用,中断,和例外"和第18章"控制流执行技术(CET)",以获得额外的CET细节.

启用 FRED 转换时无法执行指令 。 一个已经允许FRED过渡的操作系统应该使用ERETU代替.

  1. 联合国 无论R11的值如何,RF和VM旗在RFLAGS执行SYSRET后总是0. 此外,RFLAGS中的所有保留位保留了固定值.

指令令. 遵循一个SYSRET的指令,可以在早期指令完成执行之前从内存中获取,但是在SYSRET之前的所有指令完成执行之前,它们不会执行(甚至推测)(在早期指令存储的数据变得全球可见之前,后期指令可能执行).

行动

IF (CS.L  1 ) or (IA32_EFER.LMA  1) or (IA32_EFER.SCE  1) or (CR4.FRED = 1)

(* Not in 64-Bit Mode or SYSCALL/SYSRET not enabled in IA32_EFER or FRED enabled *)
    THEN #UD; FI;

IF (CPL  0) THEN #GP(0); FI;

IF (operand size is 64-bit)

     THEN (* Return to 64-Bit Mode *)

     IF (RCX is not canonical) THEN #GP(0);

     RIP := RCX;

     ELSE (* Return to Compatibility Mode *)

     RIP := ECX;

FI;

RFLAGS := (R11 & 3C7FD7H) | 2;                (* Clear RF, VM, reserved bits; set bit 1 *)

IF (operand size is 64-bit)

     THEN CS.Selector := IA32_STAR[63:48]+16;

     ELSE CS.Selector := IA32_STAR[63:48];

FI;

CS.Selector := CS.Selector OR 3;              (* RPL forced to 3 *)

(* Set rest of CS to a fixed value *)

CS.Base := 0;                                 (* Flat segment *)

CS.Limit := FFFFFH;                           (* With 4-KByte granularity, implies a 4-GByte limit *)

CS.Type := 11;                                (* Execute/read code, accessed *)

CS.S := 1;

CS.DPL := 3;

CS.P := 1;

IF (operand size is 64-bit)

     THEN (* Return to 64-Bit Mode *)

     CS.L := 1;                               (* 64-bit code segment *)

     CS.D := 0;                               (* Required if CS.L = 1 *)

     ELSE (* Return to Compatibility Mode *)

     CS.L := 0;                               (* Compatibility mode *)

     CS.D := 1;                               (* 32-bit code segment *)

FI;

CS.G := 1;                                    (* 4-KByte granularity *)

CPL := 3;

IF ShadowStackEnabled(CPL)

     SSP := IA32_PL3_SSP;

FI;

SS.Selector := (IA32_STAR[63:48]+8) OR 3;     (* RPL forced to 3 *)
(* Set rest of SS to a fixed value *)         (* Flat segment *)
SS.Base := 0;                                 (* With 4-KByte granularity, implies a 4-GByte limit *)
SS.Limit := FFFFFH;                           (* Read/write data, accessed *)
SS.Type := 3;
SS.S := 1;                                    (* 32-bit stack segment*)
SS.DPL := 3;                                  (* 4-KByte granularity *)
SS.P := 1;
SS.B := 1;
SS.G := 1;

受影响的旗帜

All.

异常

保护模式
#UDSYSRET指令在保护模式中不被识别.
实地址模式
#UDSYSRET指令在实地址模式中不被识别.
虚拟 8086 模式
#UDSYSRET指令在虚拟 8086 模式中不被识别.
兼容模式
#UDSYSRET指令在兼容模式中不被识别.
64 位模式
#UD如果 IA32_EFER.SCE = 0. 如果使用 LOCK 前缀.
#GP(0)如果 CR4.FRED = 1. 如果 CPL 0. 如果返回为64位模式, RCX 包含一个非卡通地址.

来源