xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Boqun Feng <boqun.feng@intel.com>
To: xen-devel@lists.xen.org
Cc: "Kevin Tian" <kevin.tian@intel.com>,
	"Stefano Stabellini" <sstabellini@kernel.org>,
	"Wei Liu" <wei.liu2@citrix.com>,
	"Jun Nakajima" <jun.nakajima@intel.com>,
	"George Dunlap" <George.Dunlap@eu.citrix.com>,
	"Andrew Cooper" <andrew.cooper3@citrix.com>,
	"Ian Jackson" <ian.jackson@eu.citrix.com>,
	"Marek Marczykowski-Górecki" <marmarek@invisiblethingslab.com>,
	"Tim Deegan" <tim@xen.org>,
	kai.huang@linux.intel.com, "Julien Grall" <julien.grall@arm.com>,
	"Jan Beulich" <jbeulich@suse.com>,
	"David Scott" <dave@recoil.org>,
	"Boqun Feng" <boqun.feng@intel.com>
Subject: [PATCH v2 10/17] xen: x86: add SGX cpuid handling support.
Date: Mon,  4 Dec 2017 08:15:21 +0800	[thread overview]
Message-ID: <20171204001528.1342-11-boqun.feng@intel.com> (raw)
In-Reply-To: <20171204001528.1342-1-boqun.feng@intel.com>

From: Kai Huang <kai.huang@linux.intel.com>

This patch adds SGX to cpuid handling support. For SGX feature bit, it's
reported into raw_policy and passed along to a guest, but in
recalculate_cpu_policy(), we clear it if some one disabled SGX for some
reason. For EPC info, physical one is reported into raw_policy and
recalculated for *_policy. For a particular domain, it's EPC base and
size info will be filled by toolstack. 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>
Signed-off-by: Boqun Feng <boqun.feng@intel.com>
---
 xen/arch/x86/cpuid.c        | 62 ++++++++++++++++++++++++++++++++++++++++++++-
 xen/arch/x86/domctl.c       | 59 +++++++++++++++++++++++++++++++++++++++++-
 xen/include/asm-x86/cpuid.h | 29 ++++++++++++++++++++-
 3 files changed, 147 insertions(+), 3 deletions(-)

diff --git a/xen/arch/x86/cpuid.c b/xen/arch/x86/cpuid.c
index 5ee82d39d7cd..fcffbdec6bbe 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/sgx.h>
 
 const uint32_t known_features[] = INIT_KNOWN_FEATURES;
 const uint32_t special_features[] = INIT_SPECIAL_FEATURES;
@@ -152,6 +153,33 @@ static void recalculate_xstate(struct cpuid_policy *p)
     }
 }
 
+static void recalculate_sgx(struct cpuid_policy *p)
+{
+    if ( !p->feat.sgx || !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;
+    }
+}
+
 /*
  * Misc adjustments to the policy.  Mostly clobbering reserved fields and
  * duplicating shared fields.  Intentionally hidden fields are annotated.
@@ -233,7 +261,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;
         }
@@ -293,6 +321,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, 1, &p->sgx.raw[1]);
+        cpuid_count_leaf(SGX_CPUID, 2, &p->sgx.raw[2]);
+    }
+
     /* Extended leaves. */
     cpuid_leaf(0x80000000, &p->extd.raw[0]);
     for ( i = 1; i < min(ARRAY_SIZE(p->extd.raw),
@@ -318,6 +359,7 @@ static void __init calculate_host_policy(void)
     cpuid_featureset_to_policy(boot_cpu_data.x86_capability, p);
     recalculate_xstate(p);
     recalculate_misc(p);
+    recalculate_sgx(p);
 
     if ( p->extd.svm )
     {
@@ -351,6 +393,7 @@ static void __init calculate_pv_max_policy(void)
     sanitise_featureset(pv_featureset);
     cpuid_featureset_to_policy(pv_featureset, p);
     recalculate_xstate(p);
+    recalculate_sgx(p);
 
     p->extd.raw[0xa] = EMPTY_LEAF; /* No SVM for PV guests. */
 }
@@ -408,6 +451,7 @@ static void __init calculate_hvm_max_policy(void)
     sanitise_featureset(hvm_featureset);
     cpuid_featureset_to_policy(hvm_featureset, p);
     recalculate_xstate(p);
+    recalculate_sgx(p);
 }
 
 void __init init_guest_cpuid(void)
@@ -523,6 +567,14 @@ void recalculate_cpuid_policy(struct domain *d)
     if ( p->basic.max_leaf < XSTATE_CPUID )
         __clear_bit(X86_FEATURE_XSAVE, fs);
 
+    /*
+     * We check cpu_has_sgx here because during boot up SGX may be disabled
+     * via disable_sgx(), e.g. BIOS disables SGX by setting
+     * IA32_FEATURE_CONTROL_SGX_ENABLE=0
+     */
+    if ( p->basic.max_leaf < SGX_CPUID || !cpu_has_sgx )
+        __clear_bit(X86_FEATURE_SGX, fs);
+
     sanitise_featureset(fs);
 
     /* Fold host's FDP_EXCP_ONLY and NO_FPU_SEL into guest's view. */
@@ -545,6 +597,7 @@ void recalculate_cpuid_policy(struct domain *d)
 
     recalculate_xstate(p);
     recalculate_misc(p);
+    recalculate_sgx(p);
 
     for ( i = 0; i < ARRAY_SIZE(p->cache.raw); ++i )
     {
@@ -641,6 +694,13 @@ void guest_cpuid(const struct vcpu *v, uint32_t leaf,
             *res = p->xstate.raw[subleaf];
             break;
 
+        case SGX_CPUID:
+            if ( !p->feat.sgx || subleaf >= ARRAY_SIZE(p->sgx.raw) )
+                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 80b4df9ec95b..0ee9fb6458ec 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,11 @@ 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;
+
+        if ( ctl->input[0] == SGX_CPUID &&
+             ctl->input[1] >= ARRAY_SIZE(p->sgx.raw) )
+            return 0;
+
         break;
 
     case 0x40000000: case 0x40000100:
@@ -104,6 +110,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 +265,53 @@ static int update_domain_cpuid_info(struct domain *d,
         }
         break;
 
+    case 0x12:
+    {
+        uint64_t base_pfn, npages;
+        struct sgx_domain *sd;
+
+        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_high)) << 20) |
+            (uint64_t)p->sgx.base_low;
+        npages = (((uint64_t)(p->sgx.npages_high)) << 20) |
+            (uint64_t)p->sgx.npages_low;
+
+        sd = to_sgx(d);
+
+        if ( !sd )
+        {
+            ret = -EFAULT;
+            break;
+        }
+
+        if ( !domain_epc_populated(d) )
+            ret = domain_populate_epc(d, base_pfn, npages);
+        else
+            if ( base_pfn != sd->epc_base_pfn || npages != sd->epc_npages )
+                ret = -EINVAL;
+
+        break;
+    }
     case 0x80000001:
         if ( is_pv_domain(d) && ((levelling_caps & LCAP_e1cd) == LCAP_e1cd) )
         {
@@ -299,7 +356,7 @@ static int update_domain_cpuid_info(struct domain *d,
         break;
     }
 
-    return 0;
+    return ret;
 }
 
 static int vcpu_set_vmce(struct vcpu *v,
diff --git a/xen/include/asm-x86/cpuid.h b/xen/include/asm-x86/cpuid.h
index d2dd841e1581..6d043843713a 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,32 @@ struct cpuid_policy
         } comp[CPUID_GUEST_NR_XSTATE];
     } xstate;
 
+    union {
+        struct cpuid_leaf raw[CPUID_GUEST_NR_SGX];
+
+        struct {
+            /* Subleaf 0. */
+            bool sgx1:1, sgx2:1; uint32_t :30;
+            uint32_t miscselect;
+            uint32_t /* c */ :32;
+            uint8_t maxsize_legecy, maxsize_long; uint32_t :16; /* d */
+
+            /* Subleaf 1. */
+            bool init:1, debug:1, mode64:1, /*reserve*/:1, provisionkey:1,
+                     einittokenkey:1; uint32_t :26;
+            uint32_t /* SW reserved */ :32;
+            uint32_t xfrm_low, xfrm_high;
+
+            /* Subleaf 2. */
+            bool base_valid:1; uint32_t :11;
+            uint32_t base_low:20;
+            uint32_t base_high:20, :12;
+            bool size_valid:1; uint32_t :11;
+            uint32_t npages_low:20;
+            uint32_t npages_high:20, :12;
+        };
+    } sgx;
+
     /* Extended leaves: 0x800000xx */
     union {
         struct cpuid_leaf raw[CPUID_GUEST_NR_EXTD];
-- 
2.15.0


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

  parent reply	other threads:[~2017-12-04  0:15 UTC|newest]

Thread overview: 23+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-12-04  0:15 [RFC PATCH v2 00/17] RFC: SGX Virtualization design and draft patches Boqun Feng
2017-12-04  0:15 ` [PATCH v2 01/17] xen: x86: expose SGX to HVM domain in CPU featureset Boqun Feng
2017-12-04 11:13   ` Julien Grall
2017-12-04 13:10     ` Boqun Feng
2017-12-04 14:13       ` Jan Beulich
2017-12-05  0:22         ` Boqun Feng
2017-12-04  0:15 ` [PATCH v2 02/17] xen: x86: add early stage SGX feature detection Boqun Feng
2017-12-04  0:15 ` [PATCH v2 03/17] xen: vmx: detect ENCLS VMEXIT Boqun Feng
2017-12-04  0:15 ` [PATCH v2 04/17] xen: x86/mm: introduce ioremap_wb() Boqun Feng
2017-12-04  0:15 ` [PATCH v2 05/17] xen: p2m: new 'p2m_epc' type for EPC mapping Boqun Feng
2017-12-04  0:15 ` [PATCH v2 06/17] xen: mm: introduce non-scrubbable pages Boqun Feng
2017-12-04  0:15 ` [PATCH v2 07/17] xen: mm: manage EPC pages in Xen heaps Boqun Feng
2017-12-04  0:15 ` [PATCH v2 08/17] xen: x86/mm: add SGX EPC management Boqun Feng
2017-12-04  0:15 ` [PATCH v2 09/17] xen: x86: add functions to populate and destroy EPC for domain Boqun Feng
2017-12-04  0:15 ` Boqun Feng [this message]
2017-12-04  0:15 ` [PATCH v2 11/17] xen: vmx: handle SGX related MSRs Boqun Feng
2017-12-04  0:15 ` [PATCH v2 12/17] xen: vmx: handle ENCLS VMEXIT Boqun Feng
2017-12-04  0:15 ` [PATCH v2 13/17] xen: vmx: handle VMEXIT from SGX enclave Boqun Feng
2017-12-04  0:15 ` [PATCH v2 14/17] xen: x86: reset EPC when guest got suspended Boqun Feng
2017-12-04  0:15 ` [PATCH v2 15/17] xen: tools: add new 'sgx' parameter support Boqun Feng
2017-12-04  0:15 ` [PATCH v2 16/17] xen: tools: add SGX to applying CPUID policy Boqun Feng
2017-12-04  0:15 ` [PATCH v2 17/17] xen: tools: add SGX to applying MSR policy Boqun Feng
2017-12-25  5:01 ` [RFC PATCH v2 00/17] RFC: SGX Virtualization design and draft patches Boqun Feng

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=20171204001528.1342-11-boqun.feng@intel.com \
    --to=boqun.feng@intel.com \
    --cc=George.Dunlap@eu.citrix.com \
    --cc=andrew.cooper3@citrix.com \
    --cc=dave@recoil.org \
    --cc=ian.jackson@eu.citrix.com \
    --cc=jbeulich@suse.com \
    --cc=julien.grall@arm.com \
    --cc=jun.nakajima@intel.com \
    --cc=kai.huang@linux.intel.com \
    --cc=kevin.tian@intel.com \
    --cc=marmarek@invisiblethingslab.com \
    --cc=sstabellini@kernel.org \
    --cc=tim@xen.org \
    --cc=wei.liu2@citrix.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).