ERETU
事件返回用户
stableVMJITAOTinstruction
编码
| 操作码 | 指令 | Op/En | 64 位 | 兼容/传统 | 说明 |
|---|---|---|---|---|---|
F3 0F 01 CA | ERETU | ZO | 有效 | 有效 | 3号环发生事件事件返回事件。 |
实测开销
正在从 arch-data 加载实测数据...
涉及的标志位
VM虚拟 8086
说明
ERETU从事件处理器返回,根据堆栈的内容建立状态(典型的,是FRED事件交付前有效的状态). ERETU只有在CPL=0的情况下才能执行,它将CPL修改为3. 为此,ERETU用于处理CPL=3.
ERETU不采用明确的参数;其操作取决于正则堆栈的内容.
执行ERETU时,如果FRED的过渡没有被启用,或者CPL > 0,则导致无效的-操作码例外(#UD). 为此,ERETU只能以64位模式执行.
ERETU以三种不同方式之一确定了CS和SS的新值:
- 如果从堆栈中跳出的值对应 IA32 STAR [63:48] + 16 和
IA32 STAR [63:48] + 8,CS和SS分别加载了64位模式操作的标准值(类似由64位形式SYSCALL所建立的标准值).
- 如果从堆栈中跳出的值对应 IA32 STAR [63:48] 和 IA32 STAR [63:48] + 的值.
8,CS和SS分别被装入兼容模式下操作的标准值(类似由32位形式SYSCALL所建立的标准值).
- 否则, CS 和 SS 从 GDT 或 LDT 中装入 。
IRET的64位形式使用的方式。
详见下面的操作部分和第8.4.2节,"ERETU(Event Return to User)",载于Intel(R)64和IA-32架构软件开发者手册第3卷.
指令令. 执行ERETU后的指示可能在早先的指示完成执行之前从内存中获取,但是在ERETU前的所有指示完成执行之前不会执行(甚至推测)(以后的指示可能在先前的指示存储的数据变得全球可见之前执行).
行动
IF CR4.FRED = 0 OR CS.L = 0 OR CPL > 0
THEN #UD;
FI;
IF CSL > 0
THEN #GP(0);
FI;
// pop old state from regular stack and check it
RSP := RSP + 8; // skip over error code so that RSP references the return state
pop8B newRIP;
pop8B tempCS;
pop8B newRFLAGS;
pop8B newRSP;
pop8B tempSS;
IF tempCS & FFFFFFFF_FFFF0003H 3 OR // enforce return to ring 3
newRFLAGS & FFFFFFFF_FFC2B02AH 2 OR // enforce bit 1 set; IOPL, VM, reserved bits clear
tempSS & FFF80003H 3 // do not check bits 63:32
THEN #GP(0);
FI;
pend_DB := tempSS[17];
NMI_unblock := tempSS[18];
IF tempCS[15:0] = IA32_STAR[63:48] + 16 AND tempSS[15:0] = IA32_STAR[63:48] + 8
THEN // Return to ring 3 in standard 64-bit configuration
// set newCS to standard values used ring 3 in 64-bit mode
newCS.selector := tempCS[15:0];
newCS.base := 0;
newCS.limit := FFFFFH;
newCS.type := 11;
newCS.S := 1;
newCS.DPL := 3;
newCS.P := 1;
newCS.L := 1;
newCS.D := 0;
newCS.G := 1;
newCS.unusable := 0;
// set newSS to standard values for ring 3
newSS.selector := tempSS[15:0];
newSS.base := 0;
newSS.limit := FFFFFH;
newSS.type := 3;
newSS.S := 1;
newSS.DPL := 3;
newSS.P := 1;
newSS.B := 1;
newSS.G := 1;
newSS.unusable := 0;
ELSIF tempCS[15:0] = IA32_STAR[63:48] AND tempSS[15:0] = IA32_STAR[63:48] + 8
THEN
// set newCS to standard values used ring 3 in compatibility mode
newCS.selector := tempCS[15:0];
newCS.base := 0;
newCS.limit := FFFFFH;
newCS.type := 11;
newCS.S := 1;
newCS.DPL := 3;
newCS.P := 1;
newCS.L := 0;
newCS.D := 1;
newCS.G := 1;
newCS.unusable := 0;
// set newSS to standard values for ring 3
newSS.selector := tempSS[15:0];
newSS.base := 0;
newSS.limit := FFFFFH;
newSS.type := 3;
newSS.S := 1;
newSS.DPL := 3;
newSS.P := 1;
newSS.B := 1;
newSS.G := 1;
newSS.unusable := 0;
ELSE
load newCS using tempCS[15:0]; // load each as is done by IRET, including
load newSS using tempSS[15:0]; // checks that may lead to a fault
FI;
IF newCS.L = 1
THEN // return to 64-bit mode
IF newRIP is not paging canonical
THEN #GP(0);
FI;
ELSE // return to compatibility mode
newRIP[63:32] := 0;
IF newRIP is not within newCS's limit (based on limit field and G bit)
// newRIP is always within the limit with standard values for ring 3 in compatibility mode
THEN #GP(0);
FI;
newRSP[63:32] := 0;
FI;
// If user shadow stacks are enabled, check new SSP value on return to compatibility mode
IF CR4.CET = 1 AND IA32_U_CET.SH_STK_EN = 1 AND newCS.L = 0 AND IA32_PL3_SSP[63:32] 0
THEN #GP(0);
FI;
// If supervisor shadow stacks are enabled, compare SSP to the FRED SSP MSR for stack level 0
IF CR4.CET = 1 AND IA32_S_CET.SH_STK_EN = 1 AND IA32_FRED_SSP0 SSP
THEN #CP(FAR-RET/IRET);
FI;
// update registers for return state
RIP := newRIP;
RFLAGS := newRFLAGS; // ERETU can set RFLAGS.RF to 1
RSP := newRSP; // load all 64 bits regardless of new mode
CS := newCS; // selector and descriptor
SS := newSS; // selector and descriptor
CPL := 3;
// swap GS.base and IA32_KERNEL_GS_BASE
tempGSB := GS.base;
GS.base := IA32_KERNEL_GS_BASE;
IA32_KERNEL_GS_BASE := tempGSB;
IF CR4.CET = 1 AND IA32_U_CET.SH_STK_EN = 1
THEN SSP := IA32_PL3_SSP;
FI;
// update event-related state
IF NMI_unblock = 1
THEN unblock NMIs;
FI;
IF pend_DB = 1 AND RFLAGS.TF =1
THEN pend a single-step debug exception (#DB) to be delivered after ERETU;
FI;受影响的旗帜
RFLAGS登记册中所有定义的旗帜和字段,除了VM旗之外,都有潜在的修改.
异常
保护模式
#UD | ERETU指令在保护模式中不被识别. |
实地址模式
#UD | ERETU指令在实地址模式中不被识别. |
虚拟 8086 模式
#UD | ERETU指令在虚拟 8086 模式中不被识别. |
兼容模式
#UD | ERETU指令在兼容模式中不被识别. |
64 位模式
#UD | 如果 CR4.FRED = 0. 则使用该词. |
#GP(0) | 如果CPL >0. 如果LOCK前缀被使用。如果CSL >0,如果返回为64位模式和RIP堆栈上的图像不是 page canonical 。如果返回到兼容模式和低32位RIP堆栈上的图像不在CS.limit如果RFLAGS堆栈上的图像设置保留位元或 VM 位元( 或未设置位元 1) 如果位元为 13: 12RFLAGS堆栈上的图像(对应IOPL)不是零。如果堆栈(目标)上的 CS 图像的比特值为 1: 0CPL)不是 3. 如果堆栈上的 CS 图像的位值为 63:16 。如果堆栈上的 SS 图像的位值为 1: 0 (目标)CPL)不是 3. 如果堆栈上的 SS 图像设置了未定义的位数( 位数 31: 19) 。 如果返回为兼容模式, 并加载SSP,其值设置任意位数 63:32。如果ERETU正在从描述表格中装入 CS 和 SS(见操作部分),以下任一应用: * 如果堆栈上的 CS 图像的位值为 15:2 。 * 如果堆栈上的 SS 图像的位值为 0 。 |
#GP(selector) | 如果 ERETU 从描述表(见操作部分) 中装入 CS 和 SS ,那么以下任何一种应用 : * A 段选择子 索引在其描述表限制之外. * 段描述内存地址不是 page canonical. * CS 的段描述符并不表示它是一个代码段. * CS 的段描述符同时有 D 位和 L 位的设置. * CS 的段描述符是不符合的,其 DPL 不是 3. * SS 的段描述符并不表示它是可写数据段. |
#SS(0) | *SS的片段描述符的DPL不是3. 如果普通的堆栈访问会使用一个不拨号的地址,或者会导致LASS的违反. #CP(FAR-RET/IRET) 如果SSP的值与IA32 FRED SP0. |