diff mbox series

[v22,06/24] x86/sgx: Add SGX microarchitectural data structures

Message ID 20190903142655.21943-7-jarkko.sakkinen@linux.intel.com (mailing list archive)
State New, archived
Headers show
Series Intel SGX foundations | expand

Commit Message

Jarkko Sakkinen Sept. 3, 2019, 2:26 p.m. UTC
Define the SGX microarchitectural data structures used by various SGX
opcodes. This is not an exhaustive representation of all SGX data
structures but only those needed by the kernel.

[1] Intel SDM: 37.6 INTEL® SGX DATA STRUCTURES OVERVIEW

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
---
 arch/x86/kernel/cpu/sgx/arch.h | 423 +++++++++++++++++++++++++++++++++
 1 file changed, 423 insertions(+)
 create mode 100644 arch/x86/kernel/cpu/sgx/arch.h

Comments

Borislav Petkov Sept. 27, 2019, 4:27 p.m. UTC | #1
On Tue, Sep 03, 2019 at 05:26:37PM +0300, Jarkko Sakkinen wrote:
> Define the SGX microarchitectural data structures used by various SGX
> opcodes. This is not an exhaustive representation of all SGX data
> structures but only those needed by the kernel.
> 
> [1] Intel SDM: 37.6 INTEL® SGX DATA STRUCTURES OVERVIEW

That footnote is not being referred to. Just make it a sentence.

Btw, you could tell your SDM folks to fix formulations like:

"The use of EAX is implied implicitly by the ENCLS, ENCLU, and ENCLV
		   ^^^^^^^^^^^^^^^^^^^

instructions.... The use of additional registers does not use ModR/M
encoding and is implied implicitly by the respective leaf function
		^^^^^^^^^^^^^^^^^^^

index."

"implied" alone wasn't enough I guess. :)

> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
> Co-developed-by: Sean Christopherson <sean.j.christopherson@intel.com>
> Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
> ---
>  arch/x86/kernel/cpu/sgx/arch.h | 423 +++++++++++++++++++++++++++++++++
>  1 file changed, 423 insertions(+)
>  create mode 100644 arch/x86/kernel/cpu/sgx/arch.h
> 
> diff --git a/arch/x86/kernel/cpu/sgx/arch.h b/arch/x86/kernel/cpu/sgx/arch.h
> new file mode 100644
> index 000000000000..725a47f9f761
> --- /dev/null
> +++ b/arch/x86/kernel/cpu/sgx/arch.h
> @@ -0,0 +1,423 @@
> +/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
> +/**
> + * Copyright(c) 2016-18 Intel Corporation.
> + *
> + * Contains data structures defined by the SGX architecture.  Data structures
> + * defined by the Linux software stack should not be placed here.
> + */
> +#ifndef _ASM_X86_SGX_ARCH_H
> +#define _ASM_X86_SGX_ARCH_H
> +
> +#include <linux/types.h>
> +
> +#define SGX_CPUID				0x12
> +#define SGX_CPUID_FIRST_VARIABLE_SUB_LEAF	2
> +
> +/**
> + * enum sgx_sub_leaf_types - SGX CPUID variable sub-leaf types
> + * %SGX_CPUID_SUB_LEAF_INVALID:		Indicates this sub-leaf is invalid.
> + * %SGX_CPUID_SUB_LEAF_EPC_SECTION:	Sub-leaf enumerates an EPC section.
> + */
> +enum sgx_sub_leaf_types {
> +	SGX_CPUID_SUB_LEAF_INVALID	= 0x0,
> +	SGX_CPUID_SUB_LEAF_EPC_SECTION	= 0x1,
> +};
> +
> +#define SGX_CPUID_SUB_LEAF_TYPE_MASK	GENMASK(3, 0)
> +
> +/**
> + * enum sgx_encls_leaves - ENCLS leaf functions
> + * %SGX_ECREATE:	Create an enclave.
> + * %SGX_EADD:		Add a page to an uninitialized enclave.
> + * %SGX_EINIT:		Initialize an enclave, i.e. launch an enclave.
> + * %SGX_EREMOVE:	Remove a page from an enclave.
> + * %SGX_EDBGRD:		Read a word from an enclve (peek).
> + * %SGX_EDBGWR:		Write a word to an enclave (poke).
> + * %SGX_EEXTEND:	Measure 256 bytes of an added enclave page.
> + * %SGX_ELDB:		Load a swapped page in blocked state.
> + * %SGX_ELDU:		Load a swapped page in unblocked state.
> + * %SGX_EBLOCK:		Change page state to blocked i.e. entering hardware
> + *			threads cannot access it and create new TLB entries.
> + * %SGX_EPA:		Create a Version Array (VA) page used to store isvsvn
> + *			number for a swapped EPC page.
> + * %SGX_EWB:		Swap an enclave page to the regular memory. Checks that
> + *			all threads have exited that were in the previous
> + *			shoot-down sequence.
> + * %SGX_ETRACK:		Start a new shoot down sequence. Used to together with
> + *			EBLOCK to make sure that a page is safe to swap.
> + * %SGX_EAUG:		Add a page to an initialized enclave.
> + * %SGX_EMODPR:		Restrict an EPC page's permissions.
> + * %SGX_EMODT:		Modify the page type of an EPC page.
> + */
> +enum sgx_encls_leaves {
> +	SGX_ECREATE	= 0x00,
> +	SGX_EADD	= 0x01,
> +	SGX_EINIT	= 0x02,
> +	SGX_EREMOVE	= 0x03,
> +	SGX_EDGBRD	= 0x04,
> +	SGX_EDGBWR	= 0x05,
> +	SGX_EEXTEND	= 0x06,
> +	SGX_ELDB	= 0x07,
> +	SGX_ELDU	= 0x08,
> +	SGX_EBLOCK	= 0x09,
> +	SGX_EPA		= 0x0A,
> +	SGX_EWB		= 0x0B,
> +	SGX_ETRACK	= 0x0C,
> +	SGX_EAUG	= 0x0D,
> +	SGX_EMODPR	= 0x0E,
> +	SGX_EMODT	= 0x0F,
> +};
> +
> +#define SGX_MODULUS_SIZE 384
> +
> +/**
> + * enum sgx_miscselect - additional information to an SSA frame
> + * %SGX_MISC_EXINFO:	Report #PF or #GP to the SSA frame.
> + *
> + * Save State Area (SSA) is a stack inside the enclave used to store processor
> + * state when an exception or interrupt occurs. This enum defines additional
> + * information stored to an SSA frame.
> + */
> +enum sgx_miscselect {
> +	SGX_MISC_EXINFO		= BIT(0),
> +};
> +
> +#define SGX_MISC_RESERVED_MASK	GENMASK_ULL(63, 1)
> +
> +#define SGX_SSA_GPRS_SIZE		182
> +#define SGX_SSA_MISC_EXINFO_SIZE	16
> +
> +/**
> + * enum sgx_attributes - the attributes field in &struct sgx_secs
> + * %SGX_ATTR_INIT:		Enclave can be entered (is initialized).
> + * %SGX_ATTR_DEBUG:		Allow ENCLS(EDBGRD) and ENCLS(EDBGWR).
> + * %SGX_ATTR_MODE64BIT:		Tell that this a 64-bit enclave.
> + * %SGX_ATTR_PROVISIONKEY:      Allow to use provisioning keys for remote
> + *				attestation.
> + * %SGX_ATTR_KSS:		Allow to use key separation and sharing (KSS).
> + * %SGX_ATTR_EINITTOKENKEY:	Allow to use token signing key that is used to
> + *				sign cryptographic tokens that can be passed to
> + *				EINIT as an authorization to run an enclave.
> + */
> +enum sgx_attribute {
> +	SGX_ATTR_INIT		= BIT(0),
> +	SGX_ATTR_DEBUG		= BIT(1),
> +	SGX_ATTR_MODE64BIT	= BIT(2),
> +	SGX_ATTR_PROVISIONKEY	= BIT(4),
> +	SGX_ATTR_EINITTOKENKEY	= BIT(5),
> +	SGX_ATTR_KSS		= BIT(7),
> +};
> +
> +#define SGX_ATTR_RESERVED_MASK	(BIT_ULL(3) | BIT_ULL(7) | GENMASK_ULL(63, 8))

Looking how bit 7 is part of the reserved mask but you have it above
as SGX_ATTR_KSS too. Bit 6, OTOH, is not mentioned anywhere and it
very much looks like you need to have BIT_ULL(6) above as part of the
reserved mask instead of bit 7.

Hmmm?

> +#define SGX_ATTR_ALLOWED_MASK	(SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT | \
> +				 SGX_ATTR_KSS)
> +#define SGX_SECS_RESERVED1_SIZE 24
> +#define SGX_SECS_RESERVED2_SIZE 32
> +#define SGX_SECS_RESERVED3_SIZE 96
> +#define SGX_SECS_RESERVED4_SIZE 3836

I'd make those defines shorter...

> +
> +/**
> + * struct sgx_secs - SGX Enclave Control Structure (SECS)
> + * @size:		size of the address space
> + * @base:		base address of the  address space
> + * @ssa_frame_size:	size of an SSA frame
> + * @miscselect:		additional information stored to an SSA frame
> + * @attributes:		attributes for enclave
> + * @xfrm:		XSave-Feature Request Mask (subset of XCR0)
> + * @mrenclave:		SHA256-hash of the enclave contents
> + * @mrsigner:		SHA256-hash of the public key used to sign the SIGSTRUCT
> + * @isvprodid:		a user-defined value that is used in key derivation
> + * @isvsvn:		a user-defined value that is used in key derivation
> + *
> + * SGX Enclave Control Structure (SECS) is a special enclave page that is not
> + * visible in the address space. In fact, this structure defines the address
> + * range and other global attributes for the enclave and it is the first EPC
> + * page created for any enclave. It is moved from a temporary buffer to an EPC
> + * by the means of ENCLS(ECREATE) leaf.
> + */
> +struct sgx_secs {
> +	u64 size;
> +	u64 base;
> +	u32 ssa_frame_size;
> +	u32 miscselect;
> +	u8  reserved1[SGX_SECS_RESERVED1_SIZE];
> +	u64 attributes;
> +	u64 xfrm;
> +	u32 mrenclave[8];
> +	u8  reserved2[SGX_SECS_RESERVED2_SIZE];
> +	u32 mrsigner[8];
> +	u8  reserved3[SGX_SECS_RESERVED3_SIZE];
> +	u16 isvprodid;
> +	u16 isvsvn;
> +	u8  reserved4[SGX_SECS_RESERVED4_SIZE];

... so that they don't stick too much here.

...
Jarkko Sakkinen Oct. 1, 2019, 7:10 p.m. UTC | #2
On Fri, Sep 27, 2019 at 06:27:35PM +0200, Borislav Petkov wrote:
> On Tue, Sep 03, 2019 at 05:26:37PM +0300, Jarkko Sakkinen wrote:
> > Define the SGX microarchitectural data structures used by various SGX
> > opcodes. This is not an exhaustive representation of all SGX data
> > structures but only those needed by the kernel.
> > 
> > [1] Intel SDM: 37.6 INTEL® SGX DATA STRUCTURES OVERVIEW
> 
> That footnote is not being referred to. Just make it a sentence.

Sure!

> Btw, you could tell your SDM folks to fix formulations like:
> 
> "The use of EAX is implied implicitly by the ENCLS, ENCLU, and ENCLV
> 		   ^^^^^^^^^^^^^^^^^^^
> 
> instructions.... The use of additional registers does not use ModR/M
> encoding and is implied implicitly by the respective leaf function
> 		^^^^^^^^^^^^^^^^^^^
> 
> index."
> 
> "implied" alone wasn't enough I guess. :)

I'd guess have make it a double :-)

/Jarkko
Jarkko Sakkinen Oct. 1, 2019, 8:39 p.m. UTC | #3
On Fri, Sep 27, 2019 at 06:27:35PM +0200, Borislav Petkov wrote:
> > +#define SGX_ATTR_RESERVED_MASK	(BIT_ULL(3) | BIT_ULL(7) | GENMASK_ULL(63, 8))
> 
> Looking how bit 7 is part of the reserved mask but you have it above
> as SGX_ATTR_KSS too. Bit 6, OTOH, is not mentioned anywhere and it
> very much looks like you need to have BIT_ULL(6) above as part of the
> reserved mask instead of bit 7.
> 
> Hmmm?

Correct. This a regression. The reserved bit really should be 6 as
stated in:

  Table 37-3.  Layout of ATTRIBUTES Structure

Thank you.

/Jarkko
diff mbox series

Patch

diff --git a/arch/x86/kernel/cpu/sgx/arch.h b/arch/x86/kernel/cpu/sgx/arch.h
new file mode 100644
index 000000000000..725a47f9f761
--- /dev/null
+++ b/arch/x86/kernel/cpu/sgx/arch.h
@@ -0,0 +1,423 @@ 
+/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
+/**
+ * Copyright(c) 2016-18 Intel Corporation.
+ *
+ * Contains data structures defined by the SGX architecture.  Data structures
+ * defined by the Linux software stack should not be placed here.
+ */
+#ifndef _ASM_X86_SGX_ARCH_H
+#define _ASM_X86_SGX_ARCH_H
+
+#include <linux/types.h>
+
+#define SGX_CPUID				0x12
+#define SGX_CPUID_FIRST_VARIABLE_SUB_LEAF	2
+
+/**
+ * enum sgx_sub_leaf_types - SGX CPUID variable sub-leaf types
+ * %SGX_CPUID_SUB_LEAF_INVALID:		Indicates this sub-leaf is invalid.
+ * %SGX_CPUID_SUB_LEAF_EPC_SECTION:	Sub-leaf enumerates an EPC section.
+ */
+enum sgx_sub_leaf_types {
+	SGX_CPUID_SUB_LEAF_INVALID	= 0x0,
+	SGX_CPUID_SUB_LEAF_EPC_SECTION	= 0x1,
+};
+
+#define SGX_CPUID_SUB_LEAF_TYPE_MASK	GENMASK(3, 0)
+
+/**
+ * enum sgx_encls_leaves - ENCLS leaf functions
+ * %SGX_ECREATE:	Create an enclave.
+ * %SGX_EADD:		Add a page to an uninitialized enclave.
+ * %SGX_EINIT:		Initialize an enclave, i.e. launch an enclave.
+ * %SGX_EREMOVE:	Remove a page from an enclave.
+ * %SGX_EDBGRD:		Read a word from an enclve (peek).
+ * %SGX_EDBGWR:		Write a word to an enclave (poke).
+ * %SGX_EEXTEND:	Measure 256 bytes of an added enclave page.
+ * %SGX_ELDB:		Load a swapped page in blocked state.
+ * %SGX_ELDU:		Load a swapped page in unblocked state.
+ * %SGX_EBLOCK:		Change page state to blocked i.e. entering hardware
+ *			threads cannot access it and create new TLB entries.
+ * %SGX_EPA:		Create a Version Array (VA) page used to store isvsvn
+ *			number for a swapped EPC page.
+ * %SGX_EWB:		Swap an enclave page to the regular memory. Checks that
+ *			all threads have exited that were in the previous
+ *			shoot-down sequence.
+ * %SGX_ETRACK:		Start a new shoot down sequence. Used to together with
+ *			EBLOCK to make sure that a page is safe to swap.
+ * %SGX_EAUG:		Add a page to an initialized enclave.
+ * %SGX_EMODPR:		Restrict an EPC page's permissions.
+ * %SGX_EMODT:		Modify the page type of an EPC page.
+ */
+enum sgx_encls_leaves {
+	SGX_ECREATE	= 0x00,
+	SGX_EADD	= 0x01,
+	SGX_EINIT	= 0x02,
+	SGX_EREMOVE	= 0x03,
+	SGX_EDGBRD	= 0x04,
+	SGX_EDGBWR	= 0x05,
+	SGX_EEXTEND	= 0x06,
+	SGX_ELDB	= 0x07,
+	SGX_ELDU	= 0x08,
+	SGX_EBLOCK	= 0x09,
+	SGX_EPA		= 0x0A,
+	SGX_EWB		= 0x0B,
+	SGX_ETRACK	= 0x0C,
+	SGX_EAUG	= 0x0D,
+	SGX_EMODPR	= 0x0E,
+	SGX_EMODT	= 0x0F,
+};
+
+#define SGX_MODULUS_SIZE 384
+
+/**
+ * enum sgx_miscselect - additional information to an SSA frame
+ * %SGX_MISC_EXINFO:	Report #PF or #GP to the SSA frame.
+ *
+ * Save State Area (SSA) is a stack inside the enclave used to store processor
+ * state when an exception or interrupt occurs. This enum defines additional
+ * information stored to an SSA frame.
+ */
+enum sgx_miscselect {
+	SGX_MISC_EXINFO		= BIT(0),
+};
+
+#define SGX_MISC_RESERVED_MASK	GENMASK_ULL(63, 1)
+
+#define SGX_SSA_GPRS_SIZE		182
+#define SGX_SSA_MISC_EXINFO_SIZE	16
+
+/**
+ * enum sgx_attributes - the attributes field in &struct sgx_secs
+ * %SGX_ATTR_INIT:		Enclave can be entered (is initialized).
+ * %SGX_ATTR_DEBUG:		Allow ENCLS(EDBGRD) and ENCLS(EDBGWR).
+ * %SGX_ATTR_MODE64BIT:		Tell that this a 64-bit enclave.
+ * %SGX_ATTR_PROVISIONKEY:      Allow to use provisioning keys for remote
+ *				attestation.
+ * %SGX_ATTR_KSS:		Allow to use key separation and sharing (KSS).
+ * %SGX_ATTR_EINITTOKENKEY:	Allow to use token signing key that is used to
+ *				sign cryptographic tokens that can be passed to
+ *				EINIT as an authorization to run an enclave.
+ */
+enum sgx_attribute {
+	SGX_ATTR_INIT		= BIT(0),
+	SGX_ATTR_DEBUG		= BIT(1),
+	SGX_ATTR_MODE64BIT	= BIT(2),
+	SGX_ATTR_PROVISIONKEY	= BIT(4),
+	SGX_ATTR_EINITTOKENKEY	= BIT(5),
+	SGX_ATTR_KSS		= BIT(7),
+};
+
+#define SGX_ATTR_RESERVED_MASK	(BIT_ULL(3) | BIT_ULL(7) | GENMASK_ULL(63, 8))
+#define SGX_ATTR_ALLOWED_MASK	(SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT | \
+				 SGX_ATTR_KSS)
+#define SGX_SECS_RESERVED1_SIZE 24
+#define SGX_SECS_RESERVED2_SIZE 32
+#define SGX_SECS_RESERVED3_SIZE 96
+#define SGX_SECS_RESERVED4_SIZE 3836
+
+/**
+ * struct sgx_secs - SGX Enclave Control Structure (SECS)
+ * @size:		size of the address space
+ * @base:		base address of the  address space
+ * @ssa_frame_size:	size of an SSA frame
+ * @miscselect:		additional information stored to an SSA frame
+ * @attributes:		attributes for enclave
+ * @xfrm:		XSave-Feature Request Mask (subset of XCR0)
+ * @mrenclave:		SHA256-hash of the enclave contents
+ * @mrsigner:		SHA256-hash of the public key used to sign the SIGSTRUCT
+ * @isvprodid:		a user-defined value that is used in key derivation
+ * @isvsvn:		a user-defined value that is used in key derivation
+ *
+ * SGX Enclave Control Structure (SECS) is a special enclave page that is not
+ * visible in the address space. In fact, this structure defines the address
+ * range and other global attributes for the enclave and it is the first EPC
+ * page created for any enclave. It is moved from a temporary buffer to an EPC
+ * by the means of ENCLS(ECREATE) leaf.
+ */
+struct sgx_secs {
+	u64 size;
+	u64 base;
+	u32 ssa_frame_size;
+	u32 miscselect;
+	u8  reserved1[SGX_SECS_RESERVED1_SIZE];
+	u64 attributes;
+	u64 xfrm;
+	u32 mrenclave[8];
+	u8  reserved2[SGX_SECS_RESERVED2_SIZE];
+	u32 mrsigner[8];
+	u8  reserved3[SGX_SECS_RESERVED3_SIZE];
+	u16 isvprodid;
+	u16 isvsvn;
+	u8  reserved4[SGX_SECS_RESERVED4_SIZE];
+} __packed;
+
+/**
+ * enum sgx_tcs_flags - execution flags for TCS
+ * %SGX_TCS_DBGOPTIN:	If enabled allows single-stepping and breakpoints
+ *			inside an enclave. It is cleared by EADD but can
+ *			be set later with EDBGWR.
+ */
+enum sgx_tcs_flags {
+	SGX_TCS_DBGOPTIN	= 0x01,
+};
+
+#define SGX_TCS_RESERVED_MASK	GENMASK_ULL(63, 1)
+#define SGX_TCS_RESERVED_SIZE	4024
+
+/**
+ * struct sgx_tcs - Thread Control Structure (TCS)
+ * @state:		used to mark an entered TCS
+ * @flags:		execution flags (cleared by EADD)
+ * @ssa_offset:		SSA stack offset relative to the enclave base
+ * @ssa_index:		the current SSA frame index (cleard by EADD)
+ * @nr_ssa_frames:	the number of frame in the SSA stack
+ * @entry_offset:	entry point offset relative to the enclave base
+ * @exit_addr:		address outside the enclave to exit on an exception or
+ *			interrupt
+ * @fs_offset:		offset relative to the enclave base to become FS
+ *			segment inside the enclave
+ * @gs_offset:		offset relative to the enclave base to become GS
+ *			segment inside the enclave
+ * @fs_limit:		size to become a new FS-limit (only 32-bit enclaves)
+ * @gs_limit:		size to become a new GS-limit (only 32-bit enclaves)
+ *
+ * Thread Control Structure (TCS) is an enclave page visible in its address
+ * space that defines an entry point inside the enclave. A thread enters inside
+ * an enclave by supplying address of TCS to ENCLU(EENTER). A TCS can be entered
+ * by only one thread at a time.
+ */
+struct sgx_tcs {
+	u64 state;
+	u64 flags;
+	u64 ssa_offset;
+	u32 ssa_index;
+	u32 nr_ssa_frames;
+	u64 entry_offset;
+	u64 exit_addr;
+	u64 fs_offset;
+	u64 gs_offset;
+	u32 fs_limit;
+	u32 gs_limit;
+	u8  reserved[SGX_TCS_RESERVED_SIZE];
+} __packed;
+
+/**
+ * struct sgx_pageinfo - an enclave page descriptor
+ * @addr:	address of the enclave page
+ * @contents:	pointer to the page contents
+ * @metadata:	pointer either to a SECINFO or PCMD instance
+ * @secs:	address of the SECS page
+ */
+struct sgx_pageinfo {
+	u64 addr;
+	u64 contents;
+	u64 metadata;
+	u64 secs;
+} __packed __aligned(32);
+
+
+/**
+ * enum sgx_page_type - bits in the SECINFO flags defining the page type
+ * %SGX_PAGE_TYPE_SECS:	a SECS page
+ * %SGX_PAGE_TYPE_TCS:	a TCS page
+ * %SGX_PAGE_TYPE_REG:	a regular page
+ * %SGX_PAGE_TYPE_VA:	a VA page
+ * %SGX_PAGE_TYPE_TRIM:	a page in trimmed state
+ */
+enum sgx_page_type {
+	SGX_PAGE_TYPE_SECS,
+	SGX_PAGE_TYPE_TCS,
+	SGX_PAGE_TYPE_REG,
+	SGX_PAGE_TYPE_VA,
+	SGX_PAGE_TYPE_TRIM,
+};
+
+#define SGX_NR_PAGE_TYPES	5
+#define SGX_PAGE_TYPE_MASK	GENMASK(7, 0)
+
+/**
+ * enum sgx_secinfo_flags - the flags field in &struct sgx_secinfo
+ * %SGX_SECINFO_R:	allow read
+ * %SGX_SECINFO_W:	allow write
+ * %SGX_SECINFO_X:	allow execution
+ * %SGX_SECINFO_SECS:	a SECS page
+ * %SGX_SECINFO_TCS:	a TCS page
+ * %SGX_SECINFO_REG:	a regular page
+ * %SGX_SECINFO_VA:	a VA page
+ * %SGX_SECINFO_TRIM:	a page in trimmed state
+ */
+enum sgx_secinfo_flags {
+	SGX_SECINFO_R			= BIT(0),
+	SGX_SECINFO_W			= BIT(1),
+	SGX_SECINFO_X			= BIT(2),
+	SGX_SECINFO_SECS		= (SGX_PAGE_TYPE_SECS << 8),
+	SGX_SECINFO_TCS			= (SGX_PAGE_TYPE_TCS << 8),
+	SGX_SECINFO_REG			= (SGX_PAGE_TYPE_REG << 8),
+	SGX_SECINFO_VA			= (SGX_PAGE_TYPE_VA << 8),
+	SGX_SECINFO_TRIM		= (SGX_PAGE_TYPE_TRIM << 8),
+};
+
+#define SGX_SECINFO_PERMISSION_MASK	GENMASK_ULL(2, 0)
+#define SGX_SECINFO_PAGE_TYPE_MASK	(SGX_PAGE_TYPE_MASK << 8)
+#define SGX_SECINFO_RESERVED_MASK	~(SGX_SECINFO_PERMISSION_MASK | \
+					  SGX_SECINFO_PAGE_TYPE_MASK)
+
+/**
+ * struct sgx_secinfo - describes attributes of an EPC page
+ * @flags:	permissions and type
+ *
+ * Used together with ENCLS leaves that add or modify an EPC page to an
+ * enclave to define page permissions and type.
+ */
+struct sgx_secinfo {
+	u64 flags;
+	u8  reserved[56];
+} __packed __aligned(64);
+
+#define SGX_PCMD_RESERVED_SIZE 40
+
+/**
+ * struct sgx_pcmd - Paging Crypto Metadata (PCMD)
+ * @enclave_id:	enclave identifier
+ * @mac:	MAC over PCMD, page contents and isvsvn
+ *
+ * PCMD is stored for every swapped page to the regular memory. When ELDU loads
+ * the page back it recalculates the MAC by using a isvsvn number stored in a
+ * VA page. Together these two structures bring integrity and rollback
+ * protection.
+ */
+struct sgx_pcmd {
+	struct sgx_secinfo secinfo;
+	u64 enclave_id;
+	u8  reserved[SGX_PCMD_RESERVED_SIZE];
+	u8  mac[16];
+} __packed __aligned(128);
+
+#define SGX_SIGSTRUCT_RESERVED1_SIZE 84
+#define SGX_SIGSTRUCT_RESERVED2_SIZE 20
+#define SGX_SIGSTRUCT_RESERVED3_SIZE 32
+#define SGX_SIGSTRUCT_RESERVED4_SIZE 12
+
+/**
+ * struct sgx_sigstruct_header -  defines author of the enclave
+ * @header1:		constant byte string
+ * @vendor:		must be either 0x0000 or 0x8086
+ * @date:		YYYYMMDD in BCD
+ * @header2:		costant byte string
+ * @swdefined:		software defined value
+ */
+struct sgx_sigstruct_header {
+	u64 header1[2];
+	u32 vendor;
+	u32 date;
+	u64 header2[2];
+	u32 swdefined;
+	u8  reserved1[84];
+} __packed;
+
+/**
+ * struct sgx_sigstruct_body - defines contents of the enclave
+ * @miscselect:		additional information stored to an SSA frame
+ * @misc_mask:		required miscselect in SECS
+ * @attributes:		attributes for enclave
+ * @xfrm:		XSave-Feature Request Mask (subset of XCR0)
+ * @attributes_mask:	required attributes in SECS
+ * @xfrm_mask:		required XFRM in SECS
+ * @mrenclave:		SHA256-hash of the enclave contents
+ * @isvprodid:		a user-defined value that is used in key derivation
+ * @isvsvn:		a user-defined value that is used in key derivation
+ */
+struct sgx_sigstruct_body {
+	u32 miscselect;
+	u32 misc_mask;
+	u8  reserved2[20];
+	u64 attributes;
+	u64 xfrm;
+	u64 attributes_mask;
+	u64 xfrm_mask;
+	u8  mrenclave[32];
+	u8  reserved3[32];
+	u16 isvprodid;
+	u16 isvsvn;
+} __packed;
+
+/**
+ * struct sgx_sigstruct - an enclave signature
+ * @header:		defines author of the enclave
+ * @modulus:		the modulus of the public key
+ * @exponent:		the exponent of the public key
+ * @signature:		the signature calculated over the fields except modulus,
+ * @body:		defines contents of the enclave
+ * @q1:			a value used in RSA signature verification
+ * @q2:			a value used in RSA signature verification
+ *
+ * Header and body are the parts that are actual signed. The remaining fields
+ * define the signature of the enclave.
+ */
+struct sgx_sigstruct {
+	struct sgx_sigstruct_header header;
+	u8  modulus[SGX_MODULUS_SIZE];
+	u32 exponent;
+	u8  signature[SGX_MODULUS_SIZE];
+	struct sgx_sigstruct_body body;
+	u8  reserved4[12];
+	u8  q1[SGX_MODULUS_SIZE];
+	u8  q2[SGX_MODULUS_SIZE];
+} __packed;
+
+#define SGX_EINITTOKEN_RESERVED1_SIZE 11
+#define SGX_EINITTOKEN_RESERVED2_SIZE 32
+#define SGX_EINITTOKEN_RESERVED3_SIZE 32
+#define SGX_EINITTOKEN_RESERVED4_SIZE 24
+
+/**
+ * struct sgx_einittoken - a token permitting to launch an enclave
+ * @valid:			one if valid and zero if invalid
+ * @attributes:			attributes for enclave
+ * @xfrm:			XSave-Feature Request Mask (subset of XCR0)
+ * @mrenclave:			SHA256-hash of the enclave contents
+ * @mrsigner:			SHA256-hash of the public key used to sign the
+ *				SIGSTRUCT
+ * @le_cpusvn:			a value that reflects the SGX implementation
+ *				running in in the CPU
+ * @le_isvprodid:		a user-defined value that is used in key
+ *				derivation
+ * @le_isvsvn:			a user-defined value that is used in key
+ *				derivation
+ * @le_keyed_miscselect:	LE's miscselect masked with the token keys
+ *				miscselect
+ * @le_keyed_attributes:	LE's attributes masked with the token keys
+ *				attributes
+ * @le_keyed_xfrm:		LE's XFRM masked with the token keys xfrm
+ * @salt:			random salt for wear-out protection
+ * @mac:			CMAC over the preceding fields
+ *
+ * An enclave with EINITTOKENKEY attribute can access a key with the same name
+ * by using ENCLS(EGETKEY) and use this to sign cryptographic tokens that can
+ * be passed to ENCLS(EINIT) to permit the launch of other enclaves. This is
+ * the only viable way to launch enclaves if IA32_SGXLEPUBKEYHASHn MSRs are
+ * locked assuming that there is a Launch Enclave (LE) available that can be
+ * used for generating these tokens.
+ */
+struct sgx_einittoken {
+	u32 valid;
+	u32 reserved1[SGX_EINITTOKEN_RESERVED1_SIZE];
+	u64 attributes;
+	u64 xfrm;
+	u8  mrenclave[32];
+	u8  reserved2[SGX_EINITTOKEN_RESERVED2_SIZE];
+	u8  mrsigner[32];
+	u8  reserved3[SGX_EINITTOKEN_RESERVED3_SIZE];
+	u8  le_cpusvn[16];
+	u16 le_isvprodid;
+	u16 le_isvsvn;
+	u8  reserved4[SGX_EINITTOKEN_RESERVED4_SIZE];
+	u32 le_keyed_miscselect;
+	u64 le_keyed_attributes;
+	u64 le_keyed_xfrm;
+	u8  salt[32];
+	u8  mac[16];
+} __packed __aligned(512);
+
+#endif /* _ASM_X86_SGX_ARCH_H */