summaryrefslogtreecommitdiff
path: root/arch/x86/kernel/cpu/sgx/main.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2025-12-02 14:03:05 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2025-12-02 14:03:05 -0800
commit54de197c9a5e8f522cb0a472e68e3e9888c91aa3 (patch)
tree9d144a34a075bc75ae6989f22be7ea4a3accada0 /arch/x86/kernel/cpu/sgx/main.c
parentc76431e3b53a426de565fa75f8278c59ca6f5ed6 (diff)
parentf2f22721aca46cebb63c589eefda843721908833 (diff)
Merge tag 'x86_sgx_for_6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 SGX updates from Dave HansenL "The main content here is adding support for the new EUPDATESVN SGX ISA. Before this, folks who updated microcode had to reboot before enclaves could attest to the new microcode. The new functionality lets them do this without a reboot. The rest are some nice, but relatively mundane comment and kernel-doc fixups. Summary: - Allow security version (SVN) updates so enclaves can attest to new microcode - Fix kernel docs typos" * tag 'x86_sgx_for_6.19-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86/sgx: Fix a typo in the kernel-doc comment for enum sgx_attribute x86/sgx: Remove superfluous asterisk from copyright comment in asm/sgx.h x86/sgx: Document structs and enums with '@', not '%' x86/sgx: Add kernel-doc descriptions for params passed to vDSO user handler x86/sgx: Add a missing colon in kernel-doc markup for "struct sgx_enclave_run" x86/sgx: Enable automatic SVN updates for SGX enclaves x86/sgx: Implement ENCLS[EUPDATESVN] x86/sgx: Define error codes for use by ENCLS[EUPDATESVN] x86/cpufeatures: Add X86_FEATURE_SGX_EUPDATESVN feature flag x86/sgx: Introduce functions to count the sgx_(vepc_)open()
Diffstat (limited to 'arch/x86/kernel/cpu/sgx/main.c')
-rw-r--r--arch/x86/kernel/cpu/sgx/main.c101
1 files changed, 101 insertions, 0 deletions
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index 2de01b379aa3..3eda7e7942e6 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -16,6 +16,7 @@
#include <linux/vmalloc.h>
#include <asm/msr.h>
#include <asm/sgx.h>
+#include <asm/archrandom.h>
#include "driver.h"
#include "encl.h"
#include "encls.h"
@@ -917,6 +918,106 @@ int sgx_set_attribute(unsigned long *allowed_attributes,
}
EXPORT_SYMBOL_GPL(sgx_set_attribute);
+/* Counter to count the active SGX users */
+static int sgx_usage_count;
+
+/**
+ * sgx_update_svn() - Attempt to call ENCLS[EUPDATESVN].
+ *
+ * This instruction attempts to update CPUSVN to the
+ * currently loaded microcode update SVN and generate new
+ * cryptographic assets.
+ *
+ * Return:
+ * * %0: - Success or not supported
+ * * %-EAGAIN: - Can be safely retried, failure is due to lack of
+ * * entropy in RNG
+ * * %-EIO: - Unexpected error, retries are not advisable
+ */
+static int sgx_update_svn(void)
+{
+ int ret;
+
+ /*
+ * If EUPDATESVN is not available, it is ok to
+ * silently skip it to comply with legacy behavior.
+ */
+ if (!cpu_feature_enabled(X86_FEATURE_SGX_EUPDATESVN))
+ return 0;
+
+ /*
+ * EPC is guaranteed to be empty when there are no users.
+ * Ensure we are on our first user before proceeding further.
+ */
+ WARN(sgx_usage_count, "Elevated usage count when calling EUPDATESVN\n");
+
+ for (int i = 0; i < RDRAND_RETRY_LOOPS; i++) {
+ ret = __eupdatesvn();
+
+ /* Stop on success or unexpected errors: */
+ if (ret != SGX_INSUFFICIENT_ENTROPY)
+ break;
+ }
+
+ switch (ret) {
+ case 0:
+ /*
+ * SVN successfully updated.
+ * Let users know when the update was successful.
+ */
+ pr_info("SVN updated successfully\n");
+ return 0;
+ case SGX_NO_UPDATE:
+ /*
+ * SVN update failed since the current SVN is
+ * not newer than CPUSVN. This is the most
+ * common case and indicates no harm.
+ */
+ return 0;
+ case SGX_INSUFFICIENT_ENTROPY:
+ /*
+ * SVN update failed due to lack of entropy in DRNG.
+ * Indicate to userspace that it should retry.
+ */
+ return -EAGAIN;
+ default:
+ break;
+ }
+
+ /*
+ * EUPDATESVN was called when EPC is empty, all other error
+ * codes are unexpected.
+ */
+ ENCLS_WARN(ret, "EUPDATESVN");
+ return -EIO;
+}
+
+/* Mutex to ensure no concurrent EPC accesses during EUPDATESVN */
+static DEFINE_MUTEX(sgx_svn_lock);
+
+int sgx_inc_usage_count(void)
+{
+ int ret;
+
+ guard(mutex)(&sgx_svn_lock);
+
+ if (!sgx_usage_count) {
+ ret = sgx_update_svn();
+ if (ret)
+ return ret;
+ }
+
+ sgx_usage_count++;
+
+ return 0;
+}
+
+void sgx_dec_usage_count(void)
+{
+ guard(mutex)(&sgx_svn_lock);
+ sgx_usage_count--;
+}
+
static int __init sgx_init(void)
{
int ret;