@@ -137,6 +137,7 @@ struct sgx_encl {
unsigned int secs_child_cnt;
unsigned int vma_cnt;
struct mutex lock;
+ struct mutex eviction_lock;
struct task_struct *owner;
struct mm_struct *mm;
struct file *backing;
@@ -522,6 +522,7 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
INIT_LIST_HEAD(&encl->load_list);
INIT_LIST_HEAD(&encl->encl_list);
mutex_init(&encl->lock);
+ mutex_init(&encl->eviction_lock);
INIT_WORK(&encl->add_page_work, sgx_add_page_worker);
encl->owner = current->group_leader;
@@ -224,9 +224,9 @@ static int sgx_ewb(struct sgx_encl *encl,
return ret;
}
-void sgx_free_encl_page(struct sgx_encl_page *entry,
- struct sgx_encl *encl,
- unsigned int flags)
+static void sgx_free_encl_page(struct sgx_encl_page *entry,
+ struct sgx_encl *encl,
+ unsigned int flags)
{
sgx_free_page(entry->epc_page, encl, flags);
entry->epc_page = NULL;
@@ -238,7 +238,7 @@ static void sgx_write_pages(struct sgx_encl *encl, struct list_head *src)
struct sgx_encl_page *entry;
struct sgx_encl_page *tmp;
struct page *pages[SGX_NR_SWAP_CLUSTER_MAX + 1];
- struct vm_area_struct *evma;
+ struct vm_area_struct *vma;
int cnt = 0;
int i = 0;
int ret;
@@ -261,13 +261,15 @@ static void sgx_write_pages(struct sgx_encl *encl, struct list_head *src)
return;
}
- /* EBLOCK */
+ mutex_lock(&encl->eviction_lock);
+ /* EBLOCK */
list_for_each_entry_safe(entry, tmp, src, load_list) {
- mutex_lock(&encl->lock);
- evma = sgx_find_vma(encl, entry->addr);
- if (!evma) {
+ vma = sgx_find_vma(encl, entry->addr);
+ if (!vma) {
list_del(&entry->load_list);
+
+ mutex_lock(&encl->lock);
sgx_free_encl_page(entry, encl, 0);
mutex_unlock(&encl->lock);
continue;
@@ -276,36 +278,32 @@ static void sgx_write_pages(struct sgx_encl *encl, struct list_head *src)
pages[cnt] = sgx_get_backing(encl, entry);
if (IS_ERR(pages[cnt])) {
list_del(&entry->load_list);
+
+ mutex_lock(&encl->lock);
list_add_tail(&entry->load_list, &encl->load_list);
entry->flags &= ~SGX_ENCL_PAGE_RESERVED;
mutex_unlock(&encl->lock);
continue;
}
- zap_vma_ptes(evma, entry->addr, PAGE_SIZE);
+ zap_vma_ptes(vma, entry->addr, PAGE_SIZE);
sgx_eblock(entry->epc_page);
cnt++;
- mutex_unlock(&encl->lock);
}
- /* ETRACK */
+ if (!cnt) {
+ mutex_unlock(&encl->eviction_lock);
+ goto out;
+ }
- mutex_lock(&encl->lock);
+ /* ETRACK */
sgx_etrack(encl->secs_page.epc_page);
- mutex_unlock(&encl->lock);
/* EWB */
-
- mutex_lock(&encl->lock);
i = 0;
-
- while (!list_empty(src)) {
- entry = list_first_entry(src, struct sgx_encl_page,
- load_list);
- list_del(&entry->load_list);
-
- evma = sgx_find_vma(encl, entry->addr);
- if (evma) {
+ list_for_each_entry(entry, src, load_list) {
+ vma = sgx_find_vma(encl, entry->addr);
+ if (vma) {
ret = sgx_ewb(encl, entry, pages[i]);
BUG_ON(ret != 0 && ret != SGX_NOT_TRACKED);
/* Only kick out threads with an IPI if needed. */ @@ -313,15 +311,30 @@ static void sgx_write_pages(struct sgx_encl *encl, struct list_head *src)