@@ -658,6 +658,23 @@ static int sgx_get_key_hash(const void *modulus, void *hash)
return ret;
}
+static int __sgx_einit(struct sgx_sigstruct *sigstruct,
+ struct sgx_einittoken *token, struct sgx_epc_page *secs,
+ u64 *lepubkeyhash)
+{
+ int ret;
+
+ preempt_disable();
+ sgx_update_lepubkeyhash_msrs(lepubkeyhash, false);
+ ret = __einit(sigstruct, token, sgx_epc_addr(secs));
+ if (ret == SGX_INVALID_EINITTOKEN) {
+ sgx_update_lepubkeyhash_msrs(lepubkeyhash, true);
+ ret = __einit(sigstruct, token, sgx_epc_addr(secs));
+ }
+ preempt_enable();
+ return ret;
+}
+
static int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
struct sgx_einittoken *token)
{
@@ -686,8 +703,8 @@ static int sgx_encl_init(struct sgx_encl *encl, struct sgx_sigstruct *sigstruct,
for (i = 0; i < SGX_EINIT_SLEEP_COUNT; i++) {
for (j = 0; j < SGX_EINIT_SPIN_COUNT; j++) {
- ret = sgx_einit(sigstruct, token, encl->secs.epc_page,
- mrsigner);
+ ret = __sgx_einit(sigstruct, token,
+ encl->secs.epc_page, mrsigner);
if (ret == SGX_UNMASKED_EVENT)
continue;
else
@@ -166,7 +166,15 @@ void sgx_free_page(struct sgx_epc_page *page)
WARN(ret > 0, "sgx: EREMOVE returned %d (0x%x)", ret, ret);
}
-static void sgx_update_lepubkeyhash_msrs(u64 *lepubkeyhash, bool enforce)
+/**
+ * sgx_update_lepubkeyhash_msrs - Write the IA32_SGXLEPUBKEYHASHx MSRs
+ * @lepubkeyhash: array of desired MSRs values
+ * @enforce: force WRMSR regardless of cache status
+ *
+ * Write the IA32_SGXLEPUBKEYHASHx MSRs according to @lepubkeyhash if the
+ * last cached value doesn't match the desired value, or if @enforce is %true.
+ */
+void sgx_update_lepubkeyhash_msrs(u64 *lepubkeyhash, bool enforce)
{
u64 *cache;
int i;
@@ -180,39 +188,6 @@ static void sgx_update_lepubkeyhash_msrs(u64 *lepubkeyhash, bool enforce)
}
}
-/**
- * sgx_einit - initialize an enclave
- * @sigstruct: a pointer a SIGSTRUCT
- * @token: a pointer an EINITTOKEN (optional)
- * @secs: a pointer a SECS
- * @lepubkeyhash: the desired value for IA32_SGXLEPUBKEYHASHx MSRs
- *
- * Execute ENCLS[EINIT], writing the IA32_SGXLEPUBKEYHASHx MSRs according
- * to @lepubkeyhash (if possible and necessary).
- *
- * Return:
- * 0 on success,
- * -errno or SGX error on failure
- */
-int sgx_einit(struct sgx_sigstruct *sigstruct, struct sgx_einittoken *token,
- struct sgx_epc_page *secs, u64 *lepubkeyhash)
-{
- int ret;
-
- if (!boot_cpu_has(X86_FEATURE_SGX_LC))
- return __einit(sigstruct, token, sgx_epc_addr(secs));
-
- preempt_disable();
- sgx_update_lepubkeyhash_msrs(lepubkeyhash, false);
- ret = __einit(sigstruct, token, sgx_epc_addr(secs));
- if (ret == SGX_INVALID_EINITTOKEN) {
- sgx_update_lepubkeyhash_msrs(lepubkeyhash, true);
- ret = __einit(sigstruct, token, sgx_epc_addr(secs));
- }
- preempt_enable();
- return ret;
-}
-
static __init void sgx_free_epc_section(struct sgx_epc_section *section)
{
struct sgx_epc_page *page;
@@ -85,8 +85,8 @@ void sgx_reclaim_pages(void);
struct sgx_epc_page *sgx_alloc_page(void *owner, bool reclaim);
int __sgx_free_page(struct sgx_epc_page *page);
void sgx_free_page(struct sgx_epc_page *page);
-int sgx_einit(struct sgx_sigstruct *sigstruct, struct sgx_einittoken *token,
- struct sgx_epc_page *secs, u64 *lepubkeyhash);
+
+void sgx_update_lepubkeyhash_msrs(u64 *lepubkeyhash, bool enforce);
#define SGX_ENCL_DEV_MINOR 0
#define SGX_PROV_DEV_MINOR 1
Providing sgx_einit() in the common SGX code was a bit premature. The thought was that the native SGX driver and KVM would be able to use a common EINIT helper, but that may or may not hold true depending on how KVM's implementation shakes out. For example, KVM may want to pass user pointers directly to EINIT in order to avoid copying large amounts of data to in-kernel temp structures. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> --- arch/x86/kernel/cpu/sgx/driver/ioctl.c | 21 +++++++++++-- arch/x86/kernel/cpu/sgx/main.c | 43 ++++++-------------------- arch/x86/kernel/cpu/sgx/sgx.h | 4 +-- 3 files changed, 30 insertions(+), 38 deletions(-)