From: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> SGX virtualization requires to allocate "raw" EPC and use it as virtual EPC for SGX guest. Unlike EPC used by SGX driver, virtual EPC doesn't track how EPC pages are used in VM, e.g. (de)construction of enclaves, so it cannot guarantee EREMOVE success, e.g. it doesn't have a priori knowledge of which pages are SECS with non-zero child counts. Split sgx_free_page() into two parts so that the "add to free list" part can be used by virtual EPC without having to modify the EREMOVE logic in sgx_free_page(). Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> Signed-off-by: Kai Huang <kai.huang@xxxxxxxxx> --- arch/x86/kernel/cpu/sgx/main.c | 24 ++++++++++++++++++------ arch/x86/kernel/cpu/sgx/sgx.h | 1 + 2 files changed, 19 insertions(+), 6 deletions(-) diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c index c519fc5f6948..95aad183bb65 100644 --- a/arch/x86/kernel/cpu/sgx/main.c +++ b/arch/x86/kernel/cpu/sgx/main.c @@ -594,15 +594,30 @@ struct sgx_epc_page *sgx_alloc_epc_page(void *owner, bool reclaim) return page; } +/** + * __sgx_free_epc_page() - Free an EPC page + * @page: pointer to a previously allocated EPC page + * + * Insert an EPC page back to the list of free pages. + */ +void __sgx_free_epc_page(struct sgx_epc_page *page) +{ + struct sgx_epc_section *section = &sgx_epc_sections[page->section]; + + spin_lock(§ion->lock); + list_add_tail(&page->list, §ion->page_list); + section->free_cnt++; + spin_unlock(§ion->lock); +} + /** * sgx_free_epc_page() - Free an EPC page - * @page: an EPC page + * @page: pointer to a previously allocated EPC page * * Call EREMOVE for an EPC page and insert it back to the list of free pages. */ 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); @@ -611,10 +626,7 @@ void sgx_free_epc_page(struct sgx_epc_page *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); - section->free_cnt++; - spin_unlock(§ion->lock); + __sgx_free_epc_page(page); } static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size, diff --git a/arch/x86/kernel/cpu/sgx/sgx.h b/arch/x86/kernel/cpu/sgx/sgx.h index 5fa42d143feb..4dddd81cbbc3 100644 --- a/arch/x86/kernel/cpu/sgx/sgx.h +++ b/arch/x86/kernel/cpu/sgx/sgx.h @@ -77,6 +77,7 @@ static inline void *sgx_get_epc_virt_addr(struct sgx_epc_page *page) } struct sgx_epc_page *__sgx_alloc_epc_page(void); +void __sgx_free_epc_page(struct sgx_epc_page *page); void sgx_free_epc_page(struct sgx_epc_page *page); void sgx_mark_page_reclaimable(struct sgx_epc_page *page); -- 2.29.2