On Tue, Sep 03, 2019 at 05:26:40PM +0300, Jarkko Sakkinen wrote:
> Add functions for grabbing EPC pages into use:
> 
> * sgx_alloc_page(): Iterate the EPC sections and return the first free
>   page, or ERR_PTR(-ENOMEM) when no free pages are available.
> * __sgx_free_page(): Return the page into uninitialized state and move
>   it back to the corresponding EPC section structure. Issues WARN()
>   when EREMOVE fails.
> * sgx_free_page(): Return the page into uninitialized state and move
>   it back to the corresponding EPC section structure. Returns
>   ENCLS[EREMOVE] error code back to the caller.
> 
> [1] Intel SDM: 40.3 INTELĀ® SGX SYSTEM LEAF FUNCTION REFERENCE
> 
> Signed-off-by: Jarkko Sakkinen <[email protected]>
> Co-developed-by: Sean Christopherson <[email protected]>
> Signed-off-by: Sean Christopherson <[email protected]>
> ---
>  arch/x86/kernel/cpu/sgx/main.c | 90 ++++++++++++++++++++++++++++++++++
>  arch/x86/kernel/cpu/sgx/sgx.h  |  4 ++
>  2 files changed, 94 insertions(+)
> 
> diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
> index e2317f6e4374..6b4727df72ca 100644
> --- a/arch/x86/kernel/cpu/sgx/main.c
> +++ b/arch/x86/kernel/cpu/sgx/main.c
> @@ -9,6 +9,7 @@
>  #include <linux/sched/signal.h>
>  #include <linux/slab.h>
>  #include "arch.h"
> +#include "encls.h"
>  #include "sgx.h"
>  
>  struct sgx_epc_section sgx_epc_sections[SGX_MAX_EPC_SECTIONS];
> @@ -16,6 +17,95 @@ EXPORT_SYMBOL_GPL(sgx_epc_sections);
>  
>  int sgx_nr_epc_sections;
>  
> +static struct sgx_epc_page *sgx_section_get_page(

That fits into 80 cols (oh well, 81) and even if not, a trailing opening
arg brace is ugly.

> +     struct sgx_epc_section *section)
> +{
> +     struct sgx_epc_page *page;
> +
> +     if (!section->free_cnt)
> +             return NULL;
> +
> +     page = list_first_entry(&section->page_list,
> +                             struct sgx_epc_page, list);

That fits in 80-cols too. Why break it?

> +     list_del_init(&page->list);
> +     section->free_cnt--;
> +     return page;
> +}
> +
> +/**
> + * sgx_alloc_page - Allocate an EPC page
> + *
> + * Try to grab a page from the free EPC page list.
> + *
> + * Return:
> + *   a pointer to a &struct sgx_epc_page instance,
> + *   -errno on error
> + */
> +struct sgx_epc_page *sgx_alloc_page(void)
> +{
> +     struct sgx_epc_section *section;
> +     struct sgx_epc_page *page;
> +     int i;
> +
> +     for (i = 0; i < sgx_nr_epc_sections; i++) {
> +             section = &sgx_epc_sections[i];
> +             spin_lock(&section->lock);
> +             page = sgx_section_get_page(section);
> +             spin_unlock(&section->lock);
> +
> +             if (page)
> +                     return page;
> +     }
> +
> +     return ERR_PTR(-ENOMEM);
> +}
> +EXPORT_SYMBOL_GPL(sgx_alloc_page);

That export gets removed later too. But you know already...

> +
> +/**
> + * __sgx_free_page - Free an EPC page
> + * @page:    pointer a previously allocated EPC page
> + *
> + * EREMOVE an EPC page and insert it back to the list of free pages.
> + *
> + * Return:
> + *   0 on success
> + *   SGX error code if EREMOVE fails
> + */
> +int __sgx_free_page(struct sgx_epc_page *page)
> +{
> +     struct sgx_epc_section *section = sgx_epc_section(page);
> +     int ret;

Shouldn't you be grabbing the lock here already?

Or nothing can happen to that page from another thread after you
ENCLS[EREMOVE] it and before it is added to the ->page_list of the
section?

> +
> +     ret = __eremove(sgx_epc_addr(page));
> +     if (ret)
> +             return ret;
> +
> +     spin_lock(&section->lock);
> +     list_add_tail(&page->list, &section->page_list);
> +     section->free_cnt++;
> +     spin_unlock(&section->lock);
> +
> +     return 0;
> +}
> +EXPORT_SYMBOL_GPL(__sgx_free_page);
> +
> +/**
> + * sgx_free_page - Free an EPC page and WARN on failure
> + * @page:    pointer to a previously allocated EPC page
> + *
> + * EREMOVE an EPC page and insert it back to the list of free pages, and WARN
> + * if EREMOVE fails.  For use when the call site cannot (or chooses not to)
> + * handle failure, i.e. the page is leaked on failure.
> + */
> +void sgx_free_page(struct sgx_epc_page *page)
> +{
> +     int ret;
> +
> +     ret = __sgx_free_page(page);
> +     WARN(ret > 0, "sgx: EREMOVE returned %d (0x%x)", ret, ret);

That will potentially flood dmesg. Why are we even accommodating such
callers? They either handle the error or they don't get to alloc EPC
pages. There's also __must_check with which you can enforce the error
code checking or we simply don't allow not handling failure. Fullstop.

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

Reply via email to