Opcode/Instruction | Op/En | 64/32 bit Mode Support | CPUID Feature Flag | Description |
---|---|---|---|---|
EAX = 07H ENCLS[ELDB] | IR | V/V | SGX1 | This leaf function loads, verifies an EPC page and marks the page as blocked. |
EAX = 08H ENCLS[ELDU] | IR | V/V | SGX1 | This leaf function loads, verifies an EPC page and marks the page as unblocked. |
EAX = 12H ENCLS[ELDBC] | IR | V/V | EAX[6] | This leaf function behaves lie ELDB but with improved conflict handling for oversubscription. |
EAX = 13H ENCLS[ELDUC] | IR | V/V | EAX[6] | This leaf function behaves like ELDU but with improved conflict handling for oversubscription. |
Op/En | EAX | RBX | RCX | RDX | |
IR | (In) r (In) LDU Return error Return error | Address of the PAGEINFO (In) | Address of the EPC page (In) | Address of the version-array slot (In) |
This leaf function copies a page from regular main memory to the EPC. As part of the copying process, the page is cryptographically authenticated and decrypted. This instruction can only be executed when current privilege level is 0.
The ELDB leaf function sets the BLOCK bit in the EPCM entry for the destination page in the EPC after copying. The ELDU leaf function clears the BLOCK bit in the EPCM entry for the destination page in the EPC after copying.
RBX contains the effective address of a PAGEINFO structure; RCX contains the effective address of the destination EPC page; RDX holds the effective address of the version array slot that holds the version of the page.
The ELDBC/ELDUC leafs are very similar to ELDB and ELDU. They provide an error code on the concurrency conflict for any of the pages which need to acquire a lock. These include the destination, SECS, and VA slot.
The table below provides additional information on the memory parameter of ELDB/ELDU leaf functions.
PAGEINFO | PAGEINFO.SRCPGE | PAGEINFO.PCMD | PAGEINFO.SECS | EPCPAGE | Version-Array Slot |
Non-enclave read access | Non-enclave read access | Non-enclave read access | Enclave read/write access | Read/Write access permitted by Enclave | Read/Write access permitted by Enclave |
The error codes are:
Error Code (see Table 38-4) | Description |
---|---|
No Error | ELDB/ELDU successful. |
SGX_MAC_COMPARE_FAIL | If the MAC check fails. |
Leaf | Parameter | Base Concurrency Restrictions | ||
---|---|---|---|---|
Access | On Conflict | SGX_CONFLICT VM Exit Qualification | ||
ELDB/ELDU | Target [DS:RCX] | Exclusive | #GP | EPC_PAGE_CONFLICT_EXCEPTION |
VA [DS:RDX] | Shared | #GP | ||
SECS [DS:RBX]PAGEINFO.SECS | Shared | #GP | ||
ELDBC/ELBUC | Target [DS:RCX] | Exclusive | SGX_EPC_PAGE_ CONFLICT | EPC_PAGE_CONFLICT_ERROR |
VA [DS:RDX] | Shared | SGX_EPC_PAGE_ CONFLICT | ||
SECS [DS:RBX]PAGEINFO.SECS | Shared | SGX_EPC_PAGE_ CONFLICT |
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 | ||
ELDB/ELDU | Target [DS:RCX] | Concurrent | Concurrent | Concurrent | |||
VA [DS:RDX] | Concurrent | Concurrent | Concurrent | ||||
SECS [DS:RBX]PAGEINFO.SECS | Concurrent | Concurrent | Concurrent | ||||
ELDBC/ELBUC | Target [DS:RCX] | Concurrent | Concurrent | Concurrent | |||
VA [DS:RDX] | Concurrent | Concurrent | Concurrent | ||||
SECS [DS:RBX]PAGEINFO.SECS | Concurrent | Concurrent | Concurrent |
Name | Type | Size (Bits) | Description |
---|---|---|---|
TMP_SRCPGE | Memory page | 4KBytes | |
TMP_SECS | Memory page | 4KBytes | |
TMP_PCMD | PCMD | 128 Bytes | |
TMP_HEADER | MACHEADER | 128 Bytes | |
TMP_VER | UINT64 | 64 | |
TMP_MAC | UINT128 | 128 | |
TMP_PK | UINT128 | 128 | Page encryption/MAC key. |
SCRATCH_PCMD | PCMD | 128 Bytes |
(* Check PAGEINFO and EPCPAGE alignment *)
IF ( (DS:RBX is not 32Byte Aligned) or (DS:RCX is not 4KByte Aligned) )
THEN #GP(0); FI;
IF (DS:RCX does not resolve within an EPC)
THEN #PF(DS:RCX); FI;
(* Check VASLOT alignment *)
IF (DS:RDX is not 8Byte aligned)
THEN #GP(0); FI;
IF (DS:RDX does not resolve within an EPC)
THEN #PF(DS:RDX); FI;
TMP_SRCPGE := DS:RBX.SRCPGE;
TMP_SECS := DS:RBX.SECS;
TMP_PCMD := DS:RBX.PCMD;
(* Check alignment of PAGEINFO (RBX) linked parameters. Note: PCMD pointer is overlaid on top of PAGEINFO.SECINFO field *)
IF ( (DS:TMP_PCMD is not 128Byte aligned) or (DS:TMP_SRCPGE is not 4KByte aligned) )
THEN #GP(0); FI;
(* Check concurrency of EPC by other Intel SGX instructions *)
IF (other instructions accessing EPC)
THEN
IF ((EAX==07h) OR (EAX==08h)) (* ELDB/ELDU *)
THEN
IF (<<VMX non-root operation>> AND
<<ENABLE_EPC_VIRTUALIZATION_EXTENSIONS>>)
THEN
VMCS.Exit_reason := SGX_CONFLICT;
VMCS.Exit_qualification.code := EPC_PAGE_CONFLICT_EXCEPTION;
VMCS.Exit_qualification.error := 0;
VMCS.Guest-physical_address :=
<< translation of DS:RCX produced by paging >>;
VMCS.Guest-linear_address := DS:RCX;
Deliver VMEXIT;
ELSE
#GP(0);
FI;
ELSE (* ELDBC/ELDUC *)
IF (<<VMX non-root operation>> AND
<<ENABLE_EPC_VIRTUALIZATION_EXTENSIONS>>)
THEN
VMCS.Exit_reason := SGX_CONFLICT;
VMCS.Exit_qualification.code := EPC_PAGE_CONFLICT_ERROR;
VMCS.Exit_qualification.error := SGX_EPC_PAGE_CONFLICT;
VMCS.Guest-physical_address :=
<< translation of DS:RCX produced by paging >>;
VMCS.Guest-linear_address := DS:RCX;
Deliver VMEXIT;
ELSE
RFLAGS.ZF := 1;
RFLAGS.CF := 0;
RAX := SGX_EPC_PAGE_CONFLICT;
GOTO ERROR_EXIT;
FI;
FI;
FI;
(* Check concurrency of EPC and VASLOT by other Intel SGX instructions *)
IF (Other instructions modifying VA slot) THEN
IF ((EAX==07h) OR (EAX==08h)) (* ELDB/ELDU *)
THEN #GP(0);
ELSE (* ELDBC/ELDUC *)
RFLAGS.ZF := 1;
RFLAGS.CF := 0;
RAX := SGX_EPC_PAGE_CONFLICT;
GOTO ERROR_EXIT;
FI;
FI;
(* Verify EPCM attributes of EPC page, VA, and SECS *)
IF (EPCM(DS:RCX).VALID = 1)
THEN #PF(DS:RCX); FI;
IF ( (EPCM(DS:RDX & ~0FFFH).VALID = 0) or (EPCM(DS:RDX & ~0FFFH).PT ≠ PT_VA) )
THEN #PF(DS:RDX); FI;
(* Copy PCMD into scratch buffer *)
SCRATCH_PCMD[1023: 0] := DS:TMP_PCMD[1023:0];
(* Zero out TMP_HEADER*)
TMP_HEADER[sizeof(TMP_HEADER)-1: 0] := 0;
TMP_HEADER.SECINFO := SCRATCH_PCMD.SECINFO;
TMP_HEADER.RSVD := SCRATCH_PCMD.RSVD;
TMP_HEADER.LINADDR := DS:RBX.LINADDR;
(* Verify various attributes of SECS parameter *)
IF ( (TMP_HEADER.SECINFO.FLAGS.PT = PT_REG) or (TMP_HEADER.SECINFO.FLAGS.PT = PT_TCS) or
(TMP_HEADER.SECINFO.FLAGS.PT = PT_TRIM) or
(TMP_HEADER.SECINFO.FLAGS.PT = PT_SS_FIRST and CPUID.(EAX=12H, ECX=1):EAX[6] = 1) or
(TMP_HEADER.SECINFO.FLAGS.PT = PT_SS_REST and CPUID.(EAX=12H, ECX=1):EAX[6] = 1))
THEN
IF ( DS:TMP_SECS is not 4KByte aligned)
THEN #GP(0) FI;
IF (DS:TMP_SECS does not resolve within an EPC)
THEN #PF(DS:TMP_SECS) FI;
IF ( Another instruction is currently modifying the SECS) THEN
IF ((EAX==07h) OR (EAX==08h)) (* ELDB/ELDU *)
THEN #GP(0);
ELSE (* ELDBC/ELDUC *)
RFLAGS.ZF := 1;
RFLAGS.CF := 0;
RAX := SGX_EPC_PAGE_CONFLICT;
GOTO ERROR_EXIT;
FI;
FI;
TMP_HEADER.EID := DS:TMP_SECS.EID;
ELSE
(* TMP_HEADER.SECINFO.FLAGS.PT is PT_SECS or PT_VA which do not have a parent SECS, and hence no EID binding *)
TMP_HEADER.EID := 0;
IF (DS:TMP_SECS ≠ 0)
THEN #GP(0) FI;
FI;
(* Copy 4KBytes SRCPGE to secure location *)
DS:RCX[32767: 0] := DS:TMP_SRCPGE[32767: 0];
TMP_VER := DS:RDX[63:0];
(* Decrypt and MAC page. AES_GCM_DEC has 2 outputs, {plain text, MAC} *)
(* Parameters for AES_GCM_DEC {Key, Counter, ..} *)
{DS:RCX, TMP_MAC} := AES_GCM_DEC(CR_BASE_PK, TMP_VER << 32, TMP_HEADER, 128, DS:RCX, 4096);
IF ( (TMP_MAC ≠ DS:TMP_PCMD.MAC) )
THEN
RFLAGS.ZF := 1;
RAX := SGX_MAC_COMPARE_FAIL;
GOTO ERROR_EXIT;
FI;
(* Clear VA Slot *)
DS:RDX := 0
(* Commit EPCM changes *)
EPCM(DS:RCX).PT := TMP_HEADER.SECINFO.FLAGS.PT;
EPCM(DS:RCX).RWX := TMP_HEADER.SECINFO.FLAGS.RWX;
EPCM(DS:RCX).PENDING := TMP_HEADER.SECINFO.FLAGS.PENDING;
EPCM(DS:RCX).MODIFIED := TMP_HEADER.SECINFO.FLAGS.MODIFIED;
EPCM(DS:RCX).PR := TMP_HEADER.SECINFO.FLAGS.PR;
EPCM(DS:RCX).ENCLAVEADDRESS := TMP_HEADER.LINADDR;
IF ( ((EAX = 07H) or (EAX = 12H)) and (TMP_HEADER.SECINFO.FLAGS.PT is NOT PT_SECS or PT_VA))
THEN
EPCM(DS:RCX).BLOCKED := 1;
ELSE
EPCM(DS:RCX).BLOCKED := 0;
FI;
IF (TMP_HEADER.SECINFO.FLAGS.PT is PT_SECS)
<< store translation of DS:RCX produced by paging in SECS(DS:RCX).ENCLAVECONTEXT >>
FI;
EPCM(DS:RCX). VALID := 1;
RAX := 0;
RFLAGS.ZF := 0;
ERROR_EXIT:
RFLAGS.CF,PF,AF,OF,SF := 0;
Sets ZF if unsuccessful, otherwise cleared and RAX returns error code. Clears CF, PF, AF, OF, SF.
#GP(0) | If a memory operand effective address is outside the DS segment limit. |
If a memory operand is not properly aligned. | |
If the instruction’s EPC resource is in use by others. | |
If the instruction fails to verify MAC. | |
If the version-array slot is in use. | |
If the parameters fail consistency checks. | |
#PF(error | code) If a page fault occurs in accessing memory operands. |
If a memory operand expected to be in EPC does not resolve to an EPC page. | |
If one of the EPC memory operands has incorrect page type. | |
If the destination EPC page is already valid. |
#GP(0) | If a memory operand is non-canonical form. |
If a memory operand is not properly aligned. | |
If the instruction’s EPC resource is in use by others. | |
If the instruction fails to verify MAC. | |
If the version-array slot is in use. | |
If the parameters fail consistency checks. | |
#PF(error | code) If a page fault occurs in accessing memory operands. |
If a memory operand expected to be in EPC does not resolve to an EPC page. | |
If one of the EPC memory operands has incorrect page type. | |
If the destination EPC page is already valid. |