[intel-sgx-kernel-dev] Backing storage file for PCMD
diff mbox

Message ID 20161230161021.18794-1-jarkko.sakkinen@linux.intel.com
State New
Headers show

Commit Message

Jarkko Sakkinen Dec. 30, 2016, 4:10 p.m. UTC
Move PCMD's to a backing storage file in order to give more control
(swapping and discarding mainly) and also to help pack stuff in the
struct sgx_enclave_page tighter in the heap.

Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>
---
 drivers/platform/x86/intel_sgx.h            |  5 ++++-
 drivers/platform/x86/intel_sgx_ioctl.c      | 12 ++++++++++++
 drivers/platform/x86/intel_sgx_page_cache.c | 16 ++++++++++++++-
 drivers/platform/x86/intel_sgx_util.c       | 30 +++++++++++++++++++++++++++++
 4 files changed, 61 insertions(+), 2 deletions(-)

Comments

Jarkko Sakkinen Dec. 31, 2016, 2:48 p.m. UTC | #1
On Fri, Dec 30, 2016 at 06:10:21PM +0200, Jarkko Sakkinen wrote:
> Move PCMD's to a backing storage file in order to give more control
> (swapping and discarding mainly) and also to help pack stuff in the
> struct sgx_enclave_page tighter in the heap.
> 
> Signed-off-by: Jarkko Sakkinen <jarkko.sakkinen@linux.intel.com>

Sent this by mistake, so please ignore.

/Jarkko

> ---
>  drivers/platform/x86/intel_sgx.h            |  5 ++++-
>  drivers/platform/x86/intel_sgx_ioctl.c      | 12 ++++++++++++
>  drivers/platform/x86/intel_sgx_page_cache.c | 16 ++++++++++++++-
>  drivers/platform/x86/intel_sgx_util.c       | 30 +++++++++++++++++++++++++++++
>  4 files changed, 61 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel_sgx.h b/drivers/platform/x86/intel_sgx.h
> index ed9e8e6..1d03606 100644
> --- a/drivers/platform/x86/intel_sgx.h
> +++ b/drivers/platform/x86/intel_sgx.h
> @@ -115,7 +115,6 @@ struct sgx_encl_page {
>  	struct list_head load_list;
>  	struct sgx_va_page *va_page;
>  	unsigned int va_offset;
> -	struct sgx_pcmd pcmd;
>  };
>  
>  struct sgx_tgid_ctx {
> @@ -141,6 +140,7 @@ struct sgx_encl {
>  	struct task_struct *owner;
>  	struct mm_struct *mm;
>  	struct file *backing;
> +	struct file *pcmd;
>  	struct list_head load_list;
>  	struct kref refcount;
>  	unsigned long base;
> @@ -198,6 +198,9 @@ void sgx_put_epc_page(void *epc_page_vaddr);
>  struct page *sgx_get_backing(struct sgx_encl *encl,
>  			     struct sgx_encl_page *entry);
>  void sgx_put_backing(struct page *backing, bool write);
> +struct page *sgx_get_pcmd(struct sgx_encl *encl,
> +			  struct sgx_encl_page *entry);
> +void sgx_put_pcmd(struct page *pcmd_page, bool write);
>  void sgx_insert_pte(struct sgx_encl *encl,
>  		    struct sgx_encl_page *encl_page,
>  		    struct sgx_epc_page *epc_page,
> diff --git a/drivers/platform/x86/intel_sgx_ioctl.c b/drivers/platform/x86/intel_sgx_ioctl.c
> index 3a4a8fa..dec136a 100644
> --- a/drivers/platform/x86/intel_sgx_ioctl.c
> +++ b/drivers/platform/x86/intel_sgx_ioctl.c
> @@ -477,6 +477,7 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
>  	struct vm_area_struct *vma;
>  	void *secs_vaddr = NULL;
>  	struct file *backing;
> +	struct file *pcmd;
>  	long ret;
>  
>  	secs = kzalloc(sizeof(*secs),  GFP_KERNEL);
> @@ -501,9 +502,19 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
>  		goto out;
>  	}
>  
> +	pcmd = shmem_file_setup("dev/sgx",
> +				((secs->size >> PAGE_SHIFT) + 1) * 128,
> +				VM_NORESERVE);
> +	if (IS_ERR(pcmd)) {
> +		fput(backing);
> +		ret = PTR_ERR(pcmd);
> +		goto out;
> +	}
> +
>  	encl = kzalloc(sizeof(*encl), GFP_KERNEL);
>  	if (!encl) {
>  		fput(backing);
> +		fput(pcmd);
>  		ret = -ENOMEM;
>  		goto out;
>  	}
> @@ -522,6 +533,7 @@ static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
>  	encl->base = secs->base;
>  	encl->size = secs->size;
>  	encl->backing = backing;
> +	encl->pcmd = pcmd;
>  
>  	secs_epc = sgx_alloc_page(encl->tgid_ctx, 0);
>  	if (IS_ERR(secs_epc)) {
> diff --git a/drivers/platform/x86/intel_sgx_page_cache.c b/drivers/platform/x86/intel_sgx_page_cache.c
> index d073057..b264d20 100644
> --- a/drivers/platform/x86/intel_sgx_page_cache.c
> +++ b/drivers/platform/x86/intel_sgx_page_cache.c
> @@ -237,10 +237,14 @@ static int __sgx_ewb(struct sgx_encl *encl,
>  {
>  	struct sgx_page_info pginfo;
>  	struct page *backing;
> +	struct page *pcmd;
> +	unsigned long pcmd_offset;
>  	void *epc;
>  	void *va;
>  	int ret;
>  
> +	pcmd_offset = ((encl_page->addr >> PAGE_SHIFT() & 31) * 128;
> +
>  	backing = sgx_get_backing(encl, encl_page);
>  	if (IS_ERR(backing)) {
>  		ret = PTR_ERR(backing);
> @@ -249,19 +253,29 @@ static int __sgx_ewb(struct sgx_encl *encl,
>  		return ret;
>  	}
>  
> +	pcmd = sgx_get_pcmd(encl, encl_page);
> +	if (IS_ERR(pcmd)) {
> +		ret = PTR_ERR(pcmd);
> +		sgx_warn(encl, "pinning the pcmd page for EWB failed with %d\n",
> +			 ret);
> +		return ret;
> +	}
> +
>  	epc = sgx_get_epc_page(encl_page->epc_page);
>  	va = sgx_get_epc_page(encl_page->va_page->epc_page);
>  
>  	pginfo.srcpge = (unsigned long)kmap_atomic(backing);
> -	pginfo.pcmd = (unsigned long)&encl_page->pcmd;
> +	pginfo.pcmd = (unsigned long)kamp_atomic(pcmd) + pcmd_offset;
>  	pginfo.linaddr = 0;
>  	pginfo.secs = 0;
>  	ret = __ewb(&pginfo, epc,
>  		    (void *)((unsigned long)va + encl_page->va_offset));
> +	kunmap_atomic((void *)(unsigned long)(pginfo.pcmd - pcmd_offset));
>  	kunmap_atomic((void *)(unsigned long)pginfo.srcpge);
>  
>  	sgx_put_epc_page(va);
>  	sgx_put_epc_page(epc);
> +	sgx_put_pcmd(pcmd, true);
>  	sgx_put_backing(backing, true);
>  
>  	return ret;
> diff --git a/drivers/platform/x86/intel_sgx_util.c b/drivers/platform/x86/intel_sgx_util.c
> index 2c390c5..40f5839 100644
> --- a/drivers/platform/x86/intel_sgx_util.c
> +++ b/drivers/platform/x86/intel_sgx_util.c
> @@ -105,6 +105,33 @@ void sgx_put_backing(struct page *backing_page, bool write)
>  	put_page(backing_page);
>  }
>  
> +struct page *sgx_get_pcmd(struct sgx_encl *encl,
> +			  struct sgx_encl_page *entry)
> +{
> +	struct page *pcmd;
> +	struct inode *inode;
> +	struct address_space *mapping;
> +	gfp_t gfpmask;
> +	pgoff_t index;
> +
> +	inode = encl->pcmd->f_path.dentry->d_inode;
> +	mapping = inode->i_mapping;
> +	gfpmask = mapping_gfp_mask(mapping);
> +	/* 32 PCMD's per page */
> +	index = (entry->addr - encl->base) >> (PAGE_SHIFT + 5);
> +	pcmd = shmem_read_mapping_page_gfp(mapping, index, gfpmask);
> +
> +	return pcmd;
> +}
> +
> +void sgx_put_pcmd(struct page *pcmd_page, bool write)
> +{
> +	if (write)
> +		set_page_dirty(pcmd_page);
> +
> +	put_page(pcmd_page);
> +}
> +
>  struct vm_area_struct *sgx_find_vma(struct sgx_encl *encl, unsigned long addr)
>  {
>  	struct vm_area_struct *vma;
> @@ -245,5 +272,8 @@ void sgx_encl_release(struct kref *ref)
>  	if (encl->backing)
>  		fput(encl->backing);
>  
> +	if (encl->pcmd)
> +		fput(encl->pcmd);
> +
>  	kfree(encl);
>  }
> -- 
> 2.9.3
>

Patch
diff mbox

diff --git a/drivers/platform/x86/intel_sgx.h b/drivers/platform/x86/intel_sgx.h
index ed9e8e6..1d03606 100644
--- a/drivers/platform/x86/intel_sgx.h
+++ b/drivers/platform/x86/intel_sgx.h
@@ -115,7 +115,6 @@  struct sgx_encl_page {
 	struct list_head load_list;
 	struct sgx_va_page *va_page;
 	unsigned int va_offset;
-	struct sgx_pcmd pcmd;
 };
 
 struct sgx_tgid_ctx {
@@ -141,6 +140,7 @@  struct sgx_encl {
 	struct task_struct *owner;
 	struct mm_struct *mm;
 	struct file *backing;
+	struct file *pcmd;
 	struct list_head load_list;
 	struct kref refcount;
 	unsigned long base;
@@ -198,6 +198,9 @@  void sgx_put_epc_page(void *epc_page_vaddr);
 struct page *sgx_get_backing(struct sgx_encl *encl,
 			     struct sgx_encl_page *entry);
 void sgx_put_backing(struct page *backing, bool write);
+struct page *sgx_get_pcmd(struct sgx_encl *encl,
+			  struct sgx_encl_page *entry);
+void sgx_put_pcmd(struct page *pcmd_page, bool write);
 void sgx_insert_pte(struct sgx_encl *encl,
 		    struct sgx_encl_page *encl_page,
 		    struct sgx_epc_page *epc_page,
diff --git a/drivers/platform/x86/intel_sgx_ioctl.c b/drivers/platform/x86/intel_sgx_ioctl.c
index 3a4a8fa..dec136a 100644
--- a/drivers/platform/x86/intel_sgx_ioctl.c
+++ b/drivers/platform/x86/intel_sgx_ioctl.c
@@ -477,6 +477,7 @@  static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
 	struct vm_area_struct *vma;
 	void *secs_vaddr = NULL;
 	struct file *backing;
+	struct file *pcmd;
 	long ret;
 
 	secs = kzalloc(sizeof(*secs),  GFP_KERNEL);
@@ -501,9 +502,19 @@  static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
 		goto out;
 	}
 
+	pcmd = shmem_file_setup("dev/sgx",
+				((secs->size >> PAGE_SHIFT) + 1) * 128,
+				VM_NORESERVE);
+	if (IS_ERR(pcmd)) {
+		fput(backing);
+		ret = PTR_ERR(pcmd);
+		goto out;
+	}
+
 	encl = kzalloc(sizeof(*encl), GFP_KERNEL);
 	if (!encl) {
 		fput(backing);
+		fput(pcmd);
 		ret = -ENOMEM;
 		goto out;
 	}
@@ -522,6 +533,7 @@  static long sgx_ioc_enclave_create(struct file *filep, unsigned int cmd,
 	encl->base = secs->base;
 	encl->size = secs->size;
 	encl->backing = backing;
+	encl->pcmd = pcmd;
 
 	secs_epc = sgx_alloc_page(encl->tgid_ctx, 0);
 	if (IS_ERR(secs_epc)) {
diff --git a/drivers/platform/x86/intel_sgx_page_cache.c b/drivers/platform/x86/intel_sgx_page_cache.c
index d073057..b264d20 100644
--- a/drivers/platform/x86/intel_sgx_page_cache.c
+++ b/drivers/platform/x86/intel_sgx_page_cache.c
@@ -237,10 +237,14 @@  static int __sgx_ewb(struct sgx_encl *encl,
 {
 	struct sgx_page_info pginfo;
 	struct page *backing;
+	struct page *pcmd;
+	unsigned long pcmd_offset;
 	void *epc;
 	void *va;
 	int ret;
 
+	pcmd_offset = ((encl_page->addr >> PAGE_SHIFT() & 31) * 128;
+
 	backing = sgx_get_backing(encl, encl_page);
 	if (IS_ERR(backing)) {
 		ret = PTR_ERR(backing);
@@ -249,19 +253,29 @@  static int __sgx_ewb(struct sgx_encl *encl,
 		return ret;
 	}
 
+	pcmd = sgx_get_pcmd(encl, encl_page);
+	if (IS_ERR(pcmd)) {
+		ret = PTR_ERR(pcmd);
+		sgx_warn(encl, "pinning the pcmd page for EWB failed with %d\n",
+			 ret);
+		return ret;
+	}
+
 	epc = sgx_get_epc_page(encl_page->epc_page);
 	va = sgx_get_epc_page(encl_page->va_page->epc_page);
 
 	pginfo.srcpge = (unsigned long)kmap_atomic(backing);
-	pginfo.pcmd = (unsigned long)&encl_page->pcmd;
+	pginfo.pcmd = (unsigned long)kamp_atomic(pcmd) + pcmd_offset;
 	pginfo.linaddr = 0;
 	pginfo.secs = 0;
 	ret = __ewb(&pginfo, epc,
 		    (void *)((unsigned long)va + encl_page->va_offset));
+	kunmap_atomic((void *)(unsigned long)(pginfo.pcmd - pcmd_offset));
 	kunmap_atomic((void *)(unsigned long)pginfo.srcpge);
 
 	sgx_put_epc_page(va);
 	sgx_put_epc_page(epc);
+	sgx_put_pcmd(pcmd, true);
 	sgx_put_backing(backing, true);
 
 	return ret;
diff --git a/drivers/platform/x86/intel_sgx_util.c b/drivers/platform/x86/intel_sgx_util.c
index 2c390c5..40f5839 100644
--- a/drivers/platform/x86/intel_sgx_util.c
+++ b/drivers/platform/x86/intel_sgx_util.c
@@ -105,6 +105,33 @@  void sgx_put_backing(struct page *backing_page, bool write)
 	put_page(backing_page);
 }
 
+struct page *sgx_get_pcmd(struct sgx_encl *encl,
+			  struct sgx_encl_page *entry)
+{
+	struct page *pcmd;
+	struct inode *inode;
+	struct address_space *mapping;
+	gfp_t gfpmask;
+	pgoff_t index;
+
+	inode = encl->pcmd->f_path.dentry->d_inode;
+	mapping = inode->i_mapping;
+	gfpmask = mapping_gfp_mask(mapping);
+	/* 32 PCMD's per page */
+	index = (entry->addr - encl->base) >> (PAGE_SHIFT + 5);
+	pcmd = shmem_read_mapping_page_gfp(mapping, index, gfpmask);
+
+	return pcmd;
+}
+
+void sgx_put_pcmd(struct page *pcmd_page, bool write)
+{
+	if (write)
+		set_page_dirty(pcmd_page);
+
+	put_page(pcmd_page);
+}
+
 struct vm_area_struct *sgx_find_vma(struct sgx_encl *encl, unsigned long addr)
 {
 	struct vm_area_struct *vma;
@@ -245,5 +272,8 @@  void sgx_encl_release(struct kref *ref)
 	if (encl->backing)
 		fput(encl->backing);
 
+	if (encl->pcmd)
+		fput(encl->pcmd);
+
 	kfree(encl);
 }