ELDB/ELDU/ELDBC/ELDUC — Load an EPC Page and Mark its State

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.

Instruction Operand Encoding

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)

Description

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.

ELDB/ELDU/ELDBC/ELBUC Memory Parameter Semantics

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 37-4) Description
No Error ELDB/ELDU successful.
SGX_MAC_COMPARE_FAIL If the MAC check fails.
Table 37-28. ELDB/ELDU/ELDBC/ELBUC Return Value in RAX

Concurrency Restrictions

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
Table 37-29. Base Concurrency Restrictions of ELDB/ELDU/ELDBC/ELBUC
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
Table 37-30. Additional Concurrency Restrictions of ELDB/ELDU/ELDBC/ELBUC

Operation

Temp Variables in ELDB/ELDU/ELDBC/ELBUC Operational Flow

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 *)

#GP(0);

FI;

ELSE (* ELDBC/ELDUC *)

RFLAGS.ZF := 1;

RFLAGS.CF := 0;

RAX := SGX_EPC_PAGE_CONFLICT;

GOTO ERROR_EXIT;

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 ( Other instructions modifying SECS)

THEN

IF ((EAX==07h) OR (EAX==08h)) (* ELDB/ELDU *)

#GP(0);

FI;

ELSE (* ELDBC/ELDUC *)

RFLAGS.ZF := 1;

RFLAGS.CF := 0;

RAX := SGX_EPC_PAGE_CONFLICT;

GOTO ERROR_EXIT;

FI;

FI;

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

TMP_HEADER.EID := DS:TMP_SECS.EID;

ELSE

(* These pages do not have any parent, and hence no EID binding *)

TMP_HEADER.EID := 0;

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;

(* Check version before committing *)

IF (DS:RDX ≠ 0)

THEN #GP(0);

ELSE

DS:RDX := TMP_VER;

FI;

(* 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;

Flags Affected

Sets ZF if unsuccessful, otherwise cleared and RAX returns error code. Clears CF, PF, AF, OF, SF.

Protected Mode Exceptions

#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.

64-Bit Mode Exceptions

#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.