@@ -381,6 +381,22 @@ const struct vm_operations_struct sgx_vm_ops = {
.access = sgx_vma_access,
};
+
+/*
+ * Place the page in uninitialized state. Only usable by callers that
+ * know the page is in a clean state in which EREMOVE will succeed.
+ */
+static void sgx_reset_epc_page(struct sgx_epc_page *epc_page)
+{
+ int ret;
+
+ WARN_ON_ONCE(epc_page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED);
+
+ ret = __eremove(sgx_get_epc_virt_addr(epc_page));
+ if (WARN_ONCE(ret, "EREMOVE returned %d (0x%x)", ret, ret))
+ return;
+}
+
/**
* sgx_encl_release - Destroy an enclave instance
* @kref: address of a kref inside &sgx_encl
@@ -404,6 +420,7 @@ void sgx_encl_release(struct kref *ref)
if (sgx_unmark_page_reclaimable(entry->epc_page))
continue;
+ sgx_reset_epc_page(entry->epc_page);
sgx_free_epc_page(entry->epc_page);
encl->secs_child_cnt--;
entry->epc_page = NULL;
@@ -415,6 +432,7 @@ void sgx_encl_release(struct kref *ref)
xa_destroy(&encl->page_array);
if (!encl->secs_child_cnt && encl->secs.epc_page) {
+ sgx_reset_epc_page(encl->secs.epc_page);
sgx_free_epc_page(encl->secs.epc_page);
encl->secs.epc_page = NULL;
}
@@ -423,6 +441,7 @@ void sgx_encl_release(struct kref *ref)
va_page = list_first_entry(&encl->va_pages, struct sgx_va_page,
list);
list_del(&va_page->list);
+ sgx_reset_epc_page(va_page->epc_page);
sgx_free_epc_page(va_page->epc_page);
kfree(va_page);
}
@@ -598,18 +598,14 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim)
* sgx_free_epc_page() - Free an EPC page
* @page: an EPC page
*
- * Call EREMOVE for an EPC page and insert it back to the list of free pages.
+ * Put the EPC page back to the list of free pages. It's the caller's
+ * responsibility to make sure that the page is in uninitialized state. In other
+ * words, do EREMOVE, EWB or whatever operation is necessary before calling
+ * this function.
*/
void sgx_free_epc_page(struct sgx_epc_page *page)
{
struct sgx_epc_section *section = &sgx_epc_sections[page->section];
- int ret;
-
- WARN_ON_ONCE(page->flags & SGX_EPC_PAGE_RECLAIMER_TRACKED);
-
- ret = __eremove(sgx_get_epc_virt_addr(page));
- if (WARN_ONCE(ret, "EREMOVE returned %d (0x%x)", ret, ret))
- return;
spin_lock(§ion->lock);
list_add_tail(&page->list, §ion->page_list);