Commit 2da68a77 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull x86 sgx updates from Dave Hansen:
 "The biggest deal in this series is support for a new hardware feature
  that allows enclaves to detect and mitigate single-stepping attacks.

  There's also a minor performance tweak and a little piece of the
  kmap_atomic() -> kmap_local() transition.

  Summary:

   - Introduce a new SGX feature (Asynchrounous Exit Notification) for
     bare-metal enclaves and KVM guests to mitigate single-step attacks

   - Increase batching to speed up enclave release

   - Replace kmap/kunmap_atomic() calls"

* tag 'x86_sgx_for_6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/sgx: Replace kmap/kunmap_atomic() calls
  KVM/VMX: Allow exposing EDECCSSA user leaf function to KVM guest
  x86/sgx: Allow enclaves to use Asynchrounous Exit Notification
  x86/sgx: Reduce delay and interference of enclave release
parents c1f0fcd8 89e927bb
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -304,6 +304,7 @@
#define X86_FEATURE_UNRET		(11*32+15) /* "" AMD BTB untrain return */
#define X86_FEATURE_USE_IBPB_FW		(11*32+16) /* "" Use IBPB during runtime firmware calls */
#define X86_FEATURE_RSB_VMEXIT_LITE	(11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
#define X86_FEATURE_SGX_EDECCSSA	(11*32+18) /* "" SGX EDECCSSA user leaf function */


#define X86_FEATURE_MSR_TSX_CTRL	(11*32+20) /* "" MSR IA32_TSX_CTRL (Intel) implemented */
+26 −7
Original line number Diff line number Diff line
@@ -115,17 +115,36 @@ enum sgx_miscselect {
 * %SGX_ATTR_EINITTOKENKEY:	Allow to use token signing key that is used to
 *				sign cryptographic tokens that can be passed to
 *				EINIT as an authorization to run an enclave.
 * %SGX_ATTR_ASYNC_EXIT_NOTIFY:	Allow enclaves to be notified after an
 *				asynchronous exit has occurred.
 */
enum sgx_attribute {
	SGX_ATTR_INIT		   = BIT(0),
	SGX_ATTR_DEBUG		   = BIT(1),
	SGX_ATTR_MODE64BIT	   = BIT(2),
				  /* BIT(3) is reserved */
	SGX_ATTR_PROVISIONKEY	   = BIT(4),
	SGX_ATTR_EINITTOKENKEY	   = BIT(5),
				  /* BIT(6) is for CET */
	SGX_ATTR_KSS		   = BIT(7),
				  /* BIT(8) is reserved */
				  /* BIT(9) is reserved */
	SGX_ATTR_ASYNC_EXIT_NOTIFY = BIT(10),
};

#define SGX_ATTR_RESERVED_MASK	(BIT_ULL(3) | BIT_ULL(6) | GENMASK_ULL(63, 8))
#define SGX_ATTR_RESERVED_MASK	(BIT_ULL(3) | \
				 BIT_ULL(6) | \
				 BIT_ULL(8) | \
				 BIT_ULL(9) | \
				 GENMASK_ULL(63, 11))

#define SGX_ATTR_UNPRIV_MASK	(SGX_ATTR_DEBUG	    | \
				 SGX_ATTR_MODE64BIT | \
				 SGX_ATTR_KSS	    | \
				 SGX_ATTR_ASYNC_EXIT_NOTIFY)

#define SGX_ATTR_PRIV_MASK	(SGX_ATTR_PROVISIONKEY	| \
				 SGX_ATTR_EINITTOKENKEY)

/**
 * struct sgx_secs - SGX Enclave Control Structure (SECS)
+1 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ static const struct cpuid_dep cpuid_deps[] = {
	{ X86_FEATURE_SGX_LC,			X86_FEATURE_SGX	      },
	{ X86_FEATURE_SGX1,			X86_FEATURE_SGX       },
	{ X86_FEATURE_SGX2,			X86_FEATURE_SGX1      },
	{ X86_FEATURE_SGX_EDECCSSA,		X86_FEATURE_SGX1      },
	{ X86_FEATURE_XFD,			X86_FEATURE_XSAVES    },
	{ X86_FEATURE_XFD,			X86_FEATURE_XGETBV1   },
	{ X86_FEATURE_AMX_TILE,			X86_FEATURE_XFD       },
+1 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ static const struct cpuid_bit cpuid_bits[] = {
	{ X86_FEATURE_PER_THREAD_MBA,	CPUID_ECX,  0, 0x00000010, 3 },
	{ X86_FEATURE_SGX1,		CPUID_EAX,  0, 0x00000012, 0 },
	{ X86_FEATURE_SGX2,		CPUID_EAX,  1, 0x00000012, 0 },
	{ X86_FEATURE_SGX_EDECCSSA,	CPUID_EAX, 11, 0x00000012, 0 },
	{ X86_FEATURE_HW_PSTATE,	CPUID_EDX,  7, 0x80000007, 0 },
	{ X86_FEATURE_CPB,		CPUID_EDX,  9, 0x80000007, 0 },
	{ X86_FEATURE_PROC_FEEDBACK,    CPUID_EDX, 11, 0x80000007, 0 },
+25 −10
Original line number Diff line number Diff line
@@ -160,8 +160,8 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
		return ret;

	pginfo.addr = encl_page->desc & PAGE_MASK;
	pginfo.contents = (unsigned long)kmap_atomic(b.contents);
	pcmd_page = kmap_atomic(b.pcmd);
	pginfo.contents = (unsigned long)kmap_local_page(b.contents);
	pcmd_page = kmap_local_page(b.pcmd);
	pginfo.metadata = (unsigned long)pcmd_page + b.pcmd_offset;

	if (secs_page)
@@ -187,8 +187,8 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
	 */
	pcmd_page_empty = !memchr_inv(pcmd_page, 0, PAGE_SIZE);

	kunmap_atomic(pcmd_page);
	kunmap_atomic((void *)(unsigned long)pginfo.contents);
	kunmap_local(pcmd_page);
	kunmap_local((void *)(unsigned long)pginfo.contents);

	get_page(b.pcmd);
	sgx_encl_put_backing(&b);
@@ -197,10 +197,10 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,

	if (pcmd_page_empty && !reclaimer_writing_to_pcmd(encl, pcmd_first_page)) {
		sgx_encl_truncate_backing_page(encl, PFN_DOWN(page_pcmd_off));
		pcmd_page = kmap_atomic(b.pcmd);
		pcmd_page = kmap_local_page(b.pcmd);
		if (memchr_inv(pcmd_page, 0, PAGE_SIZE))
			pr_warn("PCMD page not empty after truncate.\n");
		kunmap_atomic(pcmd_page);
		kunmap_local(pcmd_page);
	}

	put_page(b.pcmd);
@@ -680,11 +680,15 @@ const struct vm_operations_struct sgx_vm_ops = {
void sgx_encl_release(struct kref *ref)
{
	struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount);
	unsigned long max_page_index = PFN_DOWN(encl->base + encl->size - 1);
	struct sgx_va_page *va_page;
	struct sgx_encl_page *entry;
	unsigned long index;
	unsigned long count = 0;

	XA_STATE(xas, &encl->page_array, PFN_DOWN(encl->base));

	xa_for_each(&encl->page_array, index, entry) {
	xas_lock(&xas);
	xas_for_each(&xas, entry, max_page_index) {
		if (entry->epc_page) {
			/*
			 * The page and its radix tree entry cannot be freed
@@ -699,9 +703,20 @@ void sgx_encl_release(struct kref *ref)
		}

		kfree(entry);
		/* Invoke scheduler to prevent soft lockups. */
		/*
		 * Invoke scheduler on every XA_CHECK_SCHED iteration
		 * to prevent soft lockups.
		 */
		if (!(++count % XA_CHECK_SCHED)) {
			xas_pause(&xas);
			xas_unlock(&xas);

			cond_resched();

			xas_lock(&xas);
		}
	}
	xas_unlock(&xas);

	xa_destroy(&encl->page_array);

Loading