[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH v2 16/17] xen: tools: add SGX to applying CPUID policy



From: Kai Huang <kai.huang@xxxxxxxxxxxxxxx>

In libxc, a new structure 'xc_cpuid_policy_build_info_t' is added to carry
domain's EPC base and size info from libxl. libxl_cpuid_apply_policy is also
changed to take 'libxl_domain_build_info_t' as parameter, where domain's EPC
base and size can be got and passed to xc_cpuid_apply_policy.
xc_cpuid_apply_policy is extended to support SGX CPUID. If hypervisor doesn't
report SGX feature in host type cpufeatureset, then using 'epc' parameter
results in domain creation failure as SGX cannot be supported.

Signed-off-by: Kai Huang <kai.huang@xxxxxxxxxxxxxxx>
---
 tools/libxc/include/xenctrl.h       | 14 ++++++++
 tools/libxc/xc_cpuid_x86.c          | 68 ++++++++++++++++++++++++++++++++++---
 tools/libxl/libxl.h                 |  3 +-
 tools/libxl/libxl_cpuid.c           | 15 ++++++--
 tools/libxl/libxl_dom.c             |  6 +++-
 tools/libxl/libxl_nocpuid.c         |  4 ++-
 tools/ocaml/libs/xc/xenctrl_stubs.c | 11 +++++-
 tools/python/xen/lowlevel/xc/xc.c   | 11 +++++-
 8 files changed, 121 insertions(+), 11 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 666db0b9193e..ad4429ca5ffd 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1827,6 +1827,19 @@ int xc_domain_debug_control(xc_interface *xch,
                             uint32_t vcpu);
 
 #if defined(__i386__) || defined(__x86_64__)
+typedef struct xc_cpuid_policy_build_info_sgx {
+    uint64_t epc_base;
+    uint64_t epc_size;
+} xc_cpuid_policy_build_info_sgx_t;
+
+typedef struct xc_cpuid_policy_build_info {
+    xc_cpuid_policy_build_info_sgx_t sgx;
+} xc_cpuid_policy_build_info_t;
+
+int xc_cpuid_check(xc_interface *xch,
+                   const unsigned int *input,
+                   const char **config,
+                   char **config_transformed);
 int xc_cpuid_set(xc_interface *xch,
                  uint32_t domid,
                  const unsigned int *input,
@@ -1834,6 +1847,7 @@ int xc_cpuid_set(xc_interface *xch,
                  char **config_transformed);
 int xc_cpuid_apply_policy(xc_interface *xch,
                           uint32_t domid,
+                          xc_cpuid_policy_build_info_t *b_info,
                           uint32_t *featureset,
                           unsigned int nr_features);
 void xc_cpuid_to_str(const unsigned int *regs,
diff --git a/tools/libxc/xc_cpuid_x86.c b/tools/libxc/xc_cpuid_x86.c
index 25b922ea2184..a778acf79a64 100644
--- a/tools/libxc/xc_cpuid_x86.c
+++ b/tools/libxc/xc_cpuid_x86.c
@@ -38,7 +38,7 @@ enum {
 #define clear_feature(idx, dst) ((dst) &= ~bitmaskof(idx))
 #define set_feature(idx, dst)   ((dst) |=  bitmaskof(idx))
 
-#define DEF_MAX_BASE 0x0000000du
+#define DEF_MAX_BASE 0x00000012u
 #define DEF_MAX_INTELEXT  0x80000008u
 #define DEF_MAX_AMDEXT    0x8000001cu
 
@@ -178,6 +178,8 @@ struct cpuid_domain_info
     /* HVM-only information. */
     bool pae;
     bool nestedhvm;
+
+    xc_cpuid_policy_build_info_t *b_info;
 };
 
 static void cpuid(const unsigned int *input, unsigned int *regs)
@@ -369,6 +371,12 @@ static void intel_xc_cpuid_policy(xc_interface *xch,
                                   const struct cpuid_domain_info *info,
                                   const unsigned int *input, unsigned int 
*regs)
 {
+    xc_cpuid_policy_build_info_t *b_info = info->b_info;
+    xc_cpuid_policy_build_info_sgx_t *sgx = NULL;
+
+    if ( b_info )
+        sgx = &b_info->sgx;
+
     switch ( input[0] )
     {
     case 0x00000004:
@@ -381,6 +389,30 @@ static void intel_xc_cpuid_policy(xc_interface *xch,
         regs[3] &= 0x3ffu;
         break;
 
+    case 0x00000012:
+        if ( !sgx ) {
+            regs[0] = regs[1] = regs[2] = regs[3] = 0;
+            break;
+        }
+
+        if ( !sgx->epc_base || !sgx->epc_size ) {
+            regs[0] = regs[1] = regs[2] = regs[3] = 0;
+            break;
+        }
+
+        if ( input[1] == 2 ) {
+            /*
+             * FIX EPC base and size for SGX CPUID leaf 2. Xen hypervisor is
+             * depending on XEN_DOMCTL_set_cpuid to know domain's EPC base
+             * and size.
+             */
+            regs[0] = (uint32_t)(sgx->epc_base & 0xfffff000) | 0x1;
+            regs[1] = (uint32_t)(sgx->epc_base >> 32);
+            regs[2] = (uint32_t)(sgx->epc_size & 0xfffff000) | 0x1;
+            regs[3] = (uint32_t)(sgx->epc_size >> 32);
+        }
+        break;
+
     case 0x80000000:
         if ( regs[0] > DEF_MAX_INTELEXT )
             regs[0] = DEF_MAX_INTELEXT;
@@ -444,6 +476,10 @@ static void xc_cpuid_hvm_policy(xc_interface *xch,
         regs[1] = regs[2] = regs[3] = 0;
         break;
 
+    case 0x00000012:
+        /* Intel SGX. Passthrough to Intel function */
+        break;
+
     case 0x80000000:
         /* Passthrough to cpu vendor specific functions */
         break;
@@ -649,12 +685,13 @@ void xc_cpuid_to_str(const unsigned int *regs, char 
**strs)
     }
 }
 
-static void sanitise_featureset(struct cpuid_domain_info *info)
+static int sanitise_featureset(struct cpuid_domain_info *info)
 {
     const uint32_t fs_size = xc_get_cpu_featureset_size();
     uint32_t disabled_features[fs_size];
     static const uint32_t deep_features[] = INIT_DEEP_FEATURES;
     unsigned int i, b;
+    xc_cpuid_policy_build_info_t *b_info = info->b_info;
 
     if ( info->hvm )
     {
@@ -707,9 +744,19 @@ static void sanitise_featureset(struct cpuid_domain_info 
*info)
             disabled_features[i] &= ~dfs[i];
         }
     }
+
+    /* Cannot support 'epc' parameter if SGX is unavailable */
+    if ( b_info && b_info->sgx.epc_base && b_info->sgx.epc_size )
+        if (!test_bit(X86_FEATURE_SGX, info->featureset)) {
+            printf("Xen hypervisor doesn't support SGX.\n");
+            return -EFAULT;
+        }
+
+    return 0;
 }
 
 int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid,
+                          xc_cpuid_policy_build_info_t *b_info,
                           uint32_t *featureset,
                           unsigned int nr_features)
 {
@@ -722,6 +769,8 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid,
     if ( rc )
         goto out;
 
+    info.b_info = b_info;
+
     cpuid(input, regs);
     base_max = (regs[0] <= DEF_MAX_BASE) ? regs[0] : DEF_MAX_BASE;
     input[0] = 0x80000000;
@@ -732,7 +781,9 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid,
     else
         ext_max = (regs[0] <= DEF_MAX_INTELEXT) ? regs[0] : DEF_MAX_INTELEXT;
 
-    sanitise_featureset(&info);
+    rc = sanitise_featureset(&info);
+    if ( rc )
+        goto out;
 
     input[0] = 0;
     input[1] = XEN_CPUID_INPUT_UNUSED;
@@ -757,12 +808,21 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t 
domid,
                 continue;
         }
 
+        /* Intel SGX */
+        if ( input[0] == 0x12 )
+        {
+            input[1]++;
+            /* Intel SGX has 3 leaves */
+            if ( input[1] < 3 )
+                continue;
+        }
+
         input[0]++;
         if ( !(input[0] & 0x80000000u) && (input[0] > base_max ) )
             input[0] = 0x80000000u;
 
         input[1] = XEN_CPUID_INPUT_UNUSED;
-        if ( (input[0] == 4) || (input[0] == 7) )
+        if ( (input[0] == 4) || (input[0] == 7) || input[0] == 0x12)
             input[1] = 0;
         else if ( input[0] == 0xd )
             input[1] = 1; /* Xen automatically calculates almost everything. */
diff --git a/tools/libxl/libxl.h b/tools/libxl/libxl.h
index 5e9aed739d7a..1a8a1d786ceb 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -2049,7 +2049,8 @@ libxl_device_pci 
*libxl_device_pci_assignable_list(libxl_ctx *ctx, int *num);
 int libxl_cpuid_parse_config(libxl_cpuid_policy_list *cpuid, const char* str);
 int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list *cpuid,
                                   const char* str);
-void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid);
+int libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_domain_build_info *info);
 void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
                      libxl_cpuid_policy_list cpuid);
 
diff --git a/tools/libxl/libxl_cpuid.c b/tools/libxl/libxl_cpuid.c
index e692b6156979..5fb74322b99a 100644
--- a/tools/libxl/libxl_cpuid.c
+++ b/tools/libxl/libxl_cpuid.c
@@ -386,9 +386,20 @@ int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list 
*cpuid,
     return 0;
 }
 
-void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid)
+int libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_domain_build_info *info)
 {
-    xc_cpuid_apply_policy(ctx->xch, domid, NULL, 0);
+    xc_cpuid_policy_build_info_t cpuid_binfo;
+
+    memset(&cpuid_binfo, 0, sizeof (xc_cpuid_policy_build_info_t));
+
+    /* Currently only Intel SGX needs info when applying CPUID policy */
+    if (info->type == LIBXL_DOMAIN_TYPE_HVM) {
+        cpuid_binfo.sgx.epc_base = info->u.hvm.sgx.epcbase;
+        cpuid_binfo.sgx.epc_size = (info->u.hvm.sgx.epckb << 10);
+    }
+
+    return xc_cpuid_apply_policy(ctx->xch, domid, &cpuid_binfo, NULL, 0);
 }
 
 void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
diff --git a/tools/libxl/libxl_dom.c b/tools/libxl/libxl_dom.c
index bbdba7e6e292..ac38ad65dd19 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -597,7 +597,11 @@ int libxl__build_post(libxl__gc *gc, uint32_t domid,
         return ERROR_FAIL;
     }
 
-    libxl_cpuid_apply_policy(ctx, domid);
+    rc = libxl_cpuid_apply_policy(ctx, domid, info);
+    if (rc) {
+        LOG(ERROR, "Failed to apply CPUID policy (%d)", rc);
+        return ERROR_FAIL;
+    }
     if (info->cpuid != NULL)
         libxl_cpuid_set(ctx, domid, info->cpuid);
 
diff --git a/tools/libxl/libxl_nocpuid.c b/tools/libxl/libxl_nocpuid.c
index ef1161c4342b..70e0486e981b 100644
--- a/tools/libxl/libxl_nocpuid.c
+++ b/tools/libxl/libxl_nocpuid.c
@@ -34,8 +34,10 @@ int libxl_cpuid_parse_config_xend(libxl_cpuid_policy_list 
*cpuid,
     return 0;
 }
 
-void libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid)
+int libxl_cpuid_apply_policy(libxl_ctx *ctx, uint32_t domid,
+                             libxl_domain_build_info *info)
 {
+    return 0;
 }
 
 void libxl_cpuid_set(libxl_ctx *ctx, uint32_t domid,
diff --git a/tools/ocaml/libs/xc/xenctrl_stubs.c 
b/tools/ocaml/libs/xc/xenctrl_stubs.c
index c66732f67c89..4c469dd22f6e 100644
--- a/tools/ocaml/libs/xc/xenctrl_stubs.c
+++ b/tools/ocaml/libs/xc/xenctrl_stubs.c
@@ -796,7 +796,16 @@ CAMLprim value stub_xc_domain_cpuid_apply_policy(value 
xch, value domid)
 #if defined(__i386__) || defined(__x86_64__)
        int r;
 
-       r = xc_cpuid_apply_policy(_H(xch), _D(domid), NULL, 0);
+    /*
+     * FIXME:
+     *
+     * Don't support passing SGX info to xc_cpuid_apply_policy here. To be
+     * honest I don't know the purpose of this CAML function, so I don't
+     * know whether we need to allow *caller* of this function to pass SGX
+     * info. As EPC base is calculated internally by toolstack so I think
+     * it is also impossible to pass EPC base from *user*.
+     */
+       r = xc_cpuid_apply_policy(_H(xch), _D(domid), NULL, NULL, 0);
        if (r < 0)
                failwith_xc(_H(xch));
 #else
diff --git a/tools/python/xen/lowlevel/xc/xc.c 
b/tools/python/xen/lowlevel/xc/xc.c
index f501764100ad..bdecd0466a9a 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -719,7 +719,16 @@ static PyObject *pyxc_dom_set_policy_cpuid(XcObject *self,
     if ( !PyArg_ParseTuple(args, "i", &domid) )
         return NULL;
 
-    if ( xc_cpuid_apply_policy(self->xc_handle, domid, NULL, 0) )
+    /*
+     * FIXME:
+     *
+     * Don't support passing SGX info to xc_cpuid_apply_policy here. To be
+     * honest I don't know the purpose of this python function, so I don't
+     * know whether we need to allow *caller* of this function to pass SGX
+     * info. As EPC base is calculated internally by toolstack so I think
+     * it is also impossible to pass EPC base from *user*.
+     */
+    if ( xc_cpuid_apply_policy(self->xc_handle, domid, NULL, NULL, 0) )
         return pyxc_error_to_exception(self->xc_handle);
 
     Py_INCREF(zero);
-- 
2.15.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxxx
https://lists.xenproject.org/mailman/listinfo/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.