Skip to content

Commit 2da68a7

Browse files
committed
Merge tag 'x86_sgx_for_6.2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
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
2 parents c1f0fcd + 89e927b commit 2da68a7

File tree

9 files changed

+66
-28
lines changed

9 files changed

+66
-28
lines changed

arch/x86/include/asm/cpufeatures.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,7 @@
304304
#define X86_FEATURE_UNRET (11*32+15) /* "" AMD BTB untrain return */
305305
#define X86_FEATURE_USE_IBPB_FW (11*32+16) /* "" Use IBPB during runtime firmware calls */
306306
#define X86_FEATURE_RSB_VMEXIT_LITE (11*32+17) /* "" Fill RSB on VM exit when EIBRS is enabled */
307+
#define X86_FEATURE_SGX_EDECCSSA (11*32+18) /* "" SGX EDECCSSA user leaf function */
307308

308309

309310
#define X86_FEATURE_MSR_TSX_CTRL (11*32+20) /* "" MSR IA32_TSX_CTRL (Intel) implemented */

arch/x86/include/asm/sgx.h

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -115,17 +115,36 @@ enum sgx_miscselect {
115115
* %SGX_ATTR_EINITTOKENKEY: Allow to use token signing key that is used to
116116
* sign cryptographic tokens that can be passed to
117117
* EINIT as an authorization to run an enclave.
118+
* %SGX_ATTR_ASYNC_EXIT_NOTIFY: Allow enclaves to be notified after an
119+
* asynchronous exit has occurred.
118120
*/
119121
enum sgx_attribute {
120-
SGX_ATTR_INIT = BIT(0),
121-
SGX_ATTR_DEBUG = BIT(1),
122-
SGX_ATTR_MODE64BIT = BIT(2),
123-
SGX_ATTR_PROVISIONKEY = BIT(4),
124-
SGX_ATTR_EINITTOKENKEY = BIT(5),
125-
SGX_ATTR_KSS = BIT(7),
122+
SGX_ATTR_INIT = BIT(0),
123+
SGX_ATTR_DEBUG = BIT(1),
124+
SGX_ATTR_MODE64BIT = BIT(2),
125+
/* BIT(3) is reserved */
126+
SGX_ATTR_PROVISIONKEY = BIT(4),
127+
SGX_ATTR_EINITTOKENKEY = BIT(5),
128+
/* BIT(6) is for CET */
129+
SGX_ATTR_KSS = BIT(7),
130+
/* BIT(8) is reserved */
131+
/* BIT(9) is reserved */
132+
SGX_ATTR_ASYNC_EXIT_NOTIFY = BIT(10),
126133
};
127134

128-
#define SGX_ATTR_RESERVED_MASK (BIT_ULL(3) | BIT_ULL(6) | GENMASK_ULL(63, 8))
135+
#define SGX_ATTR_RESERVED_MASK (BIT_ULL(3) | \
136+
BIT_ULL(6) | \
137+
BIT_ULL(8) | \
138+
BIT_ULL(9) | \
139+
GENMASK_ULL(63, 11))
140+
141+
#define SGX_ATTR_UNPRIV_MASK (SGX_ATTR_DEBUG | \
142+
SGX_ATTR_MODE64BIT | \
143+
SGX_ATTR_KSS | \
144+
SGX_ATTR_ASYNC_EXIT_NOTIFY)
145+
146+
#define SGX_ATTR_PRIV_MASK (SGX_ATTR_PROVISIONKEY | \
147+
SGX_ATTR_EINITTOKENKEY)
129148

130149
/**
131150
* struct sgx_secs - SGX Enclave Control Structure (SECS)

arch/x86/kernel/cpu/cpuid-deps.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ static const struct cpuid_dep cpuid_deps[] = {
7575
{ X86_FEATURE_SGX_LC, X86_FEATURE_SGX },
7676
{ X86_FEATURE_SGX1, X86_FEATURE_SGX },
7777
{ X86_FEATURE_SGX2, X86_FEATURE_SGX1 },
78+
{ X86_FEATURE_SGX_EDECCSSA, X86_FEATURE_SGX1 },
7879
{ X86_FEATURE_XFD, X86_FEATURE_XSAVES },
7980
{ X86_FEATURE_XFD, X86_FEATURE_XGETBV1 },
8081
{ X86_FEATURE_AMX_TILE, X86_FEATURE_XFD },

arch/x86/kernel/cpu/scattered.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ static const struct cpuid_bit cpuid_bits[] = {
4040
{ X86_FEATURE_PER_THREAD_MBA, CPUID_ECX, 0, 0x00000010, 3 },
4141
{ X86_FEATURE_SGX1, CPUID_EAX, 0, 0x00000012, 0 },
4242
{ X86_FEATURE_SGX2, CPUID_EAX, 1, 0x00000012, 0 },
43+
{ X86_FEATURE_SGX_EDECCSSA, CPUID_EAX, 11, 0x00000012, 0 },
4344
{ X86_FEATURE_HW_PSTATE, CPUID_EDX, 7, 0x80000007, 0 },
4445
{ X86_FEATURE_CPB, CPUID_EDX, 9, 0x80000007, 0 },
4546
{ X86_FEATURE_PROC_FEEDBACK, CPUID_EDX, 11, 0x80000007, 0 },

arch/x86/kernel/cpu/sgx/encl.c

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -160,8 +160,8 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
160160
return ret;
161161

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

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

190-
kunmap_atomic(pcmd_page);
191-
kunmap_atomic((void *)(unsigned long)pginfo.contents);
190+
kunmap_local(pcmd_page);
191+
kunmap_local((void *)(unsigned long)pginfo.contents);
192192

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

198198
if (pcmd_page_empty && !reclaimer_writing_to_pcmd(encl, pcmd_first_page)) {
199199
sgx_encl_truncate_backing_page(encl, PFN_DOWN(page_pcmd_off));
200-
pcmd_page = kmap_atomic(b.pcmd);
200+
pcmd_page = kmap_local_page(b.pcmd);
201201
if (memchr_inv(pcmd_page, 0, PAGE_SIZE))
202202
pr_warn("PCMD page not empty after truncate.\n");
203-
kunmap_atomic(pcmd_page);
203+
kunmap_local(pcmd_page);
204204
}
205205

206206
put_page(b.pcmd);
@@ -680,11 +680,15 @@ const struct vm_operations_struct sgx_vm_ops = {
680680
void sgx_encl_release(struct kref *ref)
681681
{
682682
struct sgx_encl *encl = container_of(ref, struct sgx_encl, refcount);
683+
unsigned long max_page_index = PFN_DOWN(encl->base + encl->size - 1);
683684
struct sgx_va_page *va_page;
684685
struct sgx_encl_page *entry;
685-
unsigned long index;
686+
unsigned long count = 0;
687+
688+
XA_STATE(xas, &encl->page_array, PFN_DOWN(encl->base));
686689

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

701705
kfree(entry);
702-
/* Invoke scheduler to prevent soft lockups. */
703-
cond_resched();
706+
/*
707+
* Invoke scheduler on every XA_CHECK_SCHED iteration
708+
* to prevent soft lockups.
709+
*/
710+
if (!(++count % XA_CHECK_SCHED)) {
711+
xas_pause(&xas);
712+
xas_unlock(&xas);
713+
714+
cond_resched();
715+
716+
xas_lock(&xas);
717+
}
704718
}
719+
xas_unlock(&xas);
705720

706721
xa_destroy(&encl->page_array);
707722

arch/x86/kernel/cpu/sgx/ioctl.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
111111
encl->base = secs->base;
112112
encl->size = secs->size;
113113
encl->attributes = secs->attributes;
114-
encl->attributes_mask = SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT | SGX_ATTR_KSS;
114+
encl->attributes_mask = SGX_ATTR_UNPRIV_MASK;
115115

116116
/* Set only after completion, as encl->lock has not been taken. */
117117
set_bit(SGX_ENCL_CREATED, &encl->flags);
@@ -221,11 +221,11 @@ static int __sgx_encl_add_page(struct sgx_encl *encl,
221221
pginfo.secs = (unsigned long)sgx_get_epc_virt_addr(encl->secs.epc_page);
222222
pginfo.addr = encl_page->desc & PAGE_MASK;
223223
pginfo.metadata = (unsigned long)secinfo;
224-
pginfo.contents = (unsigned long)kmap_atomic(src_page);
224+
pginfo.contents = (unsigned long)kmap_local_page(src_page);
225225

226226
ret = __eadd(&pginfo, sgx_get_epc_virt_addr(epc_page));
227227

228-
kunmap_atomic((void *)pginfo.contents);
228+
kunmap_local((void *)pginfo.contents);
229229
put_page(src_page);
230230

231231
return ret ? -EIO : 0;

arch/x86/kernel/cpu/sgx/main.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -165,17 +165,17 @@ static int __sgx_encl_ewb(struct sgx_epc_page *epc_page, void *va_slot,
165165
pginfo.addr = 0;
166166
pginfo.secs = 0;
167167

168-
pginfo.contents = (unsigned long)kmap_atomic(backing->contents);
169-
pginfo.metadata = (unsigned long)kmap_atomic(backing->pcmd) +
168+
pginfo.contents = (unsigned long)kmap_local_page(backing->contents);
169+
pginfo.metadata = (unsigned long)kmap_local_page(backing->pcmd) +
170170
backing->pcmd_offset;
171171

172172
ret = __ewb(&pginfo, sgx_get_epc_virt_addr(epc_page), va_slot);
173173
set_page_dirty(backing->pcmd);
174174
set_page_dirty(backing->contents);
175175

176-
kunmap_atomic((void *)(unsigned long)(pginfo.metadata -
176+
kunmap_local((void *)(unsigned long)(pginfo.metadata -
177177
backing->pcmd_offset));
178-
kunmap_atomic((void *)(unsigned long)pginfo.contents);
178+
kunmap_local((void *)(unsigned long)pginfo.contents);
179179

180180
return ret;
181181
}

arch/x86/kvm/cpuid.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ void kvm_set_cpu_caps(void)
665665
);
666666

667667
kvm_cpu_cap_init_scattered(CPUID_12_EAX,
668-
SF(SGX1) | SF(SGX2)
668+
SF(SGX1) | SF(SGX2) | SF(SGX_EDECCSSA)
669669
);
670670

671671
kvm_cpu_cap_mask(CPUID_8000_0001_ECX,
@@ -1047,9 +1047,7 @@ static inline int __do_cpuid_func(struct kvm_cpuid_array *array, u32 function)
10471047
* userspace. ATTRIBUTES.XFRM is not adjusted as userspace is
10481048
* expected to derive it from supported XCR0.
10491049
*/
1050-
entry->eax &= SGX_ATTR_DEBUG | SGX_ATTR_MODE64BIT |
1051-
SGX_ATTR_PROVISIONKEY | SGX_ATTR_EINITTOKENKEY |
1052-
SGX_ATTR_KSS;
1050+
entry->eax &= SGX_ATTR_PRIV_MASK | SGX_ATTR_UNPRIV_MASK;
10531051
entry->ebx &= 0;
10541052
break;
10551053
/* Intel PT */

arch/x86/kvm/reverse_cpuid.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ enum kvm_only_cpuid_leafs {
2323
/* Intel-defined SGX sub-features, CPUID level 0x12 (EAX). */
2424
#define KVM_X86_FEATURE_SGX1 KVM_X86_FEATURE(CPUID_12_EAX, 0)
2525
#define KVM_X86_FEATURE_SGX2 KVM_X86_FEATURE(CPUID_12_EAX, 1)
26+
#define KVM_X86_FEATURE_SGX_EDECCSSA KVM_X86_FEATURE(CPUID_12_EAX, 11)
2627

2728
struct cpuid_reg {
2829
u32 function;
@@ -78,6 +79,8 @@ static __always_inline u32 __feature_translate(int x86_feature)
7879
return KVM_X86_FEATURE_SGX1;
7980
else if (x86_feature == X86_FEATURE_SGX2)
8081
return KVM_X86_FEATURE_SGX2;
82+
else if (x86_feature == X86_FEATURE_SGX_EDECCSSA)
83+
return KVM_X86_FEATURE_SGX_EDECCSSA;
8184

8285
return x86_feature;
8386
}

0 commit comments

Comments
 (0)