You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@teaclave.apache.org by rd...@apache.org on 2022/12/19 08:00:23 UTC

[incubator-teaclave-sgx-sdk] branch master updated: Support intel sgx sdk 2.18

This is an automated email from the ASF dual-hosted git repository.

rduan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/incubator-teaclave-sgx-sdk.git


The following commit(s) were added to refs/heads/master by this push:
     new 27bd225a Support intel sgx sdk 2.18
27bd225a is described below

commit 27bd225ae6dbcd1d0a6d4d9590acc4d73c5195c2
Author: volcano <vo...@163.com>
AuthorDate: Sun Dec 11 16:06:56 2022 +0800

    Support intel sgx sdk 2.18
---
 common/inc/fenv.h                              | 139 ++++++++++++
 common/inc/stdalign.h                          |  15 ++
 common/inc/stddef.h                            |   2 +-
 common/inc/stdlib.h                            |   6 +
 common/inc/sys/fpu.h                           |  99 +++++++++
 common/inc/sys/ieee.h                          |  25 +++
 samplecode/switchless/app/build.rs             |   4 +-
 samplecode/unit-test/enclave/src/test_types.rs |   2 +-
 sgx_tprotected_fs/src/fs.rs                    |  74 +++++++
 sgx_trts/src/emm.rs                            | 287 +++++++++++++++++++++++++
 sgx_trts/src/lib.rs                            |   1 +
 sgx_tstd/build.rs                              |   6 +-
 sgx_tstd/src/sgxfs.rs                          |  74 ++++++-
 sgx_tstd/src/sys/sgxfs.rs                      | 266 ++++++++++++-----------
 sgx_types/src/error.rs                         |  32 +++
 sgx_types/src/function.rs                      |  98 ++++++++-
 sgx_types/src/macros.rs                        | 171 ++++++++++++++-
 sgx_types/src/metadata.rs                      |  24 ++-
 sgx_types/src/types.rs                         | 133 +++++++++++-
 sgx_urts/src/enclave.rs                        |   4 +-
 20 files changed, 1291 insertions(+), 171 deletions(-)

diff --git a/common/inc/fenv.h b/common/inc/fenv.h
new file mode 100644
index 00000000..a233172a
--- /dev/null
+++ b/common/inc/fenv.h
@@ -0,0 +1,139 @@
+/*	$OpenBSD: fenv.h,v 1.2 2011/05/25 21:46:49 martynas Exp $	*/
+/*	$NetBSD: fenv.h,v 1.2.4.1 2011/02/08 16:18:55 bouyer Exp $	*/
+
+/*
+ * Copyright (c) 2010 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef	_FENV_H_
+#define	_FENV_H_
+
+#include <sys/cdefs.h>
+
+/*
+ * Each symbol representing a floating point exception expands to an integer
+ * constant expression with values, such that bitwise-inclusive ORs of _all
+ * combinations_ of the constants result in distinct values.
+ *
+ * We use such values that allow direct bitwise operations on FPU/SSE registers.
+ */
+#define	FE_INVALID		0x01
+#define	FE_DENORMAL		0x02
+#define	FE_DIVBYZERO		0x04
+#define	FE_OVERFLOW		0x08
+#define	FE_UNDERFLOW		0x10
+#define	FE_INEXACT		0x20
+
+/*
+ * The following symbol is simply the bitwise-inclusive OR of all floating-point
+ * exception constants defined above.
+ */
+#define	FE_ALL_EXCEPT		(FE_INVALID | FE_DENORMAL | FE_DIVBYZERO | \
+				 FE_OVERFLOW | FE_UNDERFLOW | FE_INEXACT)
+#define	_SSE_MASK_SHIFT		7
+
+/*
+ * Each symbol representing the rounding direction, expands to an integer
+ * constant expression whose value is distinct non-negative value.
+ *
+ * We use such values that allow direct bitwise operations on FPU/SSE registers.
+ */
+#define	FE_TONEAREST		0x000
+#define	FE_DOWNWARD		0x400
+#define	FE_UPWARD		0x800
+#define	FE_TOWARDZERO		0xc00
+
+/*
+ * The following symbol is simply the bitwise-inclusive OR of all floating-point
+ * rounding direction constants defined above.
+ */
+#define	_X87_ROUND_MASK		(FE_TONEAREST | FE_DOWNWARD | FE_UPWARD | \
+				 FE_TOWARDZERO)
+#define	_SSE_ROUND_SHIFT	3
+
+/*
+ * fenv_t represents the entire floating-point environment.
+ */
+typedef	struct {
+	struct {
+		unsigned int __control;		/* Control word register */
+		unsigned int __status;		/* Status word register */
+		unsigned int __tag;		/* Tag word register */
+		unsigned int __others[4];	/* EIP, Pointer Selector, etc */
+	} __x87;
+	unsigned int __mxcsr;			/* Control, status register */
+} fenv_t;
+
+/*
+ * The following constant represents the default floating-point environment
+ * (that is, the one installed at program startup) and has type pointer to
+ * const-qualified fenv_t.
+ *
+ * It can be used as an argument to the functions within the <fenv.h> header
+ * that manage the floating-point environment, namely fesetenv() and
+ * feupdateenv().
+ */
+__BEGIN_DECLS
+extern	fenv_t			__fe_dfl_env;
+__END_DECLS
+#define	FE_DFL_ENV		((const fenv_t *)&__fe_dfl_env)
+
+/*
+ * fexcept_t represents the floating-point status flags collectively, including
+ * any status the implementation associates with the flags.
+ *
+ * A floating-point status flag is a system variable whose value is set (but
+ * never cleared) when a floating-point exception is raised, which occurs as a
+ * side effect of exceptional floating-point arithmetic to provide auxiliary
+ * information.
+ *
+ * A floating-point control mode is a system variable whose value may be set by
+ * the user to affect the subsequent behavior of floating-point arithmetic.
+ */
+typedef	unsigned int		fexcept_t;
+
+__BEGIN_DECLS
+
+int	feclearexcept(int);
+int	fegetexceptflag(fexcept_t *, int);
+int	feraiseexcept(int);
+int	fesetexceptflag(const fexcept_t *, int);
+int	fetestexcept(int);
+
+int	fegetround(void);
+int	fesetround(int);
+
+int	fegetenv(fenv_t *);
+int	feholdexcept(fenv_t *);
+int	fesetenv(const fenv_t *);
+int	feupdateenv(const fenv_t *);
+
+int	feenableexcept(int);
+int	fedisableexcept(int);
+int	fegetexcept(void);
+
+__END_DECLS
+
+#endif	/* ! _FENV_H_ */
diff --git a/common/inc/stdalign.h b/common/inc/stdalign.h
new file mode 100644
index 00000000..93b8f601
--- /dev/null
+++ b/common/inc/stdalign.h
@@ -0,0 +1,15 @@
+#ifndef _STDALIGN_H
+#define _STDALIGN_H
+#ifndef __cplusplus
+/* this whole header only works in C11 or with compiler extensions */
+#if __STDC_VERSION__ < 201112L && defined( __GNUC__)
+#define _Alignas(t) __attribute__((__aligned__(t)))
+#define _Alignof(t) __alignof__(t)
+#endif
+#define alignas _Alignas
+#define alignof _Alignof
+#endif
+#define __alignas_is_defined 1
+#define __alignof_is_defined 1
+#endif
+
diff --git a/common/inc/stddef.h b/common/inc/stddef.h
index c1328824..62d65302 100644
--- a/common/inc/stddef.h
+++ b/common/inc/stddef.h
@@ -64,7 +64,7 @@ typedef __WCHAR_TYPE__ wchar_t;
 #endif
 #endif
 
-#define offsetof(type, member)  ((size_t)(&((type *)0)->member))
+#define offsetof(type, member)   __builtin_offsetof (type, member)
 
 #endif /* _STDDEF_H_ */
 
diff --git a/common/inc/stdlib.h b/common/inc/stdlib.h
index e5b63653..8128e0d5 100644
--- a/common/inc/stdlib.h
+++ b/common/inc/stdlib.h
@@ -99,6 +99,12 @@ long    _TLIBC_CDECL_ labs(long);
 ldiv_t  _TLIBC_CDECL_ ldiv(long, long);
 void *  _TLIBC_CDECL_ malloc(size_t);
 void *  _TLIBC_CDECL_ memalign(size_t, size_t);
+#ifndef __cplusplus
+int     _TLIBC_CDECL_ posix_memalign(void **, size_t, size_t);
+#else
+int     _TLIBC_CDECL_ posix_memalign(void **, size_t, size_t) throw ();
+#endif
+void *  _TLIBC_CDECL_ aligned_alloc(size_t, size_t);
 void    _TLIBC_CDECL_ qsort(void *, size_t, size_t, int (*)(const void *, const void *));
 void *  _TLIBC_CDECL_ realloc(void *, size_t);
 double  _TLIBC_CDECL_ strtod(const char *, char **);
diff --git a/common/inc/sys/fpu.h b/common/inc/sys/fpu.h
new file mode 100644
index 00000000..4c218a91
--- /dev/null
+++ b/common/inc/sys/fpu.h
@@ -0,0 +1,99 @@
+/*	$OpenBSD: fpu.h,v 1.16 2018/10/07 22:43:06 guenther Exp $	*/
+/*	$NetBSD: fpu.h,v 1.1 2003/04/26 18:39:40 fvdl Exp $	*/
+
+#ifndef	_MACHINE_FPU_H_
+#define	_MACHINE_FPU_H_
+
+#include <sys/types.h>
+
+/*
+ * If the CPU supports xsave/xrstor then we use them so that we can provide
+ * AVX support.  Otherwise we require fxsave/fxrstor, as the SSE registers
+ * are part of the ABI for passing floating point values.
+ * While fxsave/fxrstor only required 16-byte alignment for the save area,
+ * xsave/xrstor requires the save area to have 64-byte alignment.
+ */
+
+struct fxsave64 {
+	u_int16_t  fx_fcw;
+	u_int16_t  fx_fsw;
+	u_int8_t   fx_ftw;
+	u_int8_t   fx_unused1;
+	u_int16_t  fx_fop;
+	u_int64_t  fx_rip;
+	u_int64_t  fx_rdp;
+	u_int32_t  fx_mxcsr;
+	u_int32_t  fx_mxcsr_mask;
+	u_int64_t  fx_st[8][2];   /* 8 normal FP regs */
+	u_int64_t  fx_xmm[16][2]; /* 16 SSE2 registers */
+	u_int8_t   fx_unused3[96];
+} __packed;
+
+struct xstate_hdr {
+	uint64_t	xstate_bv;
+	uint64_t	xstate_xcomp_bv;
+	uint8_t		xstate_rsrv0[0];
+	uint8_t		xstate_rsrv[40];
+} ___packed;
+
+struct savefpu {
+	struct fxsave64 fp_fxsave;	/* see above */
+	struct xstate_hdr fp_xstate;
+	u_int64_t fp_ymm[16][2];
+	u_int16_t fp_ex_sw;		/* saved status from last exception */
+	u_int16_t fp_ex_tw;		/* saved tag from last exception */
+};
+
+/*
+ * The i387 defaults to Intel extended precision mode and round to nearest,
+ * with all exceptions masked.
+ */
+#define	__INITIAL_NPXCW__	0x037f
+#define __INITIAL_MXCSR__ 	0x1f80
+#define __INITIAL_MXCSR_MASK__	0xffbf
+
+#ifdef _KERNEL
+/*
+ * XXX
+ */
+struct trapframe;
+struct cpu_info;
+
+extern size_t	fpu_save_len;
+extern uint32_t	fpu_mxcsr_mask;
+extern uint64_t	xsave_mask;
+
+void fpuinit(struct cpu_info *);
+int fputrap(int _type);
+void fpusave(struct savefpu *);
+void fpusavereset(struct savefpu *);
+void fpu_kernel_enter(void);
+void fpu_kernel_exit(void);
+
+int	xrstor_user(struct savefpu *_addr, uint64_t _mask);
+#define	fpureset() \
+	xrstor_user(&proc0.p_addr->u_pcb.pcb_savefpu, xsave_mask)
+int	xsetbv_user(uint32_t _reg, uint64_t _mask);
+
+#define fninit()		__asm("fninit")
+#define fwait()			__asm("fwait")
+/* should be fxsave64, but where we use this it doesn't matter */
+#define fxsave(addr)		__asm("fxsave %0" : "=m" (*addr))
+#define ldmxcsr(addr)		__asm("ldmxcsr %0" : : "m" (*addr))
+#define fldcw(addr)		__asm("fldcw %0" : : "m" (*addr))
+
+static inline void
+xsave(struct savefpu *addr, uint64_t mask)
+{
+	uint32_t lo, hi;
+
+	lo = mask;
+	hi = mask >> 32;
+	/* should be xsave64, but where we use this it doesn't matter */
+	__asm volatile("xsave %0" : "=m" (*addr) : "a" (lo), "d" (hi) :
+	    "memory");
+}
+
+#endif
+
+#endif /* _MACHINE_FPU_H_ */
diff --git a/common/inc/sys/ieee.h b/common/inc/sys/ieee.h
index eab3b975..47379b28 100644
--- a/common/inc/sys/ieee.h
+++ b/common/inc/sys/ieee.h
@@ -77,6 +77,7 @@
  */
 
 #include <sys/types.h>
+#include <sys/cdefs.h>
 
 #define SNG_EXPBITS     8
 #define SNG_FRACBITS    23
@@ -143,3 +144,27 @@ struct ieee_ext {
 #define SNG_EXP_BIAS    127
 #define DBL_EXP_BIAS    1023
 #define EXT_EXP_BIAS    16383
+
+typedef int fp_except;
+#define FP_X_INV    0x01    /* invalid operation exception */
+#define FP_X_DNML   0x02    /* denormalization exception */
+#define FP_X_DZ     0x04    /* divide-by-zero exception */
+#define FP_X_OFL    0x08    /* overflow exception */
+#define FP_X_UFL    0x10    /* underflow exception */
+#define FP_X_IMP    0x20    /* imprecise (loss of precision) */
+
+typedef enum {
+    FP_RN=0,            /* round to nearest representable number */
+    FP_RM=1,            /* round toward negative infinity */
+    FP_RP=2,            /* round toward positive infinity */
+    FP_RZ=3         /* round to zero (truncate) */
+} fp_rnd;
+
+__BEGIN_DECLS
+extern fp_rnd    fpgetround(void);
+extern fp_rnd    fpsetround(fp_rnd);
+extern fp_except fpgetmask(void);
+extern fp_except fpsetmask(fp_except);
+extern fp_except fpgetsticky(void);
+extern fp_except fpsetsticky(fp_except);
+__END_DECLS
diff --git a/samplecode/switchless/app/build.rs b/samplecode/switchless/app/build.rs
index fd8807d9..00db6fa0 100644
--- a/samplecode/switchless/app/build.rs
+++ b/samplecode/switchless/app/build.rs
@@ -28,7 +28,9 @@ fn main () {
     println!("cargo:rustc-link-lib=static=Enclave_u");
 
     println!("cargo:rustc-link-search=native={}/lib64", sdk_dir);
-    println!("cargo:rustc-link-lib=static=sgx_uswitchless");
+    println!("cargo:rustc-link-arg=-Wl,--whole-archive");
+    println!("cargo:rustc-link-arg=-lsgx_uswitchless");
+    println!("cargo:rustc-link-arg=-Wl,--no-whole-archive");
     match is_sim.as_ref() {
         "SW" => println!("cargo:rustc-link-lib=dylib=sgx_urts_sim"),
         "HW" => println!("cargo:rustc-link-lib=dylib=sgx_urts"),
diff --git a/samplecode/unit-test/enclave/src/test_types.rs b/samplecode/unit-test/enclave/src/test_types.rs
index 8698b43f..87b2ff22 100644
--- a/samplecode/unit-test/enclave/src/test_types.rs
+++ b/samplecode/unit-test/enclave/src/test_types.rs
@@ -17,7 +17,7 @@ pub fn check_metadata_size() {
 
 pub fn check_version() {
     //https://github.com/intel/linux-sgx/blob/master/common/inc/internal/metadata.h#L41
-    let curr_version = 0x0000000200000004;
+    let curr_version = 0x0000000300000000;
     assert_eq!(
         meta_data_make_version!(MAJOR_VERSION, MINOR_VERSION),
         curr_version
diff --git a/sgx_tprotected_fs/src/fs.rs b/sgx_tprotected_fs/src/fs.rs
index 241a7d7f..30571890 100644
--- a/sgx_tprotected_fs/src/fs.rs
+++ b/sgx_tprotected_fs/src/fs.rs
@@ -48,6 +48,25 @@ unsafe fn rsgx_fopen_auto_key(filename: &CStr, mode: &CStr) -> SysResult<SGX_FIL
     }
 }
 
+unsafe fn rsgx_fopen_ex(
+    filename: &CStr,
+    mode: &CStr,
+    key: Option<&sgx_key_128bit_t>,
+    cache_size: u64,
+) -> SysResult<SGX_FILE> {
+    let file = sgx_fopen_ex(
+        filename.as_ptr(),
+        mode.as_ptr(),
+        key.map_or(core::ptr::null(), |key| key as *const sgx_key_128bit_t),
+        cache_size,
+    );
+    if file.is_null() {
+        Err(errno())
+    } else {
+        Ok(file)
+    }
+}
+
 unsafe fn rsgx_fwrite(stream: SGX_FILE, buf: &[u8]) -> SysResult<usize> {
     if stream.is_null() {
         return Err(libc::EINVAL);
@@ -275,6 +294,61 @@ impl SgxFileStream {
         unsafe { rsgx_fopen_auto_key(filename, mode).map(|f| SgxFileStream { stream: f }) }
     }
 
+    ///
+    /// The open function creates or opens a protected file.
+    ///
+    /// # Description
+    ///
+    /// open_ex is expert version of open/open_auto_key which is used if you want to control the internal `cache size`.
+    /// The specified `cache size` must be page (4KB by default) aligned.
+    /// Note that export_auto_key and import_auto_key don't support configuring `cache_size` right now.
+    ///
+    /// # Parameters
+    ///
+    /// **filename**
+    ///
+    /// The name of the file to be created or opened.
+    ///
+    /// **mode**
+    ///
+    /// The file open mode string. Allowed values are any combination of, or, with possible
+    /// and possible (since string functions are currently not sup- ported, is meaningless).
+    ///
+    /// **key**
+    ///
+    /// The encryption key of the file (optional). This key is used as a key derivation key, used for deriving encryption
+    /// keys for the file. If the file is created with open, you should protect this key and provide it as
+    /// input every time the file is opened.
+    ///
+    /// **cache_size**
+    ///
+    /// Internal cache size in byte, which used to cache R/W data in enclave before flush to actual file.
+    /// It must larger than default cache size (192KB), and must be page (4KB by default) aligned.
+    ///
+    /// # Requirements
+    ///
+    /// Header: sgx_tprotected_fs.edl
+    ///
+    /// Library: libsgx_tprotected_fs.a
+    ///
+    /// This API is provided by Occlum's fork of Intel SGX SDK.
+    ///
+    /// # Return value
+    ///
+    /// If the function succeeds, it returns a valid file pointer, which can be used by all the other functions
+    /// in the Protected FS API, otherwise, error code is returned.
+    ///
+    pub fn open_ex(
+        filename: &CStr,
+        mode: &CStr,
+        key: Option<&sgx_key_128bit_t>,
+        cache_size: u64,
+    ) -> SysResult<SgxFileStream> {
+        unsafe {
+            rsgx_fopen_ex(filename, mode, key, cache_size).map(|f| SgxFileStream { stream: f })
+        }
+    }
+
     ///
     /// The read function reads the requested amount of data from the file, and extends the file pointer by that amount.
     ///
diff --git a/sgx_trts/src/emm.rs b/sgx_trts/src/emm.rs
new file mode 100644
index 00000000..70c571f0
--- /dev/null
+++ b/sgx_trts/src/emm.rs
@@ -0,0 +1,287 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements.  See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership.  The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License.  You may obtain a copy of the License at
+//
+//   http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied.  See the License for the
+// specific language governing permissions and limitations
+// under the License..
+
+use core::mem;
+use core::ptr::{self, NonNull};
+use sgx_types::*;
+
+#[derive(Clone, Copy, Debug, Eq, PartialEq)]
+pub enum AllocAddr {
+    /// Free to choose any address
+    Any,
+    /// Prefer the address, but can use other address
+    Hint(NonNull<u8>),
+    /// Need to use the address, otherwise report error
+    Need(NonNull<u8>),
+}
+
+impl_bitflags! {
+    #[repr(C)]
+    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+    pub struct AllocFlags: u32 {
+        const RESERVE           = 0x0000_0001;
+        const COMMIT_NOW        = 0x0000_0002;
+        const COMMIT_ON_DEMAND  = 0x0000_0004;
+        const GROWSDOWN         = 0x0000_0010;
+        const GROWSUP           = 0x0000_0020;
+    }
+}
+
+impl_enum! {
+    #[repr(u32)]
+    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
+    pub enum PageType {
+        TCS = 0x0000_0100,
+        REG = 0x0000_0200,
+        TRIM = 0x0000_0400,
+        SS_FIRST = 0x0000_0500,
+        SS_REST = 0x0000_0600,
+    }
+}
+
+impl_enum! {
+    #[repr(u32)]
+    #[derive(Copy, Clone, PartialEq, Eq, Debug)]
+    pub enum Align {
+        A4KB = 12,
+        A8KB = 13,
+        A16KB = 14,
+        A32KB = 15,
+        A64KB = 16,
+        A128KB = 17,
+        A256KB = 18,
+        A512KB = 19,
+        A1MB = 20,
+        A2MB = 21,
+        A4MB = 22,
+        A8MB = 23,
+        A16MB = 24,
+        A32MB = 25,
+        A64MB = 26,
+        A128MB = 27,
+        A256MB = 28,
+        A512MB = 29,
+        A1GB = 30,
+        A2GB = 31,
+        A4GB = 32,
+    }
+}
+
+impl_bitflags! {
+    #[repr(C)]
+    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+    pub struct Perm: u32 {
+        const NONE  = 0x0000_0000;
+        const READ  = 0x0000_0001;
+        const WRITE  = 0x0000_0002;
+        const EXEC  = 0x0000_0004;
+        const DEFAULT = Self::READ.bits() | Self::WRITE.bits();
+        const ALL = Self::DEFAULT.bits() | Self::EXEC.bits();
+    }
+}
+
+impl_enum! {
+    #[repr(u32)]
+    #[derive(Clone, Copy, Debug, Eq, PartialEq)]
+    pub enum HandleResult {
+        Search = 0,
+        Execution = 0xFFFFFFFF,
+    }
+}
+
+pub type PageFaultHandler = extern "C" fn(pfinfo: &sgx_pfinfo, private: usize) -> HandleResult;
+
+pub struct AllocOptions {
+    flags: AllocFlags,
+    page_type: PageType,
+    align: Align,
+    handler: Option<PageFaultHandler>,
+    private: usize,
+}
+
+impl AllocOptions {
+    #[inline]
+    pub const fn new() -> Self {
+        AllocOptions {
+            flags: AllocFlags::RESERVE,
+            page_type: PageType::REG,
+            align: Align::A4KB,
+            handler: None,
+            private: 0,
+        }
+    }
+
+    #[inline]
+    pub fn set_flags(mut self, flags: AllocFlags) -> Self {
+        self.flags = flags;
+        self
+    }
+
+    #[inline]
+    pub fn set_page_types(mut self, page_type: PageType) -> Self {
+        self.page_type = page_type;
+        self
+    }
+
+    #[inline]
+    pub fn set_align(mut self, align: Align) -> Self {
+        self.align = align;
+        self
+    }
+
+    #[inline]
+    pub fn set_handler(mut self, handler: PageFaultHandler, private: usize) -> Self {
+        self.handler.replace(handler);
+        self.private = private;
+        self
+    }
+}
+
+impl Default for AllocOptions {
+    #[inline]
+    fn default() -> Self {
+        AllocOptions::new()
+    }
+}
+
+pub struct EmmAlloc;
+
+impl EmmAlloc {
+    /// Allocate a new memory region in enclave address space (ELRANGE).
+    #[inline]
+    pub unsafe fn alloc(
+        &self,
+        addr: AllocAddr,
+        length: usize,
+        options: AllocOptions,
+    ) -> SysResult<NonNull<u8>> {
+        let mut out_addr: *mut c_void = ptr::null_mut();
+
+        let flags = options.flags.bits()
+            | options.page_type as u32
+            | (options.align as u32) << SGX_EMA_ALIGNMENT_SHIFT;
+        let (addr, flags) = match addr {
+            AllocAddr::Any => (ptr::null_mut(), flags),
+            AllocAddr::Hint(addr) => (addr.as_ptr(), flags),
+            AllocAddr::Need(addr) => (addr.as_ptr(), flags | SGX_EMA_FIXED),
+        };
+
+        let ret = sgx_mm_alloc(
+            addr as *mut _,
+            length,
+            flags as i32,
+            mem::transmute(options.handler),
+            options.private as *mut _,
+            &mut out_addr as *mut *mut _,
+        );
+        if ret == 0 {
+            Ok(NonNull::new_unchecked(out_addr as *mut _))
+        } else {
+            Err(ret)
+        }
+    }
+
+    // Commit a partial or full range of memory allocated previously with
+    // AllocFlags::COMMIT_ON_DEMAND.
+    #[inline]
+    pub unsafe fn commit(&self, addr: NonNull<u8>, length: usize) -> SysError {
+        let ret = sgx_mm_commit(addr.as_ptr() as *mut _, length);
+        if ret == 0 {
+            Ok(())
+        } else {
+            Err(ret)
+        }
+    }
+
+    /// Load data into target pages within a region previously allocated by
+    /// alloc. This can be called to load data and set target permissions
+    /// at the same time, e.g., dynamic code loading. The caller has verified
+    /// data to be trusted and expected to be loaded to the target address range.
+    // Calling this API on pages already committed will fail.
+    #[inline]
+    pub unsafe fn commit_with_data(addr: NonNull<u8>, data: &[u8], perm: Perm) -> SysError {
+        let ret = sgx_mm_commit_data(
+            addr.as_ptr() as *mut _,
+            data.len(),
+            data.as_ptr() as *mut _,
+            perm.bits() as _,
+        );
+        if ret == 0 {
+            Ok(())
+        } else {
+            Err(ret)
+        }
+    }
+
+    /// Uncommit (trim) physical EPC pages in a previously committed range.
+    /// The pages in the allocation are freed, but the address range is still
+    /// reserved.
+    #[inline]
+    pub unsafe fn uncommit(&self, addr: NonNull<u8>, length: usize) -> SysError {
+        let ret = sgx_mm_uncommit(addr.as_ptr() as *mut _, length);
+        if ret == 0 {
+            Ok(())
+        } else {
+            Err(ret)
+        }
+    }
+
+    /// Deallocate the address range.
+    /// The pages in the allocation are freed and the address range is released
+    /// for future allocation.
+    #[inline]
+    pub unsafe fn dealloc(&self, addr: NonNull<u8>, length: usize) -> SysError {
+        let ret = sgx_mm_dealloc(addr.as_ptr() as *mut _, length);
+        if ret == 0 {
+            Ok(())
+        } else {
+            Err(ret)
+        }
+    }
+
+    /// Change permissions of an allocated region.
+    #[inline]
+    pub unsafe fn modify_permissions(
+        &self,
+        addr: NonNull<u8>,
+        length: usize,
+        perm: Perm,
+    ) -> SysError {
+        let ret = sgx_mm_modify_permissions(addr.as_ptr() as *mut _, length, perm.bits() as _);
+        if ret == 0 {
+            Ok(())
+        } else {
+            Err(ret)
+        }
+    }
+
+    /// Change the page type of an allocated region.
+    #[inline]
+    pub unsafe fn modify_type(
+        &self,
+        addr: NonNull<u8>,
+        length: usize,
+        page_type: PageType,
+    ) -> SysError {
+        let ret = sgx_mm_modify_type(addr.as_ptr() as *mut _, length, page_type as _);
+        if ret == 0 {
+            Ok(())
+        } else {
+            Err(ret)
+        }
+    }
+}
diff --git a/sgx_trts/src/lib.rs b/sgx_trts/src/lib.rs
index ac9606e4..491fa3d0 100644
--- a/sgx_trts/src/lib.rs
+++ b/sgx_trts/src/lib.rs
@@ -90,6 +90,7 @@ pub mod ascii;
 pub mod c_str;
 pub mod cpu_feature;
 pub mod cpuid;
+pub mod emm;
 pub mod enclave;
 pub mod memchr;
 pub mod memeq;
diff --git a/sgx_tstd/build.rs b/sgx_tstd/build.rs
index e387d710..30b617b7 100644
--- a/sgx_tstd/build.rs
+++ b/sgx_tstd/build.rs
@@ -24,10 +24,8 @@ fn main() {
         //println!("cargo:rustc-cfg=RUST_BACKTRACE=\"full\"");
     }
 
-    let mut sdk_dir = env::var("SGX_SDK")
-                    .unwrap_or_else(|_| "/opt/sgxsdk".to_string());
-    let _is_sim = env::var("SGX_MODE")
-                    .unwrap_or_else(|_| "HW".to_string());
+    let mut sdk_dir = env::var("SGX_SDK").unwrap_or_else(|_| "/opt/sgxsdk".to_string());
+    let _is_sim = env::var("SGX_MODE").unwrap_or_else(|_| "HW".to_string());
 
     if !Path::new(&sdk_dir).exists() {
         sdk_dir = "/opt/intel/sgxsdk".to_string();
diff --git a/sgx_tstd/src/sgxfs.rs b/sgx_tstd/src/sgxfs.rs
index 2a702c06..e4626ea9 100644
--- a/sgx_tstd/src/sgxfs.rs
+++ b/sgx_tstd/src/sgxfs.rs
@@ -17,11 +17,11 @@
 
 //! Filesystem manipulation operations.
 
-use crate::io::{self, SeekFrom, Seek, Read, Write};
+use crate::io::{self, Read, Seek, SeekFrom, Write};
 use crate::path::Path;
 use crate::sys::sgxfs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
-use sgx_types::{sgx_key_128bit_t, sgx_align_key_128bit_t};
+use sgx_types::{sgx_align_key_128bit_t, sgx_key_128bit_t};
 
 /// A reference to an open file on the filesystem.
 ///
@@ -122,10 +122,30 @@ impl SgxFile {
         OpenOptions::new().read(true).open_ex(path.as_ref(), key)
     }
 
+    pub fn open_with<P: AsRef<Path>>(
+        path: P,
+        key: Option<&sgx_key_128bit_t>,
+        cache_size: Option<u64>,
+    ) -> io::Result<SgxFile> {
+        OpenOptions::new()
+            .read(true)
+            .open_with(path.as_ref(), key, cache_size)
+    }
+
     pub fn create_ex<P: AsRef<Path>>(path: P, key: &sgx_key_128bit_t) -> io::Result<SgxFile> {
         OpenOptions::new().write(true).open_ex(path.as_ref(), key)
     }
 
+    pub fn create_with<P: AsRef<Path>>(
+        path: P,
+        key: Option<&sgx_key_128bit_t>,
+        cache_size: Option<u64>,
+    ) -> io::Result<SgxFile> {
+        OpenOptions::new()
+            .write(true)
+            .open_with(path.as_ref(), key, cache_size)
+    }
+
     pub fn is_eof(&self) -> bool {
         self.inner.is_eof()
     }
@@ -140,7 +160,9 @@ impl SgxFile {
 }
 
 impl AsInner<fs_imp::SgxFile> for SgxFile {
-    fn as_inner(&self) -> &fs_imp::SgxFile { &self.inner }
+    fn as_inner(&self) -> &fs_imp::SgxFile {
+        &self.inner
+    }
 }
 impl FromInner<fs_imp::SgxFile> for SgxFile {
     fn from_inner(f: fs_imp::SgxFile) -> SgxFile {
@@ -163,7 +185,9 @@ impl Write for SgxFile {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+    fn flush(&mut self) -> io::Result<()> {
+        self.inner.flush()
+    }
 }
 
 impl Seek for SgxFile {
@@ -182,7 +206,9 @@ impl<'a> Write for &'a SgxFile {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+    fn flush(&mut self) -> io::Result<()> {
+        self.inner.flush()
+    }
 }
 
 impl<'a> Seek for &'a SgxFile {
@@ -206,7 +232,8 @@ impl OpenOptions {
     /// `read`-able if opened.
     ///
     pub fn read(&mut self, read: bool) -> &mut OpenOptions {
-        self.0.read(read); self
+        self.0.read(read);
+        self
     }
 
     /// Sets the option for write access.
@@ -215,7 +242,8 @@ impl OpenOptions {
     /// `write`-able if opened.
     ///
     pub fn write(&mut self, write: bool) -> &mut OpenOptions {
-        self.0.write(write); self
+        self.0.write(write);
+        self
     }
 
     /// Sets the option for the append mode.
@@ -241,17 +269,20 @@ impl OpenOptions {
     /// `seek(SeekFrom::Current(0))`, and restore it before the next read.
     ///
     pub fn append(&mut self, append: bool) -> &mut OpenOptions {
-        self.0.append(append); self
+        self.0.append(append);
+        self
     }
 
     /// Sets the option for update a previous file.
     pub fn update(&mut self, update: bool) -> &mut OpenOptions {
-        self.0.update(update); self
+        self.0.update(update);
+        self
     }
 
     /// Sets the option for binary a file.
     pub fn binary(&mut self, binary: bool) -> &mut OpenOptions {
-        self.0.binary(binary); self
+        self.0.binary(binary);
+        self
     }
 
     /// Opens a file at `path` with the options specified by `self`.
@@ -263,6 +294,15 @@ impl OpenOptions {
         self._open_ex(path.as_ref(), key)
     }
 
+    pub fn open_with<P: AsRef<Path>>(
+        &self,
+        path: P,
+        key: Option<&sgx_key_128bit_t>,
+        cache_size: Option<u64>,
+    ) -> io::Result<SgxFile> {
+        self._open_with(path.as_ref(), key, cache_size)
+    }
+
     fn _open(&self, path: &Path) -> io::Result<SgxFile> {
         let inner = fs_imp::SgxFile::open(path, &self.0)?;
         Ok(SgxFile { inner })
@@ -272,10 +312,22 @@ impl OpenOptions {
         let inner = fs_imp::SgxFile::open_ex(path, &self.0, key)?;
         Ok(SgxFile { inner })
     }
+
+    fn _open_with(
+        &self,
+        path: &Path,
+        key: Option<&sgx_key_128bit_t>,
+        cache_size: Option<u64>,
+    ) -> io::Result<SgxFile> {
+        let inner = fs_imp::SgxFile::open_with(path, &self.0, key, cache_size)?;
+        Ok(SgxFile { inner })
+    }
 }
 
 impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
-    fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
+    fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions {
+        &mut self.0
+    }
 }
 
 pub fn remove<P: AsRef<Path>>(path: P) -> io::Result<()> {
diff --git a/sgx_tstd/src/sys/sgxfs.rs b/sgx_tstd/src/sys/sgxfs.rs
index 7120e179..773fdf1c 100644
--- a/sgx_tstd/src/sys/sgxfs.rs
+++ b/sgx_tstd/src/sys/sgxfs.rs
@@ -15,14 +15,14 @@
 // specific language governing permissions and limitations
 // under the License..
 
-use crate::os::unix::prelude::*;
-use crate::ffi::{CString, CStr};
+use crate::ffi::{CStr, CString};
 use crate::io::{self, Error, SeekFrom};
+use crate::os::unix::prelude::*;
 use crate::path::Path;
 use crate::sys_common::FromInner;
 use sgx_libc as libc;
 use sgx_tprotected_fs::{self, SgxFileStream};
-use sgx_types::{sgx_status_t, sgx_key_128bit_t, sgx_align_key_128bit_t};
+use sgx_types::{sgx_align_key_128bit_t, sgx_key_128bit_t, sgx_status_t};
 
 pub struct SgxFile(SgxFileStream);
 
@@ -64,10 +64,10 @@ impl OpenOptions {
 
     fn get_access_mode(&self) -> io::Result<String> {
         let mut mode = match (self.read, self.write, self.append) {
-            (true,  false, false) => "r".to_string(),
-            (false, true,  false) => "w".to_string(),
-            (false, false, true)  => "a".to_string(),
-            _ => {return Err(Error::from_raw_os_error(libc::EINVAL))},
+            (true, false, false) => "r".to_string(),
+            (false, true, false) => "w".to_string(),
+            (false, false, true) => "a".to_string(),
+            _ => return Err(Error::from_raw_os_error(libc::EINVAL)),
         };
         if self.update {
             mode += "+";
@@ -84,82 +84,99 @@ impl SgxFile {
         let path = cstr(path)?;
         let mode = opts.get_access_mode()?;
         let opts = CString::new(mode.as_bytes())?;
-        SgxFile::open_c(&path, &opts, &sgx_key_128bit_t::default(), true)
+        SgxFile::open_c(&path, &opts, None, true, None)
     }
 
     pub fn open_ex(path: &Path, opts: &OpenOptions, key: &sgx_key_128bit_t) -> io::Result<SgxFile> {
         let path = cstr(path)?;
         let mode = opts.get_access_mode()?;
         let opts = CString::new(mode.as_bytes())?;
-        SgxFile::open_c(&path, &opts, key, false)
+        SgxFile::open_c(&path, &opts, Some(key), false, None)
+    }
+
+    pub fn open_with(
+        path: &Path,
+        opts: &OpenOptions,
+        key: Option<&sgx_key_128bit_t>,
+        cache_size: Option<u64>,
+    ) -> io::Result<SgxFile> {
+        let path = cstr(path)?;
+        let mode = opts.get_access_mode()?;
+        let opts = CString::new(mode.as_bytes())?;
+        SgxFile::open_c(&path, &opts, key, false, cache_size)
     }
 
-    pub fn open_c(path: &CStr, opts: &CStr, key: &sgx_key_128bit_t, auto: bool) -> io::Result<SgxFile> {
-        let file = if auto {
+    pub fn open_c(
+        path: &CStr,
+        opts: &CStr,
+        key: Option<&sgx_key_128bit_t>,
+        auto: bool,
+        cache_size: Option<u64>,
+    ) -> io::Result<SgxFile> {
+        let file = if cache_size.is_some() {
+            SgxFileStream::open_ex(path, opts, key, cache_size.unwrap())
+        } else if auto == true || key.is_none() {
             SgxFileStream::open_auto_key(path, opts)
         } else {
-            SgxFileStream::open(path, opts, key)
+            SgxFileStream::open(path, opts, key.unwrap())
         };
 
-        file.map(SgxFile)
-            .map_err(|err| {
-                match err {
-                    1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-                    2 => Error::from_raw_os_error(libc::ENOENT),
-                    3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-                    4 | 5 => Error::from_raw_os_error(err),
-                    r if r > 4096 => {
-                        let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                        Error::from_sgx_error(status)
-                    },
-                    _ => Error::from_raw_os_error(err),
-                }
-            })
+        file.map(SgxFile).map_err(|err| match err {
+            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+            2 => Error::from_raw_os_error(libc::ENOENT),
+            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+            4 | 5 => Error::from_raw_os_error(err),
+            r if r > 4096 => {
+                let status =
+                    sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                Error::from_sgx_error(status)
+            }
+            _ => Error::from_raw_os_error(err),
+        })
     }
 
     pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
-        self.0.read(buf).map_err(|err| {
-            match err {
-                1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-                2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
-                3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-                4 | 5 => Error::from_raw_os_error(err),
-                r if r > 4096 => {
-                    let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                    Error::from_sgx_error(status)
-                },
-                _ => Error::from_raw_os_error(err),
+        self.0.read(buf).map_err(|err| match err {
+            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+            2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
+            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+            4 | 5 => Error::from_raw_os_error(err),
+            r if r > 4096 => {
+                let status =
+                    sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                Error::from_sgx_error(status)
             }
+            _ => Error::from_raw_os_error(err),
         })
     }
 
     pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
-        self.0.write(buf).map_err(|err| {
-            match err {
-                1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-                2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
-                3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-                4 | 5 => Error::from_raw_os_error(err),
-                r if r > 4096 => {
-                    let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                    Error::from_sgx_error(status)
-                },
-                _ => Error::from_raw_os_error(err),
+        self.0.write(buf).map_err(|err| match err {
+            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+            2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
+            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+            4 | 5 => Error::from_raw_os_error(err),
+            r if r > 4096 => {
+                let status =
+                    sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                Error::from_sgx_error(status)
             }
+            _ => Error::from_raw_os_error(err),
         })
     }
 
     pub fn tell(&self) -> io::Result<u64> {
-        self.0.tell().map_err(|err| {
-            match err {
+        self.0
+            .tell()
+            .map_err(|err| match err {
                 r if r > 4096 => {
-                    let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                    let status = sgx_status_t::from_repr(r as u32)
+                        .unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
                     Error::from_sgx_error(status)
-                },
+                }
                 _ => Error::from_raw_os_error(err),
-            }
-        })
-        .map(|offset| offset as u64)
+            })
+            .map(|offset| offset as u64)
     }
 
     pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
@@ -169,14 +186,13 @@ impl SgxFile {
             SeekFrom::Current(off) => (sgx_tprotected_fs::SeekFrom::Current, off),
         };
 
-        self.0.seek(offset, whence).map_err(|err| {
-            match err {
-                r if r > 4096 => {
-                    let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                    Error::from_sgx_error(status)
-                },
-                _ => Error::from_raw_os_error(err),
+        self.0.seek(offset, whence).map_err(|err| match err {
+            r if r > 4096 => {
+                let status =
+                    sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                Error::from_sgx_error(status)
             }
+            _ => Error::from_raw_os_error(err),
         })?;
 
         let offset = self.tell()?;
@@ -184,18 +200,17 @@ impl SgxFile {
     }
 
     pub fn flush(&self) -> io::Result<()> {
-        self.0.flush().map_err(|err| {
-            match err {
-                1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-                2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
-                3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-                4 | 5 => Error::from_raw_os_error(err),
-                r if r > 4096 => {
-                    let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                    Error::from_sgx_error(status)
-                },
-                _ => Error::from_raw_os_error(err),
+        self.0.flush().map_err(|err| match err {
+            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+            2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
+            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+            4 | 5 => Error::from_raw_os_error(err),
+            r if r > 4096 => {
+                let status =
+                    sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                Error::from_sgx_error(status)
             }
+            _ => Error::from_raw_os_error(err),
         })
     }
 
@@ -208,87 +223,82 @@ impl SgxFile {
     }
 
     pub fn clear_cache(&self) -> io::Result<()> {
-        self.0.clear_cache().map_err(|err| {
-            match err {
-                1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-                2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
-                3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-                4 | 5 => Error::from_raw_os_error(err),
-                r if r > 4096 => {
-                    let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                    Error::from_sgx_error(status)
-                },
-                _ => Error::from_raw_os_error(err),
+        self.0.clear_cache().map_err(|err| match err {
+            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+            2 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_INVALID_PARAMETER),
+            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+            4 | 5 => Error::from_raw_os_error(err),
+            r if r > 4096 => {
+                let status =
+                    sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+                Error::from_sgx_error(status)
             }
+            _ => Error::from_raw_os_error(err),
         })
     }
 }
 
 pub fn remove(path: &Path) -> io::Result<()> {
     let path = cstr(path)?;
-    sgx_tprotected_fs::remove(&path).map_err(|err| {
-        match err {
-            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-            2 => Error::from_raw_os_error(libc::ENOENT),
-            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-            4 | 5 => Error::from_raw_os_error(err),
-            r if r > 4096 => {
-                let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                Error::from_sgx_error(status)
-            },
-            _ => Error::from_raw_os_error(err),
+    sgx_tprotected_fs::remove(&path).map_err(|err| match err {
+        1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+        2 => Error::from_raw_os_error(libc::ENOENT),
+        3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+        4 | 5 => Error::from_raw_os_error(err),
+        r if r > 4096 => {
+            let status =
+                sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+            Error::from_sgx_error(status)
         }
+        _ => Error::from_raw_os_error(err),
     })
 }
 
 pub fn export_auto_key(path: &Path) -> io::Result<sgx_key_128bit_t> {
     let path = cstr(path)?;
-    sgx_tprotected_fs::export_auto_key(&path).map_err(|err| {
-        match err {
-            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-            2 => Error::from_raw_os_error(libc::ENOENT),
-            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-            4 | 5 => Error::from_raw_os_error(err),
-            r if r > 4096 => {
-                let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                Error::from_sgx_error(status)
-            },
-            _ => Error::from_raw_os_error(err),
+    sgx_tprotected_fs::export_auto_key(&path).map_err(|err| match err {
+        1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+        2 => Error::from_raw_os_error(libc::ENOENT),
+        3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+        4 | 5 => Error::from_raw_os_error(err),
+        r if r > 4096 => {
+            let status =
+                sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+            Error::from_sgx_error(status)
         }
+        _ => Error::from_raw_os_error(err),
     })
 }
 
 pub fn export_align_auto_key(path: &Path) -> io::Result<sgx_align_key_128bit_t> {
     let path = cstr(path)?;
-    sgx_tprotected_fs::export_align_auto_key(&path).map_err(|err| {
-        match err {
-            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-            2 => Error::from_raw_os_error(libc::ENOENT),
-            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-            4 | 5 => Error::from_raw_os_error(err),
-            r if r > 4096 => {
-                let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                Error::from_sgx_error(status)
-            },
-            _ => Error::from_raw_os_error(err),
+    sgx_tprotected_fs::export_align_auto_key(&path).map_err(|err| match err {
+        1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+        2 => Error::from_raw_os_error(libc::ENOENT),
+        3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+        4 | 5 => Error::from_raw_os_error(err),
+        r if r > 4096 => {
+            let status =
+                sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+            Error::from_sgx_error(status)
         }
+        _ => Error::from_raw_os_error(err),
     })
 }
 
 pub fn import_auto_key(path: &Path, key: &sgx_key_128bit_t) -> io::Result<()> {
     let path = cstr(path)?;
-    sgx_tprotected_fs::import_auto_key(&path, key).map_err(|err| {
-        match err {
-            1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
-            2 => Error::from_raw_os_error(libc::ENOENT),
-            3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
-            4 | 5 => Error::from_raw_os_error(err),
-            r if r > 4096 => {
-                let status = sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
-                Error::from_sgx_error(status)
-            },
-            _ => Error::from_raw_os_error(err),
+    sgx_tprotected_fs::import_auto_key(&path, key).map_err(|err| match err {
+        1 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_UNEXPECTED),
+        2 => Error::from_raw_os_error(libc::ENOENT),
+        3 => Error::from_sgx_error(sgx_status_t::SGX_ERROR_OUT_OF_MEMORY),
+        4 | 5 => Error::from_raw_os_error(err),
+        r if r > 4096 => {
+            let status =
+                sgx_status_t::from_repr(r as u32).unwrap_or(sgx_status_t::SGX_ERROR_UNEXPECTED);
+            Error::from_sgx_error(status)
         }
+        _ => Error::from_raw_os_error(err),
     })
 }
 
diff --git a/sgx_types/src/error.rs b/sgx_types/src/error.rs
index acc64c38..e63093ca 100644
--- a/sgx_types/src/error.rs
+++ b/sgx_types/src/error.rs
@@ -477,6 +477,11 @@ impl_enum! {
         SGX_QL_PSW_NOT_AVAILABLE                            = 0x0000_E052,
         SGX_QL_COLLATERAL_VERSION_NOT_SUPPORTED             = 0x0000_E053,
         SGX_QL_TDX_MODULE_MISMATCH                          = 0x0000_E060,
+        SGX_QL_QEIDENTITY_NOT_FOUND                         = 0x0000_E061,
+        SGX_QL_TCBINFO_NOT_FOUND                            = 0x0000_E062,
+        SGX_QL_INTERNAL_SERVER_ERROR                        = 0x0000_E063,
+        SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED      = 0x0000_E064,
+        SGX_QL_ROOT_CA_UNTRUSTED                            = 0x0000_E065,
         SGX_QL_ERROR_MAX                                    = 0x0000_E0FF,
     }
 }
@@ -627,6 +632,15 @@ impl sgx_quote3_error_t {
             sgx_quote3_error_t::SGX_QL_TDX_MODULE_MISMATCH => {
                 "TDX SEAM module identity is NOT match to Intel signed TDX SEAM module"
             }
+            sgx_quote3_error_t::SGX_QL_QEIDENTITY_NOT_FOUND => "QE identity was not found",
+            sgx_quote3_error_t::SGX_QL_TCBINFO_NOT_FOUND => "TCB Info was not found",
+            sgx_quote3_error_t::SGX_QL_INTERNAL_SERVER_ERROR => "Internal server error",
+            sgx_quote3_error_t::SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED => {
+                "The supplemental data version is not supported"
+            }
+            sgx_quote3_error_t::SGX_QL_ROOT_CA_UNTRUSTED => {
+                "The certificate used to establish SSL session is untrusted"
+            }
             sgx_quote3_error_t::SGX_QL_ERROR_MAX => {
                 "Indicate max error to allow better translation."
             }
@@ -772,6 +786,13 @@ impl sgx_quote3_error_t {
                 "SGX_QL_COLLATERAL_VERSION_NOT_SUPPORTED"
             }
             sgx_quote3_error_t::SGX_QL_TDX_MODULE_MISMATCH => "SGX_QL_TDX_MODULE_MISMATCH",
+            sgx_quote3_error_t::SGX_QL_QEIDENTITY_NOT_FOUND => "SGX_QL_QEIDENTITY_NOT_FOUND",
+            sgx_quote3_error_t::SGX_QL_TCBINFO_NOT_FOUND => "SGX_QL_TCBINFO_NOT_FOUND",
+            sgx_quote3_error_t::SGX_QL_INTERNAL_SERVER_ERROR => "SGX_QL_INTERNAL_SERVER_ERROR",
+            sgx_quote3_error_t::SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED => {
+                "SGX_QL_SUPPLEMENTAL_DATA_VERSION_NOT_SUPPORTED"
+            }
+            sgx_quote3_error_t::SGX_QL_ROOT_CA_UNTRUSTED => "SGX_QL_ROOT_CA_UNTRUSTED",
             sgx_quote3_error_t::SGX_QL_ERROR_MAX => "SGX_QL_ERROR_MAX",
         }
     }
@@ -808,6 +829,9 @@ impl_enum! {
         SGX_QCNL_ERROR_STATUS_CERTS_UNAVAILABLE = 0x0000_B012,
         SGX_QCNL_ERROR_STATUS_SERVICE_UNAVAILABLE = 0x0000_B013,
         SGX_QCNL_INVALID_CONFIG                 = 0x0000_B030,
+        SGX_QCNL_CACHE_MISSING                  = 0x0000_B031,
+        SGX_QCNL_CACHE_EXPIRED                  = 0x0000_B032,
+        SGX_QCNL_ROOT_CA_UNTRUSTED              = 0x0000_B033,
     }
 }
 
@@ -853,6 +877,11 @@ impl sgx_qcnl_error_t {
                 "Service is currently not available"
             }
             sgx_qcnl_error_t::SGX_QCNL_INVALID_CONFIG => "Error in configuration file",
+            sgx_qcnl_error_t::SGX_QCNL_CACHE_MISSING => "Cache missing",
+            sgx_qcnl_error_t::SGX_QCNL_CACHE_EXPIRED => "Cache expired",
+            sgx_qcnl_error_t::SGX_QCNL_ROOT_CA_UNTRUSTED => {
+                "The certificate used to establish SSL session is untrusted"
+            }
         }
     }
 
@@ -893,6 +922,9 @@ impl sgx_qcnl_error_t {
                 "SGX_QCNL_ERROR_STATUS_SERVICE_UNAVAILABLE"
             }
             sgx_qcnl_error_t::SGX_QCNL_INVALID_CONFIG => "SGX_QCNL_INVALID_CONFIG",
+            sgx_qcnl_error_t::SGX_QCNL_CACHE_MISSING => "SGX_QCNL_CACHE_MISSING",
+            sgx_qcnl_error_t::SGX_QCNL_CACHE_EXPIRED => "SGX_QCNL_CACHE_EXPIRED",
+            sgx_qcnl_error_t::SGX_QCNL_ROOT_CA_UNTRUSTED => "SGX_QCNL_ROOT_CA_UNTRUSTED",
         }
     }
 }
diff --git a/sgx_types/src/function.rs b/sgx_types/src/function.rs
index 4eaee78a..5d2b6d85 100644
--- a/sgx_types/src/function.rs
+++ b/sgx_types/src/function.rs
@@ -77,6 +77,12 @@ extern "C" {
     pub fn sgx_thread_rwlock_wrunlock(rwlock: *mut sgx_thread_rwlock_t) -> int32_t;
     pub fn sgx_thread_rwlock_unlock(rwlock: *mut sgx_thread_rwlock_t) -> int32_t;
 
+    /* intel sgx sdk 2.18 */
+    pub fn sgx_thread_spin_init(mutex: *mut sgx_thread_spinlock_t) -> int32_t;
+    pub fn sgx_thread_spin_destroy(mutex: *mut sgx_thread_spinlock_t) -> int32_t;
+    pub fn sgx_thread_spin_trylock(mutex: *mut sgx_thread_spinlock_t) -> int32_t;
+    pub fn sgx_thread_spin_unlock(mutex: *mut sgx_thread_spinlock_t) -> int32_t;
+
     /* intel sgx sdk 2.8 */
     //
     // sgx_rsrv_mem_mngr.h
@@ -659,6 +665,54 @@ extern "C" {
     //
     pub fn sgx_ocalloc(size: size_t) -> *mut c_void;
     pub fn sgx_ocfree();
+
+    /* intel sgx sdk 2.18 */
+    pub fn sgx_mm_mutex_create() -> *mut sgx_mm_mutex;
+    pub fn sgx_mm_mutex_lock(mutex: *mut sgx_mm_mutex) -> int32_t;
+    pub fn sgx_mm_mutex_unlock(mutex: *mut sgx_mm_mutex) -> int32_t;
+    pub fn sgx_mm_mutex_destroy(mutex: *mut sgx_mm_mutex) -> int32_t;
+    pub fn sgx_mm_is_within_enclave(addr: *const c_void, size: size_t) -> bool;
+
+    pub fn sgx_mm_register_pfhandler(pfhandler: sgx_mm_pfhandler_t) -> bool;
+    pub fn sgx_mm_unregister_pfhandler(pfhandler: sgx_mm_pfhandler_t) -> bool;
+
+    pub fn sgx_mm_alloc_ocall(
+        addr: uint64_t,
+        length: size_t,
+        page_type: int32_t,
+        alloc_flags: int32_t,
+    ) -> int32_t;
+    pub fn sgx_mm_modify_ocall(
+        addr: uint64_t,
+        length: size_t,
+        page_properties_from: int32_t,
+        page_properties_to: int32_t,
+    ) -> int32_t;
+}
+
+/* intel sgx sdk 2.18 */
+//#[link(name = "sgx_mm")]
+extern "C" {
+    pub fn sgx_mm_alloc(
+        addr: *mut c_void,
+        length: size_t,
+        flags: int32_t,
+        handler: sgx_enclave_fault_handler_t,
+        handler_private: *mut c_void,
+        out_addr: *mut *mut c_void,
+    ) -> int32_t;
+
+    pub fn sgx_mm_commit(addr: *mut c_void, length: size_t) -> int32_t;
+    pub fn sgx_mm_commit_data(
+        addr: *mut c_void,
+        length: size_t,
+        data: *mut uint8_t,
+        prot: int32_t,
+    ) -> int32_t;
+    pub fn sgx_mm_uncommit(addr: *mut c_void, length: size_t) -> int32_t;
+    pub fn sgx_mm_dealloc(addr: *mut c_void, length: size_t) -> int32_t;
+    pub fn sgx_mm_modify_permissions(addr: *mut c_void, length: size_t, prot: int32_t) -> int32_t;
+    pub fn sgx_mm_modify_type(addr: *mut c_void, length: size_t, page_type: int32_t) -> int32_t;
 }
 
 //#[link(name = "sgx_epid")]
@@ -905,6 +959,13 @@ extern "C" {
     ) -> SGX_FILE;
 
     pub fn sgx_fopen_auto_key(filename: *const c_char, mode: *const c_char) -> SGX_FILE;
+    /* intel sgx sdk 2.18 */
+    pub fn sgx_fopen_ex(
+        filename: *const c_char,
+        mode: *const c_char,
+        key: *const sgx_key_128bit_t,
+        cache_size: uint64_t,
+    ) -> SGX_FILE;
 
     pub fn sgx_fwrite(ptr: *const c_void, size: size_t, count: size_t, stream: SGX_FILE) -> size_t;
 
@@ -1050,7 +1111,10 @@ extern "C" {
     ) -> sgx_quote3_error_t;
     pub fn sgx_ql_free_root_ca_crl(p_root_ca_crl: *const uint8_t) -> sgx_quote3_error_t;
     /* intel DCAP 2.14 */
-    pub fn sgx_ql_set_logging_callback(logger: sgx_ql_logging_callback_t) -> sgx_quote3_error_t;
+    pub fn sgx_ql_set_logging_callback(
+        logger: sgx_ql_logging_callback_t,
+        loglevel: sgx_ql_log_level_t,
+    ) -> sgx_quote3_error_t;
 }
 
 //#[link(name = "sgx_default_qcnl_wrapper")]
@@ -1116,7 +1180,10 @@ extern "C" {
     /* intel DCAP 1.13 */
     pub fn sgx_qcnl_get_api_version(p_major_ver: *mut uint16_t, p_minor_ver: *mut uint16_t)
         -> bool;
-    pub fn sgx_qcnl_set_logging_callback(logger: sgx_ql_logging_callback_t) -> sgx_qcnl_error_t;
+    pub fn sgx_qcnl_set_logging_callback(
+        logger: sgx_ql_logging_callback_t,
+        loglevel: sgx_ql_log_level_t,
+    ) -> sgx_qcnl_error_t;
 
     /* intel DCAP 1.13 delete */
     // pub fn sgx_qcnl_register_platform(
@@ -1186,6 +1253,33 @@ extern "C" {
         supplemental_data_size: uint32_t,
         p_supplemental_data: *mut uint8_t,
     ) -> sgx_quote3_error_t;
+
+    /* intel DCAP 1.15 */
+    pub fn tee_qv_get_collateral(
+        p_quote: *const uint8_t,
+        quote_size: uint32_t,
+        pp_quote_collateral: *mut *mut uint8_t,
+        p_collateral_size: *mut uint32_t,
+    ) -> sgx_quote3_error_t;
+
+    pub fn tee_qv_free_collateral(p_quote_collateral: *const uint8_t) -> sgx_quote3_error_t;
+    pub fn tee_get_supplemental_data_version_and_size(
+        p_quote: *const uint8_t,
+        quote_size: uint32_t,
+        p_version: *mut uint32_t,
+        p_data_size: *mut uint32_t,
+    ) -> sgx_quote3_error_t;
+
+    pub fn tee_verify_quote(
+        p_quote: *const uint8_t,
+        quote_size: uint32_t,
+        p_quote_collateral: *const uint8_t,
+        expiration_check_date: time_t,
+        p_collateral_expiration_status: *mut uint32_t,
+        p_quote_verification_result: *mut sgx_ql_qv_result_t,
+        p_qve_report_info: *mut sgx_ql_qe_report_info_t,
+        p_supp_data_descriptor: *const tee_supp_data_descriptor_t,
+    ) -> sgx_quote3_error_t;
 }
 
 /* intel DCAP 1.7 */
diff --git a/sgx_types/src/macros.rs b/sgx_types/src/macros.rs
index 835edfb6..35d6b83c 100644
--- a/sgx_types/src/macros.rs
+++ b/sgx_types/src/macros.rs
@@ -211,7 +211,7 @@ macro_rules! impl_struct_clone {
 
 macro_rules! impl_struct_ContiguousMemory {
     ($($t:ty;)*) => {$(
-        unsafe impl ContiguousMemory for $t {}
+        unsafe impl $crate::marker::ContiguousMemory for $t {}
     )*}
 }
 
@@ -257,6 +257,175 @@ macro_rules! impl_enum {
     )
 }
 
+#[macro_export]
+macro_rules! impl_bitflags {
+    (
+        $(#[$outer:meta])*
+        pub struct $BitFlags:ident: $T:ty {
+            $(
+                const $Flag:ident = $value:expr;
+            )+
+        }
+    )
+    => (
+        $(#[$outer])*
+        pub struct $BitFlags($T);
+
+        impl $BitFlags {
+            $(
+                pub const $Flag: $BitFlags = $BitFlags($value);
+            )+
+
+            #[inline]
+            pub const fn empty() -> $BitFlags {
+                $BitFlags(0)
+            }
+
+            #[inline]
+            pub const fn all() -> $BitFlags {
+                $BitFlags($($value)|+)
+            }
+
+            #[inline]
+            pub const fn bits(&self) -> $T {
+                self.0
+            }
+
+            #[inline]
+            pub fn from_bits(bits: $T) -> Option<$BitFlags> {
+                if (bits & !$BitFlags::all().bits()) == 0 {
+                    Some($BitFlags(bits))
+                } else {
+                    None
+                }
+            }
+
+            #[inline]
+            pub const fn from_bits_truncate(bits: $T) -> $BitFlags {
+                $BitFlags(bits & $BitFlags::all().bits())
+            }
+
+            /// # Safety
+            #[inline]
+            pub const unsafe fn from_bits_unchecked(bits: $T) -> $BitFlags {
+                $BitFlags(bits)
+            }
+
+            #[inline]
+            pub const fn is_empty(&self) -> bool {
+                self.bits() == Self::empty().bits()
+            }
+
+            #[inline]
+            pub const fn is_all(&self) -> bool {
+                self.0 == Self::all().0
+            }
+
+            #[inline]
+            pub const fn contains(&self, other: $BitFlags) -> bool {
+                (self.0 & other.0) == other.0
+            }
+
+            #[inline]
+            pub const fn intersects(&self, other: $BitFlags) -> bool {
+                !$BitFlags(self.0 & other.0).is_empty()
+            }
+
+            #[inline]
+            pub fn insert(&mut self, other: $BitFlags) {
+                self.0 |= other.0;
+            }
+
+            #[inline]
+            pub fn remove(&mut self, other: $BitFlags) {
+                self.0 &= !other.0;
+            }
+
+            #[inline]
+            pub fn toggle(&mut self, other: $BitFlags) {
+                self.0 ^= other.0;
+            }
+        }
+
+        impl ::core::default::Default for $BitFlags {
+            #[inline]
+            fn default() -> Self {
+                Self::empty()
+            }
+        }
+
+        impl ::core::ops::Not for $BitFlags {
+            type Output = $BitFlags;
+            #[inline]
+            fn not(self) -> $BitFlags {
+                $BitFlags(!self.0) & $BitFlags::all()
+            }
+        }
+
+        impl ::core::ops::BitAnd for $BitFlags {
+            type Output = $BitFlags;
+            #[inline]
+            fn bitand(self, rhs: $BitFlags) -> $BitFlags {
+                $BitFlags(self.0 & rhs.0)
+            }
+        }
+
+        impl ::core::ops::BitOr for $BitFlags {
+            type Output = $BitFlags;
+            #[inline]
+            fn bitor(self, rhs: $BitFlags) -> $BitFlags {
+                $BitFlags(self.0 | rhs.0)
+            }
+        }
+
+        impl ::core::ops::BitXor for $BitFlags {
+            type Output = $BitFlags;
+            #[inline]
+            fn bitxor(self, rhs: $BitFlags) -> $BitFlags {
+                $BitFlags(self.0 ^ rhs.0)
+            }
+        }
+
+        impl ::core::ops::BitAndAssign for $BitFlags {
+            #[inline]
+            fn bitand_assign(&mut self, rhs: $BitFlags) {
+                self.0 &= rhs.0;
+            }
+        }
+
+        impl ::core::ops::BitOrAssign for $BitFlags {
+            #[inline]
+            fn bitor_assign(&mut self, rhs: $BitFlags) {
+                self.0 |= rhs.0;
+            }
+        }
+
+        impl ::core::ops::BitXorAssign for $BitFlags {
+            #[inline]
+            fn bitxor_assign(&mut self, rhs: $BitFlags) {
+                self.0 ^= rhs.0;
+            }
+        }
+
+        impl ::core::ops::Sub for $BitFlags {
+            type Output = $BitFlags;
+            #[inline]
+            fn sub(self, rhs: $BitFlags) -> $BitFlags {
+                $BitFlags(self.0 & !rhs.0)
+            }
+        }
+
+        impl ::core::ops::SubAssign for $BitFlags {
+            #[inline]
+            fn sub_assign(&mut self, rhs: $BitFlags) {
+                self.0 &= !rhs.0;
+            }
+        }
+
+        unsafe impl $crate::marker::ContiguousMemory for $BitFlags {}
+    )
+}
+
 #[macro_export]
 macro_rules! meta_data_make_version {
     ($major:ident, $minor:ident) => {
diff --git a/sgx_types/src/metadata.rs b/sgx_types/src/metadata.rs
index 873cdbb4..5b6fbd03 100644
--- a/sgx_types/src/metadata.rs
+++ b/sgx_types/src/metadata.rs
@@ -73,11 +73,11 @@ pub struct enclave_css_t {
 }
 
 /* version of metadata */
-/* based on 2.9.1 */
-pub const MAJOR_VERSION: u32 = 2;
-pub const MINOR_VERSION: u32 = 4;
+/* based on 2.18 */
+pub const MAJOR_VERSION: u32 = 3;
+pub const MINOR_VERSION: u32 = 0;
 
-pub const SGX_2_ELRANGE_MAJOR_VERSION: u32 = 12;
+pub const SGX_2_ELRANGE_MAJOR_VERSION: u32 = 13;
 pub const SGX_1_ELRANGE_MAJOR_VERSION: u32 = 11;
 pub const SGX_MAJOR_VERSION_GAP: u32 = 10;
 
@@ -101,13 +101,14 @@ pub const MAX_SAVE_BUF_SIZE: u32 = 2632;
 pub const TCS_NUM_MIN: u32 = 1;
 pub const SSA_NUM_MIN: u32 = 2;
 pub const SSA_FRAME_SIZE_MIN: u32 = 1;
-pub const SSA_FRAME_SIZE_MAX: u32 = 2;
-pub const STACK_SIZE_MIN: u32 = 0x0000_2000; /*   8 KB */
-pub const STACK_SIZE_MAX: u32 = 0x0004_0000; /* 256 KB */
-pub const HEAP_SIZE_MIN: u32 = 0x0000_1000; /*   4 KB */
-pub const HEAP_SIZE_MAX: u32 = 0x0100_0000; /*  16 MB */
-pub const RSRV_SIZE_MIN: u32 = 0x0000_0000; /*   0 KB */
-pub const RSRV_SIZE_MAX: u32 = 0x0000_0000; /*   0 KB */
+pub const SSA_FRAME_SIZE_MAX: u32 = 4;
+pub const STACK_SIZE_MIN: u32 = 0x0000_2000; // 8 KB
+pub const STACK_SIZE_MAX: u32 = 0x0004_0000; // 256 KB
+pub const HEAP_SIZE_MIN: u32 = 0x0000_1000; // 4 KB
+pub const HEAP_SIZE_MAX: u32 = 0x0100_0000; // 16 MB
+pub const RSRV_SIZE_MIN: u32 = 0x0000_0000; // 0 KB
+pub const RSRV_SIZE_MAX: u32 = 0x0000_0000; // 0 KB
+pub const USER_REGION_SIZE: u32 = 0x0000_0000; // 0 KB
 pub const DEFAULT_MISC_SELECT: u32 = 0;
 pub const DEFAULT_MISC_MASK: u32 = 0xFFFF_FFFF;
 pub const ISVFAMILYID_MAX: u64 = 0xFFFF_FFFF_FFFF_FFFF;
@@ -157,6 +158,7 @@ pub const LAYOUT_ID_THREAD_GROUP_DYN: u32 = group_id!(19);
 pub const LAYOUT_ID_RSRV_MIN: u32 = 20;
 pub const LAYOUT_ID_RSRV_INIT: u32 = 21;
 pub const LAYOUT_ID_RSRV_MAX: u32 = 22;
+pub const LAYOUT_ID_USER_REGION: u32 = 23;
 
 type si_flags_t = u64;
 
diff --git a/sgx_types/src/types.rs b/sgx_types/src/types.rs
index 04863629..a5a10bb3 100644
--- a/sgx_types/src/types.rs
+++ b/sgx_types/src/types.rs
@@ -38,6 +38,7 @@ pub const SGX_FLAGS_RESERVED: uint64_t = !(SGX_FLAGS_INITTED
     | SGX_FLAGS_PROVISION_KEY
     | SGX_FLAGS_EINITTOKEN_KEY
     | SGX_FLAGS_KSS);
+pub const SGX_FLAGS_NON_CHECK_BITS: uint64_t = 0x00FF_0000_0000_0000; //BIT[55-48] will not be checked
 
 // XSAVE Feature Request Mask
 pub const SGX_XFRM_LEGACY: uint64_t = 0x0000_0000_0000_0003; //Legacy XFRM
@@ -45,9 +46,10 @@ pub const SGX_XFRM_AVX: uint64_t = 0x0000_0000_0000_0006; // AVX
 pub const SGX_XFRM_AVX512: uint64_t = 0x0000_0000_0000_00E6; // AVX-512 - not supported
 pub const SGX_XFRM_MPX: uint64_t = 0x0000_0000_0000_0018; // MPX - not supported
 pub const SGX_XFRM_PKRU: uint64_t = 0x0000_0000_0000_0200; // PKRU state
+pub const SGX_XFRM_AMX: uint64_t = 0x0000_0000_0006_0000; // AMX XFRM, including XTILEDATA(0x40000) and XTILECFG(0x20000)
 
 pub const SGX_XFRM_RESERVED: uint64_t =
-    !(SGX_XFRM_LEGACY | SGX_XFRM_AVX | SGX_XFRM_AVX512 | SGX_XFRM_PKRU);
+    !(SGX_XFRM_LEGACY | SGX_XFRM_AVX | SGX_XFRM_AVX512 | SGX_XFRM_PKRU | SGX_XFRM_AMX);
 
 impl_struct! {
     pub struct sgx_attributes_t {
@@ -945,6 +947,21 @@ pub const SGX_THREAD_COND_INITIALIZER: sgx_thread_cond_t = sgx_thread_cond_t {
     },
 };
 
+/* intel sgx sdk 2.18 */
+#[repr(C)]
+pub struct sgx_thread_spinlock_t {
+    pub m_refcount: size_t,
+    pub m_lock: uint32_t,
+    pub m_owner: sgx_thread_t,
+}
+
+pub const SGX_THREAD_RECURSIVE_SPINLOCK_INITIALIZER: sgx_thread_spinlock_t =
+    sgx_thread_spinlock_t {
+        m_refcount: 0,
+        m_lock: 0,
+        m_owner: SGX_THREAD_T_NULL,
+    };
+
 //
 // sgx_tkey_exchange.h
 //
@@ -1032,11 +1049,20 @@ cfg_if! {
     }
 }
 
+impl_struct! {
+    pub struct sgx_misc_exinfo_t {
+        pub faulting_address: uint64_t,
+        pub error_code: uint32_t,
+        pub reserved: uint32_t,
+    }
+}
+
 impl_struct! {
     pub struct sgx_exception_info_t {
         pub cpu_context: sgx_cpu_context_t,
         pub exception_vector: sgx_exception_vector_t,
         pub exception_type: sgx_exception_type_t,
+        pub exinfo: sgx_misc_exinfo_t,
     }
 }
 
@@ -1250,11 +1276,11 @@ pub const SGX_USWITCHLESS_WORKER_EVENT_NUM: size_t = 4;
 
 #[repr(C)]
 pub struct sgx_uswitchless_config_t {
-    pub switchless_calls_pool_size_qwords: uint32_t,
-    pub num_uworkers: uint32_t,
-    pub num_tworkers: uint32_t,
-    pub retries_before_fallback: uint32_t,
-    pub retries_before_sleep: uint32_t,
+    pub switchless_calls_pool_size_qwords: uint64_t,
+    pub num_uworkers: uint64_t,
+    pub num_tworkers: uint64_t,
+    pub retries_before_fallback: uint64_t,
+    pub retries_before_sleep: uint64_t,
     pub callback_func: [sgx_uswitchless_worker_callback_t; SGX_USWITCHLESS_WORKER_EVENT_NUM],
 }
 
@@ -1637,11 +1663,12 @@ impl_enum! {
 }
 
 //
-// qve_header.h
+// sgx_qve_header.h
 //
 
 pub const ROOT_KEY_ID_SIZE: usize = 48;
 pub const PLATFORM_INSTANCE_ID_SIZE: usize = 16;
+pub const MAX_SA_LIST_SIZE: usize = 160;
 
 /* intel DCAP 1.7 */
 impl_enum! {
@@ -1678,17 +1705,27 @@ impl_copy_clone! {
         pub dynamic_platform: pck_cert_flag_enum_t,
         pub cached_keys: pck_cert_flag_enum_t,
         pub smt_enabled: pck_cert_flag_enum_t,
+        /* intel DCAP 1.15 */
+        pub sa_list: [c_char; MAX_SA_LIST_SIZE],
     }
 }
 
 impl_struct_default! {
-    sgx_ql_qv_supplemental_t; //176
+    sgx_ql_qv_supplemental_t; //336
 }
 
 impl_struct_ContiguousMemory! {
     sgx_ql_qv_supplemental_t;
 }
 
+/* intel DCAP 1.15 */
+#[repr(C)]
+pub struct tee_supp_data_descriptor_t {
+    pub major_version: uint16_t,
+    pub data_size: uint32_t,
+    pub p_data: *mut uint8_t,
+}
+
 /* intel DCAP 1.6 */
 //
 // sgx_dcap_quoteverify.h
@@ -1900,7 +1937,6 @@ unsafe impl ContiguousMemory for sgx_align_ec256_dh_shared_t {}
 unsafe impl ContiguousMemory for sgx_align_ec256_private_t {}
 
 /* intel sgx sdk 2.8 */
-
 //
 // sgx_rsrv_mem_mngr.h
 //
@@ -1908,3 +1944,82 @@ pub const SGX_PROT_READ: uint32_t = 0x1; /* page can be read */
 pub const SGX_PROT_WRITE: uint32_t = 0x2; /* page can be written */
 pub const SGX_PROT_EXEC: uint32_t = 0x4; /* page can be executed */
 pub const SGX_PROT_NONE: uint32_t = 0x0; /* page can not be accessed */
+
+/* intel sgx sdk 2.18 */
+//
+// sgx_mm_rt_abstraction.h
+//
+#[repr(C)]
+pub struct sgx_mm_mutex {
+    pub m: sgx_thread_spinlock_t,
+}
+
+pub type sgx_mm_pfhandler_t = extern "C" fn(pfinfo: *const sgx_pfinfo) -> int32_t;
+
+//
+// sgx_mm.h
+//
+impl_struct! {
+    pub struct sgx_pfinfo {
+        pub maddr: uint64_t,
+        pub pfec: uint32_t,
+        pub reserved: uint32_t,
+    }
+}
+
+pub type sgx_enclave_fault_handler_t =
+    extern "C" fn(pfinfo: *const sgx_pfinfo, private_data: *mut c_void) -> int32_t;
+
+// bit 0 - 7 are allocation flags.
+pub const SGX_EMA_ALLOC_FLAGS_SHIFT: uint32_t = 0;
+pub const SGX_EMA_ALLOC_FLAGS_MASK: uint32_t = 0xFF << SGX_EMA_ALLOC_FLAGS_SHIFT;
+// Only reserve an address range, no physical memory committed.
+pub const SGX_EMA_RESERVE: uint32_t = 0x01 << SGX_EMA_ALLOC_FLAGS_SHIFT;
+// Reserve an address range and commit physical memory.
+pub const SGX_EMA_COMMIT_NOW: uint32_t = 0x02 << SGX_EMA_ALLOC_FLAGS_SHIFT;
+// Reserve an address range and commit physical memory on demand.
+pub const SGX_EMA_COMMIT_ON_DEMAND: uint32_t = 0x04 << SGX_EMA_ALLOC_FLAGS_SHIFT;
+// Always commit pages from higher to lower addresses,
+// no gaps in addresses above the last committed.
+pub const SGX_EMA_GROWSDOWN: uint32_t = 0x10 << SGX_EMA_ALLOC_FLAGS_SHIFT;
+// Always commit pages from lower to higher addresses,
+// no gaps in addresses below the last committed.
+pub const SGX_EMA_GROWSUP: uint32_t = 0x20 << SGX_EMA_ALLOC_FLAGS_SHIFT;
+// Map addr must be exactly as requested.
+pub const SGX_EMA_FIXED: uint32_t = 0x40 << SGX_EMA_ALLOC_FLAGS_SHIFT;
+
+// bit 8 - 15 are page types.
+pub const SGX_EMA_PAGE_TYPE_SHIFT: uint32_t = 8;
+pub const SGX_EMA_PAGE_TYPE_MASK: uint32_t = 0xFF << SGX_EMA_PAGE_TYPE_SHIFT;
+// TCS page type.
+pub const SGX_EMA_PAGE_TYPE_TCS: uint32_t = 0x01 << SGX_EMA_PAGE_TYPE_SHIFT;
+// regular page type, default if not specified.
+pub const SGX_EMA_PAGE_TYPE_REG: uint32_t = 0x02 << SGX_EMA_PAGE_TYPE_SHIFT;
+// TRIM page type.
+pub const SGX_EMA_PAGE_TYPE_TRIM: uint32_t = 0x04 << SGX_EMA_PAGE_TYPE_SHIFT;
+// the first page in shadow stack.
+pub const SGX_EMA_PAGE_TYPE_SS_FIRST: uint32_t = 0x05 << SGX_EMA_PAGE_TYPE_SHIFT;
+// the rest pages in shadow stack.
+pub const SGX_EMA_PAGE_TYPE_SS_REST: uint32_t = 0x06 << SGX_EMA_PAGE_TYPE_SHIFT;
+
+// Use bit 24-31 for alignment masks.
+pub const SGX_EMA_ALIGNMENT_SHIFT: uint32_t = 24;
+pub const SGX_EMA_ALIGNMENT_MASK: uint32_t = 0xFF << SGX_EMA_ALIGNMENT_SHIFT;
+pub const SGX_EMA_ALIGNMENT_64KB: uint32_t = 16 << SGX_EMA_ALIGNMENT_SHIFT;
+pub const SGX_EMA_ALIGNMENT_16MB: uint32_t = 24 << SGX_EMA_ALIGNMENT_SHIFT;
+pub const SGX_EMA_ALIGNMENT_4GB: uint32_t = 32 << SGX_EMA_ALIGNMENT_SHIFT;
+
+pub const SGX_EMA_PROT_NONE: uint32_t = 0x0;
+pub const SGX_EMA_PROT_READ: uint32_t = 0x1;
+pub const SGX_EMA_PROT_WRITE: uint32_t = 0x2;
+pub const SGX_EMA_PROT_EXEC: uint32_t = 0x4;
+pub const SGX_EMA_PROT_READ_WRITE: uint32_t = SGX_EMA_PROT_READ | SGX_EMA_PROT_WRITE;
+pub const SGX_EMA_PROT_READ_EXEC: uint32_t = SGX_EMA_PROT_READ | SGX_EMA_PROT_EXEC;
+pub const SGX_EMA_PROT_MASK: uint32_t = SGX_EMA_PROT_READ_WRITE | SGX_EMA_PROT_EXEC;
+
+// Return value used by the EMM #PF handler to indicate
+// to the dispatcher that it should continue searching for the next handler.
+pub const SGX_MM_EXCEPTION_CONTINUE_SEARCH: int32_t = 0;
+// Return value used by the EMM #PF handler to indicate
+// to the dispatcher that it should stop searching and continue execution.
+pub const SGX_MM_EXCEPTION_CONTINUE_EXECUTION: int32_t = -1;
diff --git a/sgx_urts/src/enclave.rs b/sgx_urts/src/enclave.rs
index 1af6e263..0aea765f 100644
--- a/sgx_urts/src/enclave.rs
+++ b/sgx_urts/src/enclave.rs
@@ -436,8 +436,8 @@ pub fn rsgx_create_enclave_with_workers(
     num_tworkers: u32,
 ) -> SgxResult<sgx_enclave_id_t> {
     let us_config = sgx_uswitchless_config_t {
-        num_tworkers,
-        num_uworkers,
+        num_tworkers: num_tworkers as u64,
+        num_uworkers: num_uworkers as u64,
         ..Default::default()
     };
     let mut enclave_ex_p: [*const c_void; 32] = [ptr::null(); 32];


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@teaclave.apache.org
For additional commands, e-mail: commits-help@teaclave.apache.org