Browse Source

[Pal/Linux-SGX] Change manifest option sgx.enable_[avx|avx512|mpx] to sgx.require_[avx|avx512|mpx]

This commit allows setting the AVX, AVX512, and MPX bits in SIGSTRUCT.xfrms
dynamically unless the features are specifically enabled in the manifest via
sgx.require_[avx|avx512|mpx]=1 options. If the bits are set in SIGSTRUCT.xfrms
but the CPU feature(s) are not available on the platform, the enclave
initialization (EINIT) should fail. In addition, the xfrms and xfrmmask fields
in the EINITTOKEN must match with SIGSTRUCT.
Chia-Che Tsai 4 years ago
parent
commit
c8a352553b

+ 12 - 0
Documentation/oldwiki/Graphene-SGX-Manifest-Syntax.md

@@ -32,6 +32,18 @@ threads are destroyed).
 This syntax specifies whether the enclave can be debugged. Set it to 1 for a debug enclave and to 0
 for a production enclave.
 
+### Optional CPU features (AVX, AVX512, MPX)
+
+    sgx.require_avx=[1|0]
+    sgx.require_avx512=[1|0]
+    sgx.require_mpx=[1|0]
+    (Default: 0)
+
+This syntax ensures that the CPU features are available and enabled for the enclave. If the options
+are set in the manifest but the features are unavailable on the platform, enclave initialization
+should fail. If the options are unset, enclave initialization should succeed even if these features
+are unavailable on the platform.
+
 ### ISV Product ID and SVN
 
     sgx.isvprodid=[NUM]

+ 2 - 7
Pal/regression/AvxDisable.c

@@ -13,12 +13,7 @@ int main() {
     __m256 result = _mm256_sub_ps(evens, odds);
 
     /* Display the elements of the result vector */
-    float f = result[0];
-
-    PAL_HANDLE file1 = DkStreamOpen("file:avxRes", PAL_ACCESS_RDWR, 0, 0, 0);
-    if (file1) {
-        DkStreamWrite(file1, 0, sizeof(f), &f, NULL);
-        DkObjectClose(file1);
-    }
+    pal_printf("Result: %d %d %d %d %d %d %d %d\n", (int)result[0], (int)result[1], (int)result[2],
+               (int)result[3], (int)result[4], (int)result[5], (int)result[6], (int)result[7]);
     return 1;
 }

+ 0 - 5
Pal/src/host/Linux-SGX/sgx_framework.c

@@ -159,11 +159,6 @@ int create_enclave(sgx_arch_secs_t * secs,
     secs->misc_select = token->masked_misc_select_le;
     memcpy(&secs->attributes, &token->body.attributes, sizeof(sgx_attributes_t));
 
-    // Enable AVX and AVX512
-    // [2019-09-18] TODO(dep): This alone is not enough to get the fully optional behavior we will want.
-    // Leave this here for future work in another PR
-    // secs->attributes.xfrm |= SGX_XFRM_AVX;
-
     /* Do not initialize secs->mr_signer and secs->mr_enclave here as they are
      * not used by ECREATE to populate the internal SECS. SECS's mr_enclave is
      * computed dynamically and SECS's mr_signer is populated based on the

+ 33 - 0
Pal/src/host/Linux-SGX/signer/pal-sgx-get-token

@@ -11,6 +11,38 @@ import aesm_pb2
 sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
 from generated_offsets import *
 
+def set_optional_sgx_features(attr):
+    """Set optional SGX features if they are available on this machine."""
+    optional_sgx_features = {
+        SGX_XFRM_AVX:      "avx",
+        SGX_XFRM_AVX512:   "avx512f",
+        SGX_XFRM_MPX:      "mpx",
+    }
+
+    cpu_features = ""
+    with open("/proc/cpuinfo", "r") as f:
+        for line in f:
+            if line.startswith("flags"):
+                cpu_features = line.split(":")[1].strip().split()
+                break
+        else:
+            raise Exception("Failed to parse CPU flags")
+
+    xfrms    = int.from_bytes(attr['xfrms'], byteorder='little')
+    xfrmmask = int.from_bytes(attr['xfrm_mask'], byteorder='little')
+
+    new_xfrms = 0
+    for (bits, feature) in optional_sgx_features.items():
+        # Check if SIGSTRUCT allows enabling an optional CPU feature.
+        # If all the xfrm bits for a feature, after applying xfrmmask, are set in xfrms,
+        # we can set the remaining bits if the feature is available.
+        # If the xfrmmask includes all the required xfrm bits, then these bits cannot be
+        # changed in xfrm (need to stay the same as signed).
+        if xfrms & (bits & xfrmmask) == (bits & xfrmmask) and feature in cpu_features:
+            new_xfrms |= xfrms | bits
+
+    attr['xfrms'] = new_xfrms.to_bytes(length=8, byteorder='little')
+
 
 def read_sigstruct(sig):
     """Reading Sigstruct."""
@@ -97,6 +129,7 @@ def main(args=None):
     args = argparser.parse_args(args)
 
     attr = read_sigstruct(args.sig.read())
+    set_optional_sgx_features(attr)
 
     print("Attributes:")
     print("    mr_enclave:  %s" % attr['enclave_hash'].hex())

+ 1 - 1
Pal/src/host/Linux-SGX/signer/pal-sgx-sign

@@ -170,7 +170,7 @@ def get_enclave_attributes(manifest):
         'debug': 'FLAG_DEBUG',
         'require_avx': 'XFRM_AVX',
         'require_avx512': 'XFRM_AVX512',
-        'enable_mpx': 'XFRM_MPX',
+        'require_mpx': 'XFRM_MPX',
         'support_exinfo': 'MISC_EXINFO',
     }