ERETU

Event Return to User

stableVMJITAOTinstruction

Encodings

OpcodeInstructionOp/En64-bitCompat/LegacyDescription
F3 0F 01 CAERETUZOValidValidEvent return for events occurring in ring 3.

Measured cost

Loading measurements from arch-data...

Flags named

Description

ERETU returns from an event handler, establishing the state based on the contents of the stack (typically, that which was in effect before FRED event delivery). ERETU can be executed only if CPL = 0, and it changes CPL to 3. For this reason, ERETU is used to return from handling events that occurred while CPL = 3.

ERETU takes no explicit arguments; its operation depends on the contents of the regular stack.

Execution of ERETU causes an invalid-opcode exception (#UD) if FRED transitions are not enabled or if CPL > 0. For this reason, ERETU can be executed only in 64-bit mode.

ERETU establishes new values of CS and SS in one of three different ways:

IA32_STAR[63:48] + 8, respectively, CS and SS are loaded with standard values for operation in 64-bit mode (similar those established by the 64-bit form of SYSCALL).

8, respectively, CS and SS are loaded with standard values for operation in compatibility mode (similar those established by the 32-bit form of SYSCALL).

manner used by the 64-bit form of IRET).

For further details see the Operation section below and Section 8.4.2, "ERETU (Event Return to User)," in the Intel(R) 64 and IA-32 Architectures Software Developer's Manual, Volume 3.

Instruction ordering. Instructions following execution of ERETU may be fetched from memory before earlier instructions complete execution, but they will not execute (even speculatively) until all instructions prior to ERETU have completed execution (the later instructions may execute before data stored by the earlier instructions have become globally visible).

Operation

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;

Flags affected

All defined flags and fields in the RFLAGS register are potentially modified except for the VM flag.

Exceptions

Protected mode
#UDThe ERETU instruction is not recognized in protected mode.
Real address mode
#UDThe ERETU instruction is not recognized in real-address mode.
Virtual-8086 mode
#UDThe ERETU instruction is not recognized in virtual-8086 mode.
Compatibility mode
#UDThe ERETU instruction is not recognized in compatibility mode.
64-bit mode
#UDIf CR4.FRED = 0.
#GP(0)If CPL > 0. If the LOCK prefix is used. If CSL > 0. If the return is to 64-bit mode and the RIP image on the stack is not paging canonical. If the return is to compatibility mode and the low 32 bits of the RIP image on the stack is not within the CS.limit being established. If the RFLAGS image on the stack sets reserved bits or the VM bit (or fails to set bit 1). If bits 13:12 of the RFLAGS image on the stack (corresponding to IOPL) are not zero. If the value of bits 1:0 of the CS image on the stack (the target CPL) is not 3. If the value of bits 63:16 of the CS image on the stack is not zero. If the value of bits 1:0 of the SS image on the stack (the target CPL) is not 3. If the SS image on the stack sets undefined bits (bits 31:19). If the return is to compatibility mode and would load SSP with a value that sets any of bits 63:32. If ERETU is loading CS and SS from descriptor tables (see Operation section) and either of the following apply: * If the value of bits 15:2 of the CS image on the stack is 0. * If the value of bits 15:2 of the SS image on the stack is 0.
#GP(selector)If ERETU is loading CS and SS from descriptor tables (see Operation section) and any of the following apply: * A segment selector index is outside its descriptor table limits. * A segment descriptor memory address is not paging canonical. * The segment descriptor for CS does not indicate that it is a code segment. * The segment descriptor for CS has both the D-bit and L-bit set. * The segment descriptor for CS is non-conforming and its DPL is not 3. * The segment descriptor for SS does not indicate that it is a writable data segment.
#SS(0)* The DPL of the segment descriptor for SS is not 3. If an ordinary stack access would use an address that is not paging canonical or would cause a LASS violation. #CP(FAR-RET/IRET) If the value in SSP differs from that in IA32_FRED_SSP0.

Sources