Opcode/Instruction | Op/En | 64/32 bit Mode Support | CPUID Feature Flag | Description |
---|---|---|---|---|
EAX = 03H ENCLU[ERESUME] | IR | V/V | SGX1 | This leaf function is used to re-enter an enclave after an interrupt. |
Op/En | RAX | RBX | RCX |
IR | ERESUME (In) | Address of a TCS (In) | Address of AEP (In) |
The ENCLU[ERESUME] instruction resumes execution of an enclave that was interrupted due to an exception or interrupt, using the machine state previously stored in the SSA.
TCS |
Enclave read/write access |
The instruction faults if any of the following:
Address in RBX is not properly aligned. | Any TCS.FLAGS’s must-be-zero bit is not zero. |
TCS pointed to by RBX is not valid or available or locked. | Current 32/64 mode does not match the enclave mode in SECS.ATTRIBUTES.MODE64. |
The SECS is in use by another enclave. | Either of TCS-specified FS and GS segment is not a subset of the current DS segment. |
Any one of DS, ES, CS, SS is not zero. | If XSAVE available, CR4.OSXSAVE = 0, but SECS.ATTRIBUTES.XFRM ≠ 3. |
CR4.OSFXSR ≠ 1. | If CR4.OSXSAVE = 1, SECS.ATTRIBUTES.XFRM is not a subset of XCR0. |
Offsets 520-535 of the XSAVE area not 0. | The bit vector stored at offset 512 of the XSAVE area must be a subset of SECS.ATTRIBUTES.XFRM. |
The SSA frame is not valid or in use. |
The following operations are performed by ERESUME:
Leaf | Parameter | Base Concurrency Restrictions | ||
---|---|---|---|---|
Access | On Conflict | SGX_CONFLICT VM Exit Qualification | ||
ERESUME | TCS [DS:RBX] | Shared | #GP |
Leaf | Parameter | Additional Concurrency Restrictions | |||||
---|---|---|---|---|---|---|---|
vs. EACCEPT, EACCEPTCOPY, EMODPE, EMODPR, EMODT | vs. EADD, EEXTEND, EINIT | vs. ETRACK, ETRACKC | |||||
Access | On Conflict | Access | On Conflict | Access | On Conflict | ||
ERESUME | TCS [DS:RBX] | Concurrent | Concurrent | Concurrent |
Name | Type | Size | Description |
---|---|---|---|
TMP_FSBASE | Effective Address | 32/64 | Proposed base address for FS segment. |
TMP_GSBASE | Effective Address | 32/64 | Proposed base address for FS segment. |
TMP_FSLIMIT | Effective Address | 32/64 | Highest legal address in proposed FS segment. |
TMP_GSLIMIT | Effective Address | 32/64 | Highest legal address in proposed GS segment. |
TMP_TARGET | Effective Address | 32/64 | Address of first instruction inside enclave at which execution is to resume. |
TMP_SECS | Effective Address | 32/64 | Physical address of SECS for this enclave. |
TMP_SSA | Effective Address | 32/64 | Address of current SSA frame. |
TMP_XSIZE | integer | 64 | Size of XSAVE area based on SECS.ATTRIBUTES.XFRM. |
TMP_SSA_PAGE | Effective Address | 32/64 | Pointer used to iterate over the SSA pages in the current frame. |
TMP_GPR | Effective Address | 32/64 | Address of the GPR area within the current SSA frame. |
TMP_BRANCH_RECORD | LBR Record | From/to addresses to be pushed onto the LBR stack. |
TMP_MODE64←((IA32_EFER.LMA = 1) && (CS.L = 1));
(* Make sure DS is usable, expand up *)
IF (TMP_MODE64 = 0 and (DS not usable or ( ( DS[S] = 1) and (DS[bit 11] = 0) and DS[bit 10] = 1) ) ) )
THEN #GP(0); FI;
(* Check that CS, SS, DS, ES.base is 0 *)
IF (TMP_MODE64 = 0)
THEN
IF(CS.base ≠ 0 or DS.base ≠ 0) #GP(0); FI;
IF(ES usable and ES.base ≠ 0) #GP(0); FI;
IF(SS usable and SS.base ≠ 0) #GP(0); FI;
IF(SS usable and SS.B = 0) #GP(0); FI;
FI;
IF (DS:RBX is not 4KByte Aligned)
THEN #GP(0); FI;
IF (DS:RBX does not resolve within an EPC)
THEN #PF(DS:RBX); FI;
(* Check AEP is canonical*)
IF (TMP_MODE64 = 1 and (CS:RCX is not canonical) )
THEN #GP(0); FI;
(* Check concurrency of TCS operation*)
IF (Other Intel SGX instructions is operating on TCS)
THEN #GP(0); FI;
(* TCS verification *)
IF (EPCM(DS:RBX).VALID = 0)
THEN #PF(DS:RBX); FI;
IF (EPCM(DS:RBX).BLOCKED = 1)
THEN #PF(DS:RBX); FI;
IF ((EPCM(DS:RBX).PENDING = 1) or (EPCM(DS:RBX).MODIFIED = 1))
THEN #PF(DS:RBX); FI;
IF ( (EPCM(DS:RBX).ENCLAVEADDRESS ≠ DS:RBX) or (EPCM(DS:RBX).PT ≠ PT_TCS) )
THEN #PF(DS:RBX); FI;
IF ( (DS:RBX).OSSA is not 4KByte Aligned)
THEN #GP(0); FI;
(* Check proposed FS and GS *)
IF ( ( (DS:RBX).OFSBASE is not 4KByte Aligned) or ( (DS:RBX).OGSBASE is not 4KByte Aligned) )
THEN #GP(0); FI;
(* Get the SECS for the enclave in which the TCS resides *)
TMP_SECS←Address of SECS for TCS;
(* Make sure that the FLAGS field in the TCS does not have any reserved bits set *)
IF ( ( (DS:RBX).FLAGS & FFFFFFFFFFFFFFFEH) ≠ 0)
THEN #GP(0); FI;
(* SECS must exist and enclave must have previously been EINITted *)
IF (the enclave is not already initialized)
THEN #GP(0); FI;
(* make sure the logical processor’s operating mode matches the enclave *)
IF ( (TMP_MODE64 ≠ TMP_SECS.ATTRIBUTES.MODE64BIT) )
THEN #GP(0); FI;
IF (CR4.OSFXSR = 0)
THEN #GP(0); FI;
(* Check for legal values of SECS.ATTRIBUTES.XFRM *)
IF (CR4.OSXSAVE = 0)
THEN
IF (TMP_SECS.ATTRIBUTES.XFRM ≠ 03H) THEN #GP(0); FI;
ELSE
IF ( (TMP_SECS.ATTRIBUTES.XFRM & XCR0) ≠ TMP_SECS.ATTRIBUTES.XFRM) THEN #GP(0); FI;
FI;
(* Make sure the SSA contains at least one active frame *)
IF ( (DS:RBX).CSSA = 0)
THEN #GP(0); FI;
(* Compute linear address of SSA frame *)
TMP_SSA ← (DS:RBX).OSSA + TMP_SECS.BASEADDR + 4096 * TMP_SECS.SSAFRAMESIZE * ( (DS:RBX).CSSA - 1);
TMP_XSIZE ← compute_XSAVE_frame_size(TMP_SECS.ATTRIBUTES.XFRM);
FOR EACH TMP_SSA_PAGE = TMP_SSA to TMP_SSA + TMP_XSIZE
(* Check page is read/write accessible *)
Check that DS:TMP_SSA_PAGE is read/write accessible;
If a fault occurs, release locks, abort and deliver that fault;
IF (DS:TMP_SSA_PAGE does not resolve to EPC page)
THEN #PF(DS:TMP_SSA_PAGE); FI;
IF (EPCM(DS:TMP_SSA_PAGE).VALID = 0)
THEN #PF(DS:TMP_SSA_PAGE); FI;
IF (EPCM(DS:TMP_SSA_PAGE).BLOCKED = 1)
THEN #PF(DS:TMP_SSA_PAGE); FI;
IF ((EPCM(DS:TMP_SSA_PAGE).PENDING = 1) or (EPCM(DS:TMP_SSA_PAGE_.MODIFIED = 1))
THEN #PF(DS:TMP_SSA_PAGE); FI;
IF ( ( EPCM(DS:TMP_SSA_PAGE).ENCLAVEADDRESS ≠ DS:TMPSSA_PAGE) or (EPCM(DS:TMP_SSA_PAGE).PT ≠ PT_REG) or
(EPCM(DS:TMP_SSA_PAGE).ENCLAVESECS ≠ EPCM(DS:RBX).ENCLAVESECS) or
(EPCM(DS:TMP_SSA_PAGE).R = 0) or (EPCM(DS:TMP_SSA_PAGE).W = 0) )
THEN #PF(DS:TMP_SSA_PAGE); FI;
CR_XSAVE_PAGE_n ← Physical_Address(DS:TMP_SSA_PAGE);
ENDFOR
(* Compute address of GPR area*)
TMP_GPR←TMP_SSA + 4096 * DS:TMP_SECS.SSAFRAMESIZE - sizeof(GPRSGX_AREA);
Check that DS:TMP_SSA_PAGE is read/write accessible;
If a fault occurs, release locks, abort and deliver that fault;
IF (DS:TMP_GPR does not resolve to EPC page)
THEN #PF(DS:TMP_GPR); FI;
IF (EPCM(DS:TMP_GPR).VALID = 0)
THEN #PF(DS:TMP_GPR); FI;
IF (EPCM(DS:TMP_GPR).BLOCKED = 1)
THEN #PF(DS:TMP_GPR); FI;
IF ((EPCM(DS:TMP_GPR).PENDING = 1) or (EPCM(DS:TMP_GPR).MODIFIED = 1)) THEN #PF(DS:TMP_GPR); FI;
IF ( ( EPCM(DS:TMP_GPR).ENCLAVEADDRESS ≠ DS:TMP_GPR) or (EPCM(DS:TMP_GPR).PT ≠ PT_REG) or
(EPCM(DS:TMP_GPR).ENCLAVESECS ≠ EPCM(DS:RBX).ENCLAVESECS) or
(EPCM(DS:TMP_GPR).R = 0) or (EPCM(DS:TMP_GPR).W = 0) )
THEN #PF(DS:TMP_GPR); FI;
IF (TMP_MODE64 = 0)
THEN
IF (TMP_GPR + (GPR_SIZE -1) is not in DS segment) THEN #GP(0); FI;
FI;
CR_GPR_PA←Physical_Address (DS: TMP_GPR);
TMP_TARGET ← (DS:TMP_GPR).RIP;
IF (TMP_MODE64 = 1)
THEN
IF (TMP_TARGET is not canonical) THEN #GP(0); FI;
ELSE
IF (TMP_TARGET > CS limit) THEN #GP(0); FI;
FI;
(* Check proposed FS/GS segments fall within DS *)
IF (TMP_MODE64 = 0)
THEN
TMP_FSBASE←(DS:RBX).OFSBASE + TMP_SECS.BASEADDR;
TMP_FSLIMIT←(DS:RBX).OFSBASE + TMP_SECS.BASEADDR + (DS:RBX).FSLIMIT;
TMP_GSBASE←(DS:RBX).OGSBASE + TMP_SECS.BASEADDR;
TMP_GSLIMIT←(DS:RBX).OGSBASE + TMP_SECS.BASEADDR + (DS:RBX).GSLIMIT;
(* if FS wrap-around, make sure DS has no holes*)
IF (TMP_FSLIMIT < TMP_FSBASE)
THEN
IF (DS.limit < 4GB) THEN #GP(0); FI;
ELSE
IF (TMP_FSLIMIT > DS.limit) THEN #GP(0); FI;
FI;
(* if GS wrap-around, make sure DS has no holes*)
IF (TMP_GSLIMIT < TMP_GSBASE)
THEN
IF (DS.limit < 4GB) THEN #GP(0); FI;
ELSE
IF (TMP_GSLIMIT > DS.limit) THEN #GP(0); FI;
FI;
ELSE
TMP_FSBASE ← DS:TMP_GPR.FSBASE;
TMP_GSBASE ← DS:TMP_GPR.GSBASE;
IF ( (TMP_FSBASE is not canonical) or (TMP_GSBASE is not canonical))
THEN #GP(0); FI;
FI;
(* Ensure the enclave is not already active and this thread is the only one using the TCS*)
IF (DS:RBX.STATE = ACTIVE))
THEN #GP(0); FI;
(* SECS.ATTRIBUTES.XFRM selects the features to be saved. *)
(* CR_XSAVE_PAGE_n: A list of 1 or more physical address of pages that contain the XSAVE area. *)
XRSTOR(TMP_MODE64, SECS.ATTRIBUTES.XFRM, CR_XSAVE_PAGE_n);
IF (XRSTOR failed with #GP)
THEN
DS:RBX.STATE ← INACTIVE;
#GP(0);
FI;
CR_ENCLAVE_MODE ← 1;
CR_ACTIVE_SECS ← TMP_SECS;
CR_ELRANGE←(TMP_SECS.BASEADDR, TMP_SECS.SIZE);
(* Save sate for possible AEXs *)
CR_TCS_PA←Physical_Address (DS:RBX);
CR_TCS_LA ← RBX;
CR_TCS_LA.AEP ← RCX;
(* Save the hidden portions of FS and GS *)
CR_SAVE_FS_selector ← FS.selector;
CR_SAVE_FS_base ← FS.base;
CR_SAVE_FS_limit ← FS.limit;
CR_SAVE_FS_access_rights ← FS.access_rights;
CR_SAVE_GS_selector ← GS.selector;
CR_SAVE_GS_base ← GS.base;
CR_SAVE_GS_limit ← GS.limit;
CR_SAVE_GS_access_rights ← GS.access_rights;
RIP ← TMP_TARGET;
Restore_GPRs from DS:TMP_GPR;
(*Restore the RFLAGS values from SSA*)
RFLAGS.CF ← DS:TMP_GPR.RFLAGS.CF;
RFLAGS.PF ← DS:TMP_GPR.RFLAGS.PF;
RFLAGS.AF ← DS:TMP_GPR.RFLAGS.AF;
RFLAGS.ZF ← DS:TMP_GPR.RFLAGS.ZF;
RFLAGS.SF ← DS:TMP_GPR.RFLAGS.SF;
RFLAGS.DF ← DS:TMP_GPR.RFLAGS.DF;
RFLAGS.OF ← DS:TMP_GPR.RFLAGS.OF;
RFLAGS.NT ← DS:TMP_GPR.RFLAGS.NT;
RFLAGS.AC ← DS:TMP_GPR.RFLAGS.AC;
RFLAGS.ID ← DS:TMP_GPR.RFLAGS.ID;
RFLAGS.RF ← DS:TMP_GPR.RFLAGS.RF;
RFLAGS.VM ← 0;
IF (RFLAGS.IOPL = 3)
THEN RFLAGS.IF←DS:TMP_GPR.RFLAGS.IF; FI;
IF (TCS.FLAGS.OPTIN = 0)
THEN RFLAGS.TF←0; FI;
(* If XSAVE is enabled, save XCR0 and replace it with SECS.ATTRIBUTES.XFRM*)
IF (CR4.OSXSAVE = 1)
CR_SAVE_XCR0 ← XCR0;
XCR0 ← TMP_SECS.ATTRIBUTES.XFRM;
FI;
(* Pop the SSA stack*)
(DS:RBX).CSSA←(DS:RBX).CSSA -1;
(* Do the FS/GS swap *)
FS.base ← TMP_FSBASE;
FS.limit ← DS:RBX.FSLIMIT;
FS.type ← 0001b;
FS.W ← DS.W;
FS.S ← 1;
FS.DPL ← DS.DPL;
FS.G ← 1;
FS.B ← 1;
FS.P ← 1;
FS.AVL ← DS.AVL;
FS.L ← DS.L;
FS.unusable ← 0;
FS.selector ← 0BH;
GS.base ← TMP_GSBASE;
GS.limit ← DS:RBX.GSLIMIT;
GS.type ← 0001b;
GS.W ← DS.W;
GS.S ← 1;
GS.DPL ← DS.DPL;
GS.G ← 1;
GS.B ← 1;
GS.P ← 1;
GS.AVL ← DS.AVL;
GS.L ← DS.L;
GS.unusable ← 0;
GS.selector ← 0BH;
CR_DBGOPTIN ← TCS.FLAGS.DBGOPTIN;
Suppress all code breakpoints that are outside ELRANGE;
IF (CR_DBGOPTIN = 0)
THEN
Suppress all code breakpoints that overlap with ELRANGE;
CR_SAVE_TF ← RFLAGS.TF;
RFLAGS.TF ← 0;
Suppress any MTF VM exits during execution of the enclave;
Clear all pending debug exceptions;
Clear any pending MTF VM exit;
ELSE
Clear all pending debug exceptions;
Clear pending MTF VM exits;
FI;
(* Assure consistent translations *)
Flush_linear_context;
Clear_Monitor_FSM;
Allow_front_end_to_begin_fetch_at_new_RIP;
RFLAGS.TF is cleared on opt-out entry
#GP(0) | If DS:RBX is not page aligned. |
If the enclave is not initialized. | |
If the thread is not in the INACTIVE state. | |
If CS, DS, ES or SS bases are not all zero. | |
If executed in enclave mode. | |
If part or all of the FS or GS segment specified by TCS is outside the DS segment. | |
If any reserved field in the TCS FLAG is set. | |
If the target address is not within the CS segment. | |
If CR4.OSFXSR = 0. | |
If CR4.OSXSAVE = 0 and SECS.ATTRIBUTES.XFRM ≠ 3. | |
If CR4.OSXSAVE = 1and SECS.ATTRIBUTES.XFRM is not a subset of XCR0. | |
#PF(error | code) If a page fault occurs in accessing memory. |
If DS:RBX does not point to a valid TCS. | |
If one or more pages of the current SSA frame are not readable/writable, or do not resolve to a valid PT_REG EPC page. |
#GP(0) | If DS:RBX is not page aligned. |
If the enclave is not initialized. | |
If the thread is not in the INACTIVE state. | |
If CS, DS, ES or SS bases are not all zero. | |
If executed in enclave mode. | |
If part or all of the FS or GS segment specified by TCS is outside the DS segment. | |
If any reserved field in the TCS FLAG is set. | |
If the target address is not canonical. | |
If CR4.OSFXSR = 0. | |
If CR4.OSXSAVE = 0 and SECS.ATTRIBUTES.XFRM ≠ 3. | |
If CR4.OSXSAVE = 1and SECS.ATTRIBUTES.XFRM is not a subset of XCR0. | |
#PF(error | code) If a page fault occurs in accessing memory operands. |
If DS:RBX does not point to a valid TCS. | |
If one or more pages of the current SSA frame are not readable/writable, or do not resolve to a valid PT_REG EPC page. |