@@ -91,15 +91,18 @@ static inline void sgx_free_va_slot(struct sgx_va_page *page,
enum sgx_encl_page_flags {
SGX_ENCL_PAGE_TCS = BIT(0),
SGX_ENCL_PAGE_RESERVED = BIT(1),
+ SGX_ENCL_PAGE_EPC_VALID = BIT(2),
};
struct sgx_encl_page {
unsigned long addr;
unsigned int flags;
- struct sgx_epc_page *epc_page;
- struct list_head load_list;
- struct sgx_va_page *va_page;
unsigned int va_offset;
+ union {
+ struct sgx_epc_page *epc_page;
+ struct sgx_va_page *va_page;
+ };
+ struct list_head load_list;
};
struct sgx_tgid_ctx {
@@ -267,6 +267,7 @@ static bool sgx_process_add_page_req(struct sgx_add_page_req *req)
goto out;
}
+ encl_page->flags |= SGX_ENCL_PAGE_EPC_VALID;
encl_page->epc_page = epc_page;
sgx_test_and_clear_young(encl_page, encl);
list_add_tail(&encl_page->load_list, &encl->load_list);
@@ -558,6 +559,7 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
goto out;
}
+ encl->secs_page.flags |= SGX_ENCL_PAGE_EPC_VALID;
encl->secs_page.epc_page = secs_epc;
createp->src = (unsigned long)encl->base;
@@ -330,10 +330,14 @@ static int __sgx_ewb(struct sgx_encl *encl,
sgx_put_page(va);
sgx_put_page(epc);
- if (ret == SGX_SUCCESS)
+ if (ret == SGX_SUCCESS) {
+ encl_page->flags &= ~(SGX_ENCL_PAGE_RESERVED | SGX_ENCL_PAGE_EPC_VALID);
+ sgx_free_page(encl_page->epc_page, encl);
encl_page->va_page = va_page;
- else
+ }
+ else {
sgx_free_va_slot(va_page, encl_page->va_offset);
+ }
out_pcmd:
sgx_put_backing(pcmd, true);
@@ -368,9 +372,6 @@ static void sgx_evict_page(struct sgx_encl_page *entry,
struct sgx_encl *encl)
{
sgx_ewb(encl, entry);
- sgx_free_page(entry->epc_page, encl);
- entry->epc_page = NULL;
- entry->flags &= ~SGX_ENCL_PAGE_RESERVED;
}
static void sgx_write_pages(struct sgx_encl *encl, struct list_head *src)
@@ -232,6 +232,7 @@ static int sgx_eldu(struct sgx_encl *encl,
ret = -EFAULT;
} else {
sgx_free_va_slot(encl_page->va_page, encl_page->va_offset);
+ encl_page->flags |= SGX_ENCL_PAGE_EPC_VALID;
encl_page->epc_page = epc_page;
}
@@ -293,7 +294,7 @@ static struct sgx_encl_page *sgx_do_fault(struct vm_area_struct *vma,
}
/* Legal race condition, page is already faulted. */
- if (entry->epc_page) {
+ if (entry->flags & SGX_ENCL_PAGE_EPC_VALID) {
if (reserve)
entry->flags |= SGX_ENCL_PAGE_RESERVED;
goto out;
@@ -307,7 +308,7 @@ static struct sgx_encl_page *sgx_do_fault(struct vm_area_struct *vma,
}
/* If SECS is evicted then reload it first */
- if (!encl->secs_page.epc_page) {
+ if (!(encl->secs_page.flags & SGX_ENCL_PAGE_EPC_VALID)) {
secs_epc_page = sgx_alloc_page(SGX_ALLOC_ATOMIC);
if (IS_ERR(secs_epc_page)) {
rc = PTR_ERR(secs_epc_page);
@@ -398,7 +399,7 @@ void sgx_encl_release(struct kref *ref)
radix_tree_for_each_slot(slot, &encl->page_tree, &iter, 0) {
entry = *slot;
- if (entry->epc_page) {
+ if (entry->flags & SGX_ENCL_PAGE_EPC_VALID) {
list_del(&entry->load_list);
sgx_free_page(entry->epc_page, encl);
}
@@ -414,11 +415,9 @@ void sgx_encl_release(struct kref *ref)
kfree(va_page);
}
- if (encl->secs_page.epc_page)
+ if (encl->secs_page.flags & SGX_ENCL_PAGE_EPC_VALID)
sgx_free_page(encl->secs_page.epc_page, encl);
- encl->secs_page.epc_page = NULL;
-
if (encl->tgid_ctx)
kref_put(&encl->tgid_ctx->refcount, sgx_tgid_ctx_release);
Combine sgx_encl_page's epc_page and va_page into a union. On-demand VA slot/page allocations guarantees only one of epc_page or va_page will be valid at any given time. Add a new flag, SGX_ENCL_PAGE_EPC_VALID, to track if an encl page has been loaded into the EPC. If SGX_ENCL_PAGE_EPC_VALID is set, then the epc_page member of the epc_page/va_page union is valid, otherwise va_page *may* be valid, e.g. neither is valid if EADD has not been completed. Move the functionality of sgx_evict_page into the success path of EWB, as the EPC page must be freed before updating the encl_page's va_page. Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com> --- drivers/platform/x86/intel_sgx/sgx.h | 9 ++++++--- drivers/platform/x86/intel_sgx/sgx_ioctl.c | 2 ++ drivers/platform/x86/intel_sgx/sgx_page_cache.c | 11 ++++++----- drivers/platform/x86/intel_sgx/sgx_util.c | 11 +++++------ 4 files changed, 19 insertions(+), 14 deletions(-)