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

[Xen-devel] [PATCH 14/15] xen: tools: add SGX to applying CPUID policy



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       | 10 ++++++
 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, 117 insertions(+), 11 deletions(-)

diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
index 1629f412dd..b621b35dea 100644
--- a/tools/libxc/include/xenctrl.h
+++ b/tools/libxc/include/xenctrl.h
@@ -1783,6 +1783,15 @@ 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,
@@ -1794,6 +1803,7 @@ int xc_cpuid_set(xc_interface *xch,
                  char **config_transformed);
 int xc_cpuid_apply_policy(xc_interface *xch,
                           domid_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 1bedf050b8..b7eb652db9 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, domid_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, domid_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, domid_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, domid_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 cf8687aa7e..dad72bf277 100644
--- a/tools/libxl/libxl.h
+++ b/tools/libxl/libxl.h
@@ -1949,7 +1949,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 24591e2461..550258bdf4 100644
--- a/tools/libxl/libxl_cpuid.c
+++ b/tools/libxl/libxl_cpuid.c
@@ -332,9 +332,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 6d1d51d35d..9d05d2813e 100644
--- a/tools/libxl/libxl_dom.c
+++ b/tools/libxl/libxl_dom.c
@@ -535,7 +535,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 ef1161c434..70e0486e98 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 5e455519d4..34f90bc630 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 5d112af6e0..a3e753589e 100644
--- a/tools/python/xen/lowlevel/xc/xc.c
+++ b/tools/python/xen/lowlevel/xc/xc.c
@@ -742,7 +742,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.11.0


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

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