EADD — Add a Page to an Uninitialized Enclave

Opcode/Instruction Op/En 64/32 bit Mode Support CPUID Feature Flag Description
EAX = 01H ENCLS[EADD] IR V/V SGX1 This leaf function adds a page to an uninitialized enclave.

Instruction Operand Encoding

Op/En EAX RBX RCX
IR EADD (In) Address of a PAGEINFO (In) Address of the destination EPC page (In)

Description

This leaf function copies a source page from non-enclave memory into the EPC, associates the EPC page with an SECS page residing in the EPC, and stores the linear address and security attributes in EPCM. As part of the association, the enclave offset and the security attributes are measured and extended into the SECS.MRENCLAVE. This instruction can only be executed when current privilege level is 0.

RBX contains the effective address of a PAGEINFO structure while RCX contains the effective address of an EPC page. The table below provides additional information on the memory parameter of EADD leaf function.

EADD Memory Parameter Semantics

PAGEINFO PAGEINFO.SECS PAGEINFO.SRCPGE PAGEINFO.SECINFO EPCPAGE
Read access permitted by Non Enclave Read/Write access permitted by Enclave Read access permitted by Non Enclave Read access permitted by Non Enclave Write access permitted by Enclave

The instruction faults if any of the following:

EADD Faulting Conditions

The operands are not properly aligned. Unsupported security attributes are set.
Refers to an invalid SECS. Reference is made to an SECS that is locked by another thread.
The EPC page is locked by another thread. RCX does not contain an effective address of an EPC page.
The EPC page is already valid. If security attributes specifies a TCS and the source page specifies unsupported TCS values or fields.
The SECS has been initialized. The specified enclave offset is outside of the enclave address space.

Concurrency Restrictions

Leaf Parameter Base Concurrency Restrictions
Access On Conflict SGX_CONFLICT VM Exit Qualification
EADD Target [DS:RCX] Exclusive #GP EPC_PAGE_CONFLICT_EXCEPTION
SECS [DS:RBX]PAGEINFO.SECS Shared #GP
Table 38-8. Base Concurrency Restrictions of EADD
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
EADD Target [DS:RCX] Concurrent Concurrent Concurrent
SECS [DS:RBX]PAGEINFO.SECS Concurrent Exclusive #GP Concurrent
Table 38-9. Additional Concurrency Restrictions of EADD

Operation

Temp Variables in EADD Operational Flow

Name Type Size (bits) Description
TMP_SRCPGE Effective Address 32/64 Effective address of the source page.
TMP_SECS Effective Address 32/64 Effective address of the SECS destination page.
TMP_SECINFO Effective Address 32/64 Effective address of an SECINFO structure which contains security attributes of the page to be added.
SCRATCH_SECINFO SECINFO 512 Scratch storage for holding the contents of DS:TMP_SECINFO.
TMP_LINADDR Unsigned Integer 64 Holds the linear address to be stored in the EPCM and used to calculate TMP_ENCLAVEOFFSET.
TMP_ENCLAVEOFFSET Enclave Offset 64 The page displacement from the enclave base address.
TMPUPDATEFIELD SHA256 Buffer 512 Buffer used to hold data being added to TMP_SECS.MRENCLAVE.

IF (DS:RBX is not 32Byte Aligned)

THEN #GP(0); FI;

IF (DS:RCX is not 4KByte Aligned)

THEN #GP(0); FI;

IF (DS:RCX does not resolve within an EPC)

THEN #PF(DS:RCX); FI;

TMP_SRCPGE := DS:RBX.SRCPGE;

TMP_SECS := DS:RBX.SECS;

TMP_SECINFO := DS:RBX.SECINFO;

TMP_LINADDR := DS:RBX.LINADDR;

IF (DS:TMP_SRCPGE is not 4KByte aligned or DS:TMP_SECS is not 4KByte aligned or

DS:TMP_SECINFO is not 64Byte aligned or TMP_LINADDR is not 4KByte aligned)

THEN #GP(0); FI;

IF (DS:TMP_SECS does not resolve within an EPC)

THEN #PF(DS:TMP_SECS); FI;

SCRATCH_SECINFO := DS:TMP_SECINFO;

(* Check for misconfigured SECINFO flags*)

IF (SCRATCH_SECINFO reserved fields are not zero or

! (SCRATCH_SECINFO.FLAGS.PT is PT_REG or SCRATCH_SECINFO.FLAGS.PT is PT_TCS or

(SCRATCH_SECINFO.FLAGS.PT is PT_SS_FIRST and CPUID.(EAX=12H, ECX=1):EAX[6] = 1) or

(SCRATCH_SECINFO.FLAGS.PT is PT_SS_REST and CPUID.(EAX=12H, ECX=1):EAX[6] = 1)) )

THEN #GP(0); FI;

(* If PT_SS_FIRST/PT_SS_REST page types are requested then CR4.CET must be 1 *)

IF ( (SCRATCH_SECINFO.FLAGS.PT is PT_SS_FIRST OR

SCRATCH_SECINFO.FLAGS.PT is PT_SS_REST) AND CR4.CET == 0)

THEN #GP(0); FI;

(* Check the EPC page for concurrency *)

IF (EPC page is not available for EADD)

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;

FI;

IF (EPCM(DS:RCX).VALID ≠ 0)

THEN #PF(DS:RCX); FI;

(* Check the SECS for concurrency *)

IF (SECS is not available for EADD)

THEN #GP(0); FI;

IF (EPCM(DS:TMP_SECS).VALID = 0 or EPCM(DS:TMP_SECS).PT ≠ PT_SECS)

THEN #PF(DS:TMP_SECS); FI;

(* Copy 4KBytes from source page to EPC page*)

DS:RCX[32767:0] := DS:TMP_SRCPGE[32767:0];

CASE (SCRATCH_SECINFO.FLAGS.PT)

PT_TCS:

IF (DS:RCX.RESERVED ≠ 0) #GP(0); FI;

IF ( (DS:TMP_SECS.ATTRIBUTES.MODE64BIT = 0) and

((DS:TCS.FSLIMIT & 0FFFH ≠ 0FFFH) or (DS:TCS.GSLIMIT & 0FFFH ≠ 0FFFH) )) #GP(0); FI;

(* Ensure TCS.PREVSSP is zero *)

IF (CPUID.(EAX=07H, ECX=00h):ECX[CET_SS] = 1) and (DS:RCX.PREVSSP != 0) #GP(0); FI;

BREAK;

PT_REG:

IF (SCRATCH_SECINFO.FLAGS.W = 1 and SCRATCH_SECINFO.FLAGS.R = 0) #GP(0); FI;

BREAK;

PT_SS_FIRST:

PT_SS_REST:

(* SS pages cannot be created on first or last page of ELRANGE *)

IF ( TMP_LINADDR = DS:TMP_SECS.BASEADDR or TMP_LINADDR = (DS:TMP_SECS.BASEADDR + DS:TMP_SECS.SIZE - 0x1000) )

THEN #GP(0); FI;

IF ( DS:RCX[4087:0] != 0 ) #GP(0); FI;

IF (SCRATCH_SECINFO.FLAGS.PT == PT_SS_FIRST)

THEN

(* Check that valid RSTORSSP token exists *)

IF ( DS:RCX[4095:4088] != ((TMP_LINADDR + 0x1000) | DS:TMP_SECS.ATTRIBUTES.MODE64BIT) ) #GP(0); FI;

ELSE

(* Check the 8 bytes are zero *)

IF ( DS:RCX[4095:4088] != 0 ) #GP(0); FI;

FI;

IF (SCRATCH_SECINFO.FLAGS.W = 0 OR SCRATCH_SECINFO.FLAGS.R = 0 OR

SCRATCH_SECINFO.FLAGS.X = 1) #GP(0); FI;

BREAK;

ESAC;

(* Check the enclave offset is within the enclave linear address space *) IF (TMP_LINADDR < DS:TMP_SECS.BASEADDR or TMP_LINADDR ≥ DS:TMP_SECS.BASEADDR + DS:TMP_SECS.SIZE) THEN #GP(0); FI;

(* Check concurrency of measurement resource*)

IF (Measurement being updated)

THEN #GP(0); FI;

(* Check if the enclave to which the page will be added is already in Initialized state *)

IF (DS:TMP_SECS already initialized)

THEN #GP(0); FI;

(* For TCS pages, force EPCM.rwx bits to 0 and no debug access *)

IF (SCRATCH_SECINFO.FLAGS.PT = PT_TCS)

THEN

SCRATCH_SECINFO.FLAGS.R := 0;

SCRATCH_SECINFO.FLAGS.W := 0;

SCRATCH_SECINFO.FLAGS.X := 0;

(DS:RCX).FLAGS.DBGOPTIN := 0; // force TCS.FLAGS.DBGOPTIN off

DS:RCX.CSSA := 0;

DS:RCX.AEP := 0;

DS:RCX.STATE := 0;

FI;

(* Add enclave offset and security attributes to MRENCLAVE *)

TMP_ENCLAVEOFFSET := TMP_LINADDR - DS:TMP_SECS.BASEADDR;

TMPUPDATEFIELD[63:0] := 0000000044444145H; // “EADD”

TMPUPDATEFIELD[127:64] := TMP_ENCLAVEOFFSET;

TMPUPDATEFIELD[511:128] := SCRATCH_SECINFO[375:0]; // 48 bytes

DS:TMP_SECS.MRENCLAVE := SHA256UPDATE(DS:TMP_SECS.MRENCLAVE, TMPUPDATEFIELD)

INC enclave’s MRENCLAVE update counter;

(* Add enclave offset and security attributes to MRENCLAVE *)

EPCM(DS:RCX).R := SCRATCH_SECINFO.FLAGS.R;

EPCM(DS:RCX).W := SCRATCH_SECINFO.FLAGS.W;

EPCM(DS:RCX).X := SCRATCH_SECINFO.FLAGS.X;

EPCM(DS:RCX).PT := SCRATCH_SECINFO.FLAGS.PT;

EPCM(DS:RCX).ENCLAVEADDRESS := TMP_LINADDR;

(* associate the EPCPAGE with the SECS by storing the SECS identifier of DS:TMP_SECS *)

Update EPCM(DS:RCX) SECS identifier to reference DS:TMP_SECS identifier;

(* Set EPCM entry fields *)

EPCM(DS:RCX).BLOCKED := 0;

EPCM(DS:RCX).PENDING := 0;

EPCM(DS:RCX).MODIFIED := 0;

EPCM(DS:RCX).VALID := 1;

Flags Affected

None

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 an enclave memory operand is outside of the EPC.
If an enclave memory operand is the wrong type.
If a memory operand is locked.
If the enclave is initialized.
If the enclave's MRENCLAVE is locked.
If the TCS page reserved bits are set.
If the TCS page PREVSSP field is not zero.
If the PT_SS_REST or PT_SS_REST page is the first or last page in the enclave.
If the PT_SS_FIRST or PT_SS_REST page is not initialized correctly.
#PF(error code) If a page fault occurs in accessing memory operands.
If the EPC page is valid.

64-Bit Mode Exceptions

#GP(0) If a memory operand is non-canonical form.
If a memory operand is not properly aligned.
If an enclave memory operand is outside of the EPC.
If an enclave memory operand is the wrong type.
If a memory operand is locked.
If the enclave is initialized.
If the enclave's MRENCLAVE is locked.
If the TCS page reserved bits are set.
If the TCS page PREVSSP field is not zero.
If the PT_SS_REST or PT_SS_REST page is the first or last page in the enclave.
If the PT_SS_FIRST or PT_SS_REST page is not initialized correctly.
#PF(error code) If a page fault occurs in accessing memory operands.
If the EPC page is valid.