lkml.org 
[lkml]   [2021]   [Nov]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH] x86/sgx: Fix free page accounting
    Date
    The SGX driver maintains a single global free page counter,
    sgx_nr_free_pages, that reflects the number of free pages available
    across all NUMA nodes. Correspondingly, a list of free pages is
    associated with each NUMA node and sgx_nr_free_pages is updated
    every time a page is added or removed from any of the free page
    lists. The main usage of sgx_nr_free_pages is by the reclaimer
    that will run when the total free pages go below a watermark to
    ensure that there are always some free pages available to, for
    example, support efficient page faults.

    With sgx_nr_free_pages accessed and modified from a few places
    it is essential to ensure that these accesses are done safely but
    this is not the case. sgx_nr_free_pages is sometimes accessed
    without any protection and when it is protected it is done
    inconsistently with any one of the spin locks associated with the
    individual NUMA nodes.

    The consequence of sgx_nr_free_pages not being protected is that
    its value may not accurately reflect the actual number of free
    pages on the system, impacting the availability of free pages in
    support of many flows. The problematic scenario is when the
    reclaimer never runs because it believes there to be sufficient
    free pages while any attempt to allocate a page fails because there
    are no free pages available. The worst scenario observed was a
    user space hang because of repeated page faults caused by
    no free pages ever made available.

    Change the global free page counter to an atomic type that
    ensures simultaneous updates are done safely. While doing so, move
    the updating of the variable outside of the spin lock critical
    section to which it does not belong.

    Cc: stable@vger.kernel.org
    Fixes: 901ddbb9ecf5 ("x86/sgx: Add a basic NUMA allocation scheme to sgx_alloc_epc_page()")
    Suggested-by: Dave Hansen <dave.hansen@linux.intel.com>
    Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
    ---
    arch/x86/kernel/cpu/sgx/main.c | 12 ++++++------
    1 file changed, 6 insertions(+), 6 deletions(-)

    diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
    index 63d3de02bbcc..8558d7d5f3e7 100644
    --- a/arch/x86/kernel/cpu/sgx/main.c
    +++ b/arch/x86/kernel/cpu/sgx/main.c
    @@ -28,8 +28,7 @@ static DECLARE_WAIT_QUEUE_HEAD(ksgxd_waitq);
    static LIST_HEAD(sgx_active_page_list);
    static DEFINE_SPINLOCK(sgx_reclaimer_lock);

    -/* The free page list lock protected variables prepend the lock. */
    -static unsigned long sgx_nr_free_pages;
    +atomic_long_t sgx_nr_free_pages = ATOMIC_LONG_INIT(0);

    /* Nodes with one or more EPC sections. */
    static nodemask_t sgx_numa_mask;
    @@ -403,14 +402,15 @@ static void sgx_reclaim_pages(void)

    spin_lock(&node->lock);
    list_add_tail(&epc_page->list, &node->free_page_list);
    - sgx_nr_free_pages++;
    spin_unlock(&node->lock);
    + atomic_long_inc(&sgx_nr_free_pages);
    }
    }

    static bool sgx_should_reclaim(unsigned long watermark)
    {
    - return sgx_nr_free_pages < watermark && !list_empty(&sgx_active_page_list);
    + return atomic_long_read(&sgx_nr_free_pages) < watermark &&
    + !list_empty(&sgx_active_page_list);
    }

    static int ksgxd(void *p)
    @@ -471,9 +471,9 @@ static struct sgx_epc_page *__sgx_alloc_epc_page_from_node(int nid)

    page = list_first_entry(&node->free_page_list, struct sgx_epc_page, list);
    list_del_init(&page->list);
    - sgx_nr_free_pages--;

    spin_unlock(&node->lock);
    + atomic_long_dec(&sgx_nr_free_pages);

    return page;
    }
    @@ -625,9 +625,9 @@ void sgx_free_epc_page(struct sgx_epc_page *page)
    spin_lock(&node->lock);

    list_add_tail(&page->list, &node->free_page_list);
    - sgx_nr_free_pages++;

    spin_unlock(&node->lock);
    + atomic_long_inc(&sgx_nr_free_pages);
    }

    static bool __init sgx_setup_epc_section(u64 phys_addr, u64 size,
    --
    2.25.1
    \
     
     \ /
      Last update: 2021-11-04 19:29    [W:5.012 / U:0.052 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site