All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kai Huang <kaih.linux@gmail.com>
To: xen-devel@lists.xen.org
Cc: andrew.cooper3@citrix.com, jbeulich@suse.com
Subject: [PATCH 08/15] xen: x86: add SGX cpuid handling support.
Date: Sun,  9 Jul 2017 20:10:57 +1200	[thread overview]
Message-ID: <1ca2e437e21b0684518ff32dad292aa6080dcb11.1499586046.git.kai.huang@linux.intel.com> (raw)
In-Reply-To: <418c69fb675136a4768c3ef45521ad70131645c1.1499586046.git.kai.huang@linux.intel.com>
In-Reply-To: <cover.1499586046.git.kai.huang@linux.intel.com>

This patch adds SGX to cpuid handling support. In init_guest_cpuid, for
raw_policy and host_policy, physical EPC info is reported, but for pv_max_policy
and hvm_max_policy EPC is hidden, as for particular domain, it's EPC base and
size are from tookstack, and it is meaningless to contain physical EPC info in
them. Before domain's EPC base and size are properly configured, guest's SGX
cpuid should report invalid EPC, which is also consistent with HW behavior.

Currently all EPC pages are fully populated for domain when it is created.
Xen gets domain's EPC base and size from toolstack via XEN_DOMCTL_set_cpuid,
so domain's EPC pages are also populated in XEN_DOMCTL_set_cpuid, after
receiving valid EPC base and size. Failure to populate EPC (such as there's
no enough free EPC pages) results in domain creation failure by making
XEN_DOMCTL_set_cpuid return error.

Signed-off-by: Kai Huang <kai.huang@linux.intel.com>
---
 xen/arch/x86/cpuid.c        | 87 ++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/domctl.c       | 47 +++++++++++++++++++++++-
 xen/include/asm-x86/cpuid.h | 26 +++++++++++++-
 3 files changed, 157 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index d359e090f3..db896be2e8 100644
--- a/xen/arch/x86/cpuid.c
+++ b/xen/arch/x86/cpuid.c
@@ -9,6 +9,7 @@
 #include <asm/paging.h>
 #include <asm/processor.h>
 #include <asm/xstate.h>
+#include <asm/hvm/vmx/sgx.h>
 
 const uint32_t known_features[] = INIT_KNOWN_FEATURES;
 const uint32_t special_features[] = INIT_SPECIAL_FEATURES;
@@ -158,6 +159,44 @@ static void recalculate_xstate(struct cpuid_policy *p)
     }
 }
 
+static void recalculate_sgx(struct cpuid_policy *p, bool_t hide_epc)
+{
+    if ( !p->feat.sgx )
+    {
+        memset(&p->sgx, 0, sizeof (p->sgx));
+        return;
+    }
+
+    if ( !p->sgx.sgx1 )
+    {
+        memset(&p->sgx, 0, sizeof (p->sgx));
+        return;
+    }
+
+    /*
+     * SDM 42.7.2.1 SECS.ATTRIBUTE.XFRM:
+     *
+     * Legal value for SECS.ATTRIBUTE.XFRM conform to these requirements:
+     *  - XFRM[1:0] must be set to 0x3;
+     *  - If processor does not support XSAVE, or if the system software has not
+     *    enabled XSAVE, then XFRM[63:2] must be 0.
+     *  - If the processor does support XSAVE, XFRM must contain a value that
+     *    would be legal if loaded into XCR0.
+     */
+    p->sgx.xfrm_low = 0x3;
+    p->sgx.xfrm_high = 0;
+    if ( p->basic.xsave )
+    {
+        p->sgx.xfrm_low |= p->xstate.xcr0_low;
+        p->sgx.xfrm_high |= p->xstate.xcr0_high;
+    }
+
+    if ( hide_epc )
+    {
+        memset(&p->sgx.raw[0x2], 0, sizeof (struct cpuid_leaf));
+    }
+}
+
 /*
  * Misc adjustments to the policy.  Mostly clobbering reserved fields and
  * duplicating shared fields.  Intentionally hidden fields are annotated.
@@ -239,7 +278,7 @@ static void __init calculate_raw_policy(void)
     {
         switch ( i )
         {
-        case 0x4: case 0x7: case 0xd:
+        case 0x4: case 0x7: case 0xd: case 0x12:
             /* Multi-invocation leaves.  Deferred. */
             continue;
         }
@@ -299,6 +338,19 @@ static void __init calculate_raw_policy(void)
         }
     }
 
+    if ( p->basic.max_leaf >= SGX_CPUID )
+    {
+        /*
+         * For raw policy we just report native CPUID. For EPC on native it's
+         * possible that we will have multiple EPC sections (meaning subleaf 3,
+         * 4, ... may also be valid), but as the policy is for guest so we only
+         * need one EPC section (subleaf 2).
+         */
+        cpuid_count_leaf(SGX_CPUID, 0, &p->sgx.raw[0]);
+        cpuid_count_leaf(SGX_CPUID, 0, &p->sgx.raw[0]);
+        cpuid_count_leaf(SGX_CPUID, 0, &p->sgx.raw[0]);
+    }
+
     /* Extended leaves. */
     cpuid_leaf(0x80000000, &p->extd.raw[0]);
     for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
@@ -324,6 +376,8 @@ static void __init calculate_host_policy(void)
     cpuid_featureset_to_policy(boot_cpu_data.x86_capability, p);
     recalculate_xstate(p);
     recalculate_misc(p);
+    /* For host policy we report physical EPC */
+    recalculate_sgx(p, 0);
 
     if ( p->extd.svm )
     {
@@ -357,6 +411,11 @@ static void __init calculate_pv_max_policy(void)
     sanitise_featureset(pv_featureset);
     cpuid_featureset_to_policy(pv_featureset, p);
     recalculate_xstate(p);
+    /*
+     * For PV policy we don't report physical EPC. Actually for PV policy
+     * currently SGX will be disabled.
+     */
+    recalculate_sgx(p, 1);
 
     p->extd.raw[0xa] = EMPTY_LEAF; /* No SVM for PV guests. */
 }
@@ -413,6 +472,13 @@ static void __init calculate_hvm_max_policy(void)
     sanitise_featureset(hvm_featureset);
     cpuid_featureset_to_policy(hvm_featureset, p);
     recalculate_xstate(p);
+    /*
+     * For HVM policy we don't report physical EPC. Actually cpuid policy
+     * should report VM's virtual EPC base and size. However VM's virtual
+     * EPC info will come from toolstack, and only after Xen is notified
+     * VM's cpuid policy should report invalid EPC.
+     */
+    recalculate_sgx(p, 1);
 }
 
 void __init init_guest_cpuid(void)
@@ -528,6 +594,12 @@ void recalculate_cpuid_policy(struct domain *d)
     if ( p->basic.max_leaf < XSTATE_CPUID )
         __clear_bit(X86_FEATURE_XSAVE, fs);
 
+    if ( p->basic.max_leaf < SGX_CPUID )
+    {
+        __clear_bit(X86_FEATURE_SGX, fs);
+        __clear_bit(X86_FEATURE_SGX_LAUNCH_CONTROL, fs);
+    }
+
     sanitise_featureset(fs);
 
     /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
@@ -550,6 +622,12 @@ void recalculate_cpuid_policy(struct domain *d)
 
     recalculate_xstate(p);
     recalculate_misc(p);
+    /*
+     * recalculate_cpuid_policy is also called for domain's cpuid policy,
+     * which is from toolstack via XEN_DOMCTL_set_cpuid, therefore we cannot
+     * hide domain's virtual EPC from toolstack.
+     */
+    recalculate_sgx(p, 0);
 
     for ( i = 0; i < ARRAY_SIZE(p->cache.raw); ++i )
     {
@@ -645,6 +723,13 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
             *res = p->xstate.raw[subleaf];
             break;
 
+        case SGX_CPUID:
+            if ( !p->feat.sgx )
+                return;
+
+            *res = p->sgx.raw[subleaf];
+            break;
+
         default:
             *res = p->basic.raw[leaf];
             break;
diff --git a/xen/arch/x86/domctl.c b/xen/arch/x86/domctl.c
index f40e989fd8..7d49947a3e 100644
--- a/xen/arch/x86/domctl.c
+++ b/xen/arch/x86/domctl.c
@@ -53,6 +53,7 @@ static int update_domain_cpuid_info(struct domain *d,
     struct cpuid_policy *p = d->arch.cpuid;
     const struct cpuid_leaf leaf = { ctl->eax, ctl->ebx, ctl->ecx, ctl->edx };
     int old_vendor = p->x86_vendor;
+    int ret = 0;
 
     /*
      * Skip update for leaves we don't care about.  This avoids the overhead
@@ -74,6 +75,7 @@ static int update_domain_cpuid_info(struct domain *d,
         if ( ctl->input[0] == XSTATE_CPUID &&
              ctl->input[1] != 1 ) /* Everything else automatically calculated. */
             return 0;
+
         break;
 
     case 0x40000000: case 0x40000100:
@@ -104,6 +106,10 @@ static int update_domain_cpuid_info(struct domain *d,
             p->xstate.raw[ctl->input[1]] = leaf;
             break;
 
+        case SGX_CPUID:
+            p->sgx.raw[ctl->input[1]] = leaf;
+            break;
+
         default:
             p->basic.raw[ctl->input[0]] = leaf;
             break;
@@ -255,6 +261,45 @@ static int update_domain_cpuid_info(struct domain *d,
         }
         break;
 
+    case 0x12:
+    {
+        uint64_t base_pfn, npages;
+
+        if ( boot_cpu_data.x86_vendor != X86_VENDOR_INTEL )
+            break;
+
+        if ( ctl->input[1] != 2 )
+            break;
+
+        /* SGX has not enabled */
+        if ( !p->feat.sgx || !p->sgx.sgx1 )
+            break;
+
+        /*
+         * If SGX is enabled in CPUID, then we are expecting valid EPC resource
+         * in sub-leaf 0x2. Return -EFAULT to notify toolstack that there's
+         * something wrong.
+         */
+        if ( !p->sgx.base_valid || !p->sgx.size_valid )
+        {
+            ret = -EINVAL;
+            break;
+        }
+
+        base_pfn = (((uint64_t)(p->sgx.base_pfn_high)) << 20) |
+            (uint64_t)p->sgx.base_pfn_low;
+        npages = (((uint64_t)(p->sgx.npages_high)) << 20) |
+            (uint64_t)p->sgx.npages_low;
+
+        if ( !hvm_epc_populated(d) )
+            ret = hvm_populate_epc(d, base_pfn, npages);
+        else
+            if ( base_pfn != to_sgx(d)->epc_base_pfn ||
+                    npages != to_sgx(d)->epc_npages )
+                ret = -EINVAL;
+
+        break;
+    }
     case 0x80000001:
         if ( is_pv_domain(d) && ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) )
         {
@@ -299,7 +344,7 @@ static int update_domain_cpuid_info(struct domain *d,
         break;
     }
 
-    return 0;
+    return ret;
 }
 
 void arch_get_domain_info(const struct domain *d,
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index ac25908eca..326f267263 100644
--- a/xen/include/asm-x86/cpuid.h
+++ b/xen/include/asm-x86/cpuid.h
@@ -61,10 +61,11 @@ extern struct cpuidmasks cpuidmask_defaults;
 /* Whether or not cpuid faulting is available for the current domain. */
 DECLARE_PER_CPU(bool, cpuid_faulting_enabled);
 
-#define CPUID_GUEST_NR_BASIC      (0xdu + 1)
+#define CPUID_GUEST_NR_BASIC      (0x12u + 1)
 #define CPUID_GUEST_NR_FEAT       (0u + 1)
 #define CPUID_GUEST_NR_CACHE      (5u + 1)
 #define CPUID_GUEST_NR_XSTATE     (62u + 1)
+#define CPUID_GUEST_NR_SGX        (0x2u + 1)
 #define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
 #define CPUID_GUEST_NR_EXTD_AMD   (0x1cu + 1)
 #define CPUID_GUEST_NR_EXTD       MAX(CPUID_GUEST_NR_EXTD_INTEL, \
@@ -169,6 +170,29 @@ struct cpuid_policy
         } comp[CPUID_GUEST_NR_XSTATE];
     } xstate;
 
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_SGX];
+
+        struct {
+            /* Subleaf 0. */
+            uint32_t sgx1:1, sgx2:1, :30;
+            uint32_t miscselect, /* c */ :32;
+            uint32_t maxenclavesize_n64:8, maxenclavesize_64:8, :16;
+
+            /* Subleaf 1. */
+            uint32_t init:1, debug:1, mode64:1, /*reserve*/:1, provisionkey:1,
+                     einittokenkey:1, :26;
+            uint32_t /* reserve */:32;
+            uint32_t xfrm_low, xfrm_high;
+
+            /* Subleaf 2. */
+            uint32_t base_valid:1, :11, base_pfn_low:20;
+            uint32_t base_pfn_high:20, :12;
+            uint32_t size_valid:1, :11, npages_low:20;
+            uint32_t npages_high:20, :12;
+        };
+    } sgx;
+
     /* Extended leaves: 0x800000xx */
     union {
         struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
-- 
2.11.0


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

  parent reply	other threads:[~2017-07-09  8:10 UTC|newest]

Thread overview: 58+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-07-09  8:03 [RFC PATCH 00/15] RFC: SGX virtualization design and draft patches Kai Huang
2017-07-09  8:04 ` [PATCH 01/15] xen: x86: expose SGX to HVM domain in CPU featureset Kai Huang
2017-07-12 11:09   ` Andrew Cooper
2017-07-17  6:20     ` Huang, Kai
2017-07-18 10:12   ` Andrew Cooper
2017-07-18 22:41     ` Huang, Kai
2017-07-09  8:09 ` [PATCH 02/15] xen: vmx: detect ENCLS VMEXIT Kai Huang
2017-07-12 11:11   ` Andrew Cooper
2017-07-12 18:54     ` Jan Beulich
2017-07-13  4:57       ` Huang, Kai
2017-07-09  8:09 ` [PATCH 03/15] xen: x86: add early stage SGX feature detection Kai Huang
2017-07-19 14:23   ` Andrew Cooper
2017-07-21  9:17     ` Huang, Kai
2017-07-22  1:06       ` Huang, Kai
2017-07-09  8:09 ` [PATCH 06/15] xen: x86: add SGX basic EPC management Kai Huang
2017-07-09  8:09 ` [PATCH 07/15] xen: x86: add functions to populate and destroy EPC for domain Kai Huang
2017-07-09  8:09 ` [PATCH 09/15] xen: vmx: handle SGX related MSRs Kai Huang
2017-07-19 17:27   ` Andrew Cooper
2017-07-21  9:42     ` Huang, Kai
2017-07-22  1:37       ` Huang, Kai
2017-07-09  8:09 ` [PATCH 10/15] xen: vmx: handle ENCLS VMEXIT Kai Huang
2017-07-09  8:09 ` [PATCH 11/15] xen: vmx: handle VMEXIT from SGX enclave Kai Huang
2017-07-09  8:09 ` [PATCH 12/15] xen: x86: reset EPC when guest got suspended Kai Huang
2017-07-09  8:10 ` [PATCH 04/15] xen: mm: add ioremap_cache Kai Huang
2017-07-11 20:14   ` Julien Grall
2017-07-12  1:52     ` Huang, Kai
2017-07-12  7:13       ` Julien Grall
2017-07-13  5:01         ` Huang, Kai
2017-07-12  6:17     ` Jan Beulich
2017-07-13  4:59       ` Huang, Kai
2017-07-09  8:10 ` Kai Huang [this message]
2017-07-12 10:56   ` [PATCH 08/15] xen: x86: add SGX cpuid handling support Andrew Cooper
2017-07-13  5:42     ` Huang, Kai
2017-07-14  7:37       ` Andrew Cooper
2017-07-14 11:08         ` Jan Beulich
2017-07-17  6:16         ` Huang, Kai
2017-07-09  8:12 ` [PATCH 05/15] xen: p2m: new 'p2m_epc' type for EPC mapping Kai Huang
2017-07-12 11:01   ` Andrew Cooper
2017-07-12 12:21     ` George Dunlap
2017-07-13  5:56       ` Huang, Kai
2017-07-09  8:14 ` [PATCH 13/15] xen: tools: add new 'epc' parameter support Kai Huang
2017-07-09  8:15 ` [PATCH 14/15] xen: tools: add SGX to applying CPUID policy Kai Huang
2017-07-09  8:16 ` [PATCH 15/15] xen: tools: expose EPC in ACPI table Kai Huang
2017-07-12 11:05   ` Andrew Cooper
2017-07-13  8:23     ` Huang, Kai
2017-07-14 11:31   ` Jan Beulich
2017-07-17  6:11     ` Huang, Kai
2017-07-17 10:54   ` Roger Pau Monné
2017-07-18  8:36     ` Huang, Kai
2017-07-18 10:21       ` Roger Pau Monné
2017-07-18 22:44         ` Huang, Kai
2017-07-11 14:13 ` [RFC PATCH 00/15] RFC: SGX virtualization design and draft patches Andrew Cooper
2017-07-17  6:08   ` Huang, Kai
2017-07-21  9:04     ` Huang, Kai
2017-07-17  9:16 ` Wei Liu
2017-07-18  8:22   ` Huang, Kai
2017-07-28 13:40     ` Wei Liu
2017-07-31  8:37       ` Huang, Kai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1ca2e437e21b0684518ff32dad292aa6080dcb11.1499586046.git.kai.huang@linux.intel.com \
    --to=kaih.linux@gmail.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=jbeulich@suse.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.