diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
index e03f124ce772..22ed886dc825 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
@@ -60,7 +60,7 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
 
 	page_pcmd_off = sgx_encl_get_backing_page_pcmd_offset(encl, page_index);
 
-	ret = sgx_encl_get_backing(encl, page_index, &b);
+	ret = sgx_encl_lookup_backing(encl, page_index, &b);
 	if (ret)
 		return ret;
 
@@ -102,8 +102,10 @@ static int __sgx_encl_eldu(struct sgx_encl_page *encl_page,
 
 	sgx_encl_truncate_backing_page(encl, page_index);
 
-	if (pcmd_page_empty)
+	if (pcmd_page_empty) {
+		ida_free(&encl->pcmd_in_backing, PFN_DOWN(page_pcmd_off));
 		sgx_encl_truncate_backing_page(encl, PFN_DOWN(page_pcmd_off));
+	}
 
 	return ret;
 }
@@ -617,6 +619,7 @@ void sgx_encl_release(struct kref *ref)
 
 	if (encl->backing)
 		fput(encl->backing);
+	ida_destroy(&encl->pcmd_in_backing);
 
 	cleanup_srcu_struct(&encl->srcu);
 
@@ -807,17 +810,39 @@ const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl)
 }
 
 static struct page *sgx_encl_get_backing_page(struct sgx_encl *encl,
-					      pgoff_t index)
+					      pgoff_t index, enum sgp_type sgp)
 {
 	struct inode *inode = encl->backing->f_path.dentry->d_inode;
-	struct address_space *mapping = inode->i_mapping;
-	gfp_t gfpmask = mapping_gfp_mask(mapping);
+	struct page *page = NULL;
+	int ret;
+
+	ret = shmem_getpage(inode, index, &page, sgp);
+	if (ret) {
+		pr_debug("%s:%d fail %d backing page with %d\n",
+			 __func__, __LINE__, sgp, ret);
+		return ERR_PTR(ret);
+	}
+
+	if (!page) {
+		pr_debug("%s:%d fail %d backing page with NULL page\n",
+			 __func__, __LINE__, sgp);
+		return ERR_PTR(-EFAULT);
+	}
 
-	return shmem_read_mapping_page_gfp(mapping, index, gfpmask);
+	if (PageHWPoison(page)) {
+		pr_debug("%s:%d fail %d backing page with poison page\n",
+			 __func__, __LINE__, sgp);
+		unlock_page(page);
+		put_page(page);
+		return ERR_PTR(-EIO);
+	}
+
+	unlock_page(page);
+	return page;
 }
 
 /**
- * sgx_encl_get_backing() - Pin the backing storage
+ * sgx_encl_alloc_backing() - Pin the backing storage
  * @encl:	an enclave pointer
  * @page_index:	enclave page index
  * @backing:	data for accessing backing storage for the page
@@ -829,18 +854,54 @@ static struct page *sgx_encl_get_backing_page(struct sgx_encl *encl,
  *   0 on success,
  *   -errno otherwise.
  */
-int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index,
-			 struct sgx_backing *backing)
+int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index,
+			   struct sgx_backing *backing)
+{
+	pgoff_t page_pcmd_off = sgx_encl_get_backing_page_pcmd_offset(encl, page_index);
+	pgoff_t pcmd_index = PFN_DOWN(page_pcmd_off);
+	struct page *contents;
+	struct page *pcmd;
+	int ret;
+
+	contents = sgx_encl_get_backing_page(encl, page_index, SGP_CACHE);
+	if (IS_ERR(contents))
+		return PTR_ERR(contents);
+
+	ret = ida_alloc_range(&encl->pcmd_in_backing, pcmd_index,
+			      pcmd_index, GFP_KERNEL);
+	if (ret == -ENOSPC) {
+		/* pcmd_index backing page already created, just look it up */
+		pcmd = sgx_encl_get_backing_page(encl, pcmd_index, SGP_NOALLOC);
+	} else if (ret >= 0) {
+		pcmd = sgx_encl_get_backing_page(encl, pcmd_index, SGP_CACHE);
+	} else {
+		pcmd = ERR_PTR(ret);
+	}
+	if (IS_ERR(pcmd)) {
+		put_page(contents);
+		return PTR_ERR(pcmd);
+	}
+
+	backing->page_index = page_index;
+	backing->contents = contents;
+	backing->pcmd = pcmd;
+	backing->pcmd_offset = page_pcmd_off & (PAGE_SIZE - 1);
+
+	return 0;
+}
+
+int sgx_encl_lookup_backing(struct sgx_encl *encl, unsigned long page_index,
+			    struct sgx_backing *backing)
 {
 	pgoff_t page_pcmd_off = sgx_encl_get_backing_page_pcmd_offset(encl, page_index);
 	struct page *contents;
 	struct page *pcmd;
 
-	contents = sgx_encl_get_backing_page(encl, page_index);
+	contents = sgx_encl_get_backing_page(encl, page_index, SGP_NOALLOC);
 	if (IS_ERR(contents))
 		return PTR_ERR(contents);
 
-	pcmd = sgx_encl_get_backing_page(encl, PFN_DOWN(page_pcmd_off));
+	pcmd = sgx_encl_get_backing_page(encl, PFN_DOWN(page_pcmd_off), SGP_NOALLOC);
 	if (IS_ERR(pcmd)) {
 		put_page(contents);
 		return PTR_ERR(pcmd);
diff --git a/arch/x86/kernel/cpu/sgx/encl.h b/arch/x86/kernel/cpu/sgx/encl.h
index 66adb8faec45..2a8d3bd3338f 100644
--- a/arch/x86/kernel/cpu/sgx/encl.h
+++ b/arch/x86/kernel/cpu/sgx/encl.h
@@ -8,6 +8,7 @@
 #define _X86_ENCL_H
 
 #include <linux/cpumask.h>
+#include <linux/idr.h>
 #include <linux/kref.h>
 #include <linux/list.h>
 #include <linux/mm_types.h>
@@ -62,6 +63,7 @@ struct sgx_encl {
 
 	cpumask_t cpumask;
 	struct file *backing;
+	struct ida pcmd_in_backing;
 	struct kref refcount;
 	struct list_head va_pages;
 	unsigned long mm_list_version;
@@ -107,8 +109,10 @@ int sgx_encl_may_map(struct sgx_encl *encl, unsigned long start,
 void sgx_encl_release(struct kref *ref);
 int sgx_encl_mm_add(struct sgx_encl *encl, struct mm_struct *mm);
 const cpumask_t *sgx_encl_cpumask(struct sgx_encl *encl);
-int sgx_encl_get_backing(struct sgx_encl *encl, unsigned long page_index,
-			 struct sgx_backing *backing);
+int sgx_encl_alloc_backing(struct sgx_encl *encl, unsigned long page_index,
+			   struct sgx_backing *backing);
+int sgx_encl_lookup_backing(struct sgx_encl *encl, unsigned long page_index,
+			    struct sgx_backing *backing);
 void sgx_encl_put_backing(struct sgx_backing *backing, bool do_write);
 int sgx_encl_test_and_clear_young(struct mm_struct *mm,
 				  struct sgx_encl_page *page);
diff --git a/arch/x86/kernel/cpu/sgx/ioctl.c b/arch/x86/kernel/cpu/sgx/ioctl.c
index 1c2f40b72551..94d3817b40ff 100644
--- a/arch/x86/kernel/cpu/sgx/ioctl.c
+++ b/arch/x86/kernel/cpu/sgx/ioctl.c
@@ -82,6 +82,7 @@ static int sgx_encl_create(struct sgx_encl *encl, struct sgx_secs *secs)
 	}
 
 	encl->backing = backing;
+	ida_init(&encl->pcmd_in_backing);
 
 	secs_epc = sgx_alloc_epc_page(&encl->secs, true);
 	if (IS_ERR(secs_epc)) {
diff --git a/arch/x86/kernel/cpu/sgx/main.c b/arch/x86/kernel/cpu/sgx/main.c
index ae79b8d6f645..148ec695b1b3 100644
--- a/arch/x86/kernel/cpu/sgx/main.c
+++ b/arch/x86/kernel/cpu/sgx/main.c
@@ -255,8 +255,8 @@ static void sgx_reclaimer_write(struct sgx_epc_page *epc_page,
 	sgx_encl_put_backing(backing, true);
 
 	if (!encl->secs_child_cnt && test_bit(SGX_ENCL_INITIALIZED, &encl->flags)) {
-		ret = sgx_encl_get_backing(encl, PFN_DOWN(encl->size),
-					   &secs_backing);
+		ret = sgx_encl_alloc_backing(encl, PFN_DOWN(encl->size),
+					     &secs_backing);
 		if (ret)
 			goto out;
 
@@ -326,7 +326,7 @@ static void sgx_reclaim_pages(void)
 		page_index = PFN_DOWN(encl_page->desc - encl_page->encl->base);
 
 		mutex_lock(&encl_page->encl->lock);
-		ret = sgx_encl_get_backing(encl_page->encl, page_index, &backing[i]);
+		ret = sgx_encl_alloc_backing(encl_page->encl, page_index, &backing[i]);
 		if (ret) {
 			mutex_unlock(&encl_page->encl->lock);
 			goto skip;
