[intel-sgx-kernel-dev,PATCH-v2] intel_isgx: adding multiple EPC support
diff mbox

Message ID 1495808938-10262-1-git-send-email-serge.ayoun@intel.com
State New
Headers show

Commit Message

Ayoun, Serge May 26, 2017, 2:28 p.m. UTC
This commit enables allocation from multiple EPC banks on systems
where they are available instead of assuming that there is only
one EPC bank. The banks can be enumerated by calling CPUID.0x12.0x2
sub leaf functions up until (eax & 0xf) is zero, which indicates
that the sub leaf is invalid and does not describe an EPC bank.

Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>
---
 drivers/platform/x86/intel_sgx.h      | 13 ++++--
 drivers/platform/x86/intel_sgx_main.c | 81 +++++++++++++++++++++++------------
 drivers/platform/x86/intel_sgx_util.c | 12 +++++-
 3 files changed, 73 insertions(+), 33 deletions(-)

Comments

Jarkko Sakkinen March 2, 2017, 1:41 p.m. UTC | #1
On Fri, May 26, 2017 at 05:28:58PM +0300, Serge Ayoun wrote:
> This commit enables allocation from multiple EPC banks on systems
> where they are available instead of assuming that there is only
> one EPC bank. The banks can be enumerated by calling CPUID.0x12.0x2
> sub leaf functions up until (eax & 0xf) is zero, which indicates
> that the sub leaf is invalid and does not describe an EPC bank.
> 
> Signed-off-by: Serge Ayoun <serge.ayoun@intel.com>

Thanks, applied! I'll squash this commit later today.

/Jarkko

> ---
>  drivers/platform/x86/intel_sgx.h      | 13 ++++--
>  drivers/platform/x86/intel_sgx_main.c | 81 +++++++++++++++++++++++------------
>  drivers/platform/x86/intel_sgx_util.c | 12 +++++-
>  3 files changed, 73 insertions(+), 33 deletions(-)
> 
> diff --git a/drivers/platform/x86/intel_sgx.h b/drivers/platform/x86/intel_sgx.h
> index ed9e8e6..466dc0f 100644
> --- a/drivers/platform/x86/intel_sgx.h
> +++ b/drivers/platform/x86/intel_sgx.h
> @@ -155,12 +155,17 @@ struct sgx_encl {
>  	struct mmu_notifier mmu_notifier;
>  };
>  
> -extern struct workqueue_struct *sgx_add_page_wq;
> -extern unsigned long sgx_epc_base;
> -extern unsigned long sgx_epc_size;
> +struct sgx_epc_bank {
>  #ifdef CONFIG_X86_64
> -extern void *sgx_epc_mem;
> +	void *mem;
>  #endif
> +	unsigned long start;
> +	unsigned long end;
> +};
> +
> +extern struct workqueue_struct *sgx_add_page_wq;
> +extern struct sgx_epc_bank sgx_epc_banks[];
> +extern int sgx_nr_epc_banks;
>  extern u64 sgx_encl_size_max_32;
>  extern u64 sgx_encl_size_max_64;
>  extern u64 sgx_xfrm_mask;
> diff --git a/drivers/platform/x86/intel_sgx_main.c b/drivers/platform/x86/intel_sgx_main.c
> index 63cca6a..8361f28 100644
> --- a/drivers/platform/x86/intel_sgx_main.c
> +++ b/drivers/platform/x86/intel_sgx_main.c
> @@ -83,11 +83,9 @@
>   */
>  
>  struct workqueue_struct *sgx_add_page_wq;
> -unsigned long sgx_epc_base;
> -unsigned long sgx_epc_size;
> -#ifdef CONFIG_X86_64
> -void *sgx_epc_mem;
> -#endif
> +#define SGX_MAX_EPC_BANKS 8
> +struct sgx_epc_bank sgx_epc_banks[SGX_MAX_EPC_BANKS];
> +int sgx_nr_epc_banks;
>  u64 sgx_encl_size_max_32 = ENCL_SIZE_MAX_32;
>  u64 sgx_encl_size_max_64 = ENCL_SIZE_MAX_64;
>  u64 sgx_xfrm_mask = 0x3;
> @@ -164,6 +162,7 @@ static unsigned long sgx_get_unmapped_area(struct file *file,
>  static int sgx_init_platform(void)
>  {
>  	unsigned int eax, ebx, ecx, edx;
> +	unsigned long size;
>  	int i;
>  
>  	cpuid(0, &eax, &ebx, &ecx, &edx);
> @@ -203,19 +202,31 @@ static int sgx_init_platform(void)
>  		sgx_encl_size_max_32 = 1ULL << ((edx >> 8) & 0xFF);
>  	}
>  
> -	cpuid_count(SGX_CPUID, 0x2, &eax, &ebx, &ecx, &edx);
> -
> -	/* The should be at least one EPC area or something is wrong. */
> -	if ((eax & 0xf) != 0x1)
> -		return -ENODEV;
> -
> -	sgx_epc_base = (((u64)(ebx & 0xfffff)) << 32) +
> -		(u64)(eax & 0xfffff000);
> -	sgx_epc_size = (((u64)(edx & 0xfffff)) << 32) +
> -		(u64)(ecx & 0xfffff000);
> +	sgx_nr_epc_banks = 0;
> +	do {
> +		cpuid_count(SGX_CPUID, sgx_nr_epc_banks + 2,
> +				&eax, &ebx, &ecx, &edx);
> +		if (eax & 0xf) {
> +			sgx_epc_banks[sgx_nr_epc_banks].start =
> +				(((u64) (ebx & 0xfffff)) << 32) +
> +				(u64) (eax & 0xfffff000);
> +			size = (((u64) (edx & 0xfffff)) << 32) +
> +				(u64) (ecx & 0xfffff000);
> +			sgx_epc_banks[sgx_nr_epc_banks].end =
> +				sgx_epc_banks[sgx_nr_epc_banks].start + size;
> +			if (!sgx_epc_banks[sgx_nr_epc_banks].start)
> +				return -ENODEV;
> +			sgx_nr_epc_banks++;
> +		} else {
> +			break;
> +		}
> +	} while (sgx_nr_epc_banks < SGX_MAX_EPC_BANKS);
>  
> -	if (!sgx_epc_base)
> -		return -ENODEV;
> +	/* There should be at least one EPC area or something is wrong. */
> +	if (!sgx_nr_epc_banks) {
> +		WARN_ON(1);
> +		return 1;
> +	}
>  
>  	return 0;
>  }
> @@ -251,6 +262,7 @@ static int sgx_dev_init(struct device *dev)
>  {
>  	unsigned int wq_flags;
>  	int ret;
> +	int i;
>  
>  	pr_info("intel_sgx: " DRV_DESCRIPTION " v" DRV_VERSION "\n");
>  
> @@ -261,18 +273,27 @@ static int sgx_dev_init(struct device *dev)
>  	if (ret)
>  		return ret;
>  
> -	pr_info("intel_sgx: EPC memory range 0x%lx-0x%lx\n", sgx_epc_base,
> -		sgx_epc_base + sgx_epc_size);
> +	pr_info("intel_sgx: Number of EPCs %d\n", sgx_nr_epc_banks);
>  
> +	for (i = 0; i < sgx_nr_epc_banks; i++) {
> +		pr_info("intel_sgx: EPC memory range 0x%lx-0x%lx\n",
> +			sgx_epc_banks[i].start, sgx_epc_banks[i].end);
>  #ifdef CONFIG_X86_64
> -	sgx_epc_mem = ioremap_cache(sgx_epc_base, sgx_epc_size);
> -	if (!sgx_epc_mem)
> -		return -ENOMEM;
> +		sgx_epc_banks[i].mem = ioremap_cache(sgx_epc_banks[i].start,
> +			sgx_epc_banks[i].end - sgx_epc_banks[i].start);
> +		if (!sgx_epc_banks[i].mem) {
> +			sgx_nr_epc_banks = i;
> +			ret = -ENOMEM;
> +			goto out_iounmap;
> +		}
>  #endif
> -
> -	ret = sgx_page_cache_init(sgx_epc_base, sgx_epc_size);
> -	if (ret)
> -		goto out_iounmap;
> +		ret = sgx_page_cache_init(sgx_epc_banks[i].start,
> +			sgx_epc_banks[i].end - sgx_epc_banks[i].start);
> +		if (ret) {
> +			sgx_nr_epc_banks = i+1;
> +			goto out_iounmap;
> +		}
> +	}
>  
>  	wq_flags = WQ_UNBOUND | WQ_FREEZABLE;
>  #ifdef WQ_NON_REENETRANT
> @@ -297,7 +318,8 @@ static int sgx_dev_init(struct device *dev)
>  	destroy_workqueue(sgx_add_page_wq);
>  out_iounmap:
>  #ifdef CONFIG_X86_64
> -	iounmap(sgx_epc_mem);
> +	for (i = 0; i < sgx_nr_epc_banks; i++)
> +		iounmap(sgx_epc_banks[i].mem);
>  #endif
>  	return ret;
>  }
> @@ -352,10 +374,13 @@ static int sgx_drv_probe(struct platform_device *pdev)
>  
>  static int sgx_drv_remove(struct platform_device *pdev)
>  {
> +	int i;
> +
>  	misc_deregister(&sgx_dev);
>  	destroy_workqueue(sgx_add_page_wq);
>  #ifdef CONFIG_X86_64
> -	iounmap(sgx_epc_mem);
> +	for (i = 0; i < sgx_nr_epc_banks; i++)
> +		iounmap(sgx_epc_banks[i].mem);
>  #endif
>  	sgx_page_cache_teardown();
>  
> diff --git a/drivers/platform/x86/intel_sgx_util.c b/drivers/platform/x86/intel_sgx_util.c
> index 2c390c5..089530b 100644
> --- a/drivers/platform/x86/intel_sgx_util.c
> +++ b/drivers/platform/x86/intel_sgx_util.c
> @@ -66,7 +66,17 @@ void *sgx_get_epc_page(struct sgx_epc_page *entry)
>  #ifdef CONFIG_X86_32
>  	return kmap_atomic_pfn(PFN_DOWN(entry->pa));
>  #else
> -	return sgx_epc_mem + (entry->pa - sgx_epc_base);
> +	int i;
> +
> +	for (i = 0; i < sgx_nr_epc_banks; i++) {
> +		if (entry->pa < sgx_epc_banks[i].end &&
> +		    entry->pa >= sgx_epc_banks[i].start) {
> +			return sgx_epc_banks[i].mem +
> +				(entry->pa - sgx_epc_banks[i].start);
> +		}
> +	}
> +
> +	return NULL;
>  #endif
>  }
>  
> -- 
> 1.9.1
> 
> ---------------------------------------------------------------------
> Intel Israel (74) Limited
> 
> This e-mail and any attachments may contain confidential material for
> the sole use of the intended recipient(s). Any review or distribution
> by others is strictly prohibited. If you are not the intended
> recipient, please contact the sender and delete all copies.
> 
> _______________________________________________
> intel-sgx-kernel-dev mailing list
> intel-sgx-kernel-dev@lists.01.org
> https://lists.01.org/mailman/listinfo/intel-sgx-kernel-dev

Patch
diff mbox

diff --git a/drivers/platform/x86/intel_sgx.h b/drivers/platform/x86/intel_sgx.h
index ed9e8e6..466dc0f 100644
--- a/drivers/platform/x86/intel_sgx.h
+++ b/drivers/platform/x86/intel_sgx.h
@@ -155,12 +155,17 @@  struct sgx_encl {
 	struct mmu_notifier mmu_notifier;
 };
 
-extern struct workqueue_struct *sgx_add_page_wq;
-extern unsigned long sgx_epc_base;
-extern unsigned long sgx_epc_size;
+struct sgx_epc_bank {
 #ifdef CONFIG_X86_64
-extern void *sgx_epc_mem;
+	void *mem;
 #endif
+	unsigned long start;
+	unsigned long end;
+};
+
+extern struct workqueue_struct *sgx_add_page_wq;
+extern struct sgx_epc_bank sgx_epc_banks[];
+extern int sgx_nr_epc_banks;
 extern u64 sgx_encl_size_max_32;
 extern u64 sgx_encl_size_max_64;
 extern u64 sgx_xfrm_mask;
diff --git a/drivers/platform/x86/intel_sgx_main.c b/drivers/platform/x86/intel_sgx_main.c
index 63cca6a..8361f28 100644
--- a/drivers/platform/x86/intel_sgx_main.c
+++ b/drivers/platform/x86/intel_sgx_main.c
@@ -83,11 +83,9 @@ 
  */
 
 struct workqueue_struct *sgx_add_page_wq;
-unsigned long sgx_epc_base;
-unsigned long sgx_epc_size;
-#ifdef CONFIG_X86_64
-void *sgx_epc_mem;
-#endif
+#define SGX_MAX_EPC_BANKS 8
+struct sgx_epc_bank sgx_epc_banks[SGX_MAX_EPC_BANKS];
+int sgx_nr_epc_banks;
 u64 sgx_encl_size_max_32 = ENCL_SIZE_MAX_32;
 u64 sgx_encl_size_max_64 = ENCL_SIZE_MAX_64;
 u64 sgx_xfrm_mask = 0x3;
@@ -164,6 +162,7 @@  static unsigned long sgx_get_unmapped_area(struct file *file,
 static int sgx_init_platform(void)
 {
 	unsigned int eax, ebx, ecx, edx;
+	unsigned long size;
 	int i;
 
 	cpuid(0, &eax, &ebx, &ecx, &edx);
@@ -203,19 +202,31 @@  static int sgx_init_platform(void)
 		sgx_encl_size_max_32 = 1ULL << ((edx >> 8) & 0xFF);
 	}
 
-	cpuid_count(SGX_CPUID, 0x2, &eax, &ebx, &ecx, &edx);
-
-	/* The should be at least one EPC area or something is wrong. */
-	if ((eax & 0xf) != 0x1)
-		return -ENODEV;
-
-	sgx_epc_base = (((u64)(ebx & 0xfffff)) << 32) +
-		(u64)(eax & 0xfffff000);
-	sgx_epc_size = (((u64)(edx & 0xfffff)) << 32) +
-		(u64)(ecx & 0xfffff000);
+	sgx_nr_epc_banks = 0;
+	do {
+		cpuid_count(SGX_CPUID, sgx_nr_epc_banks + 2,
+				&eax, &ebx, &ecx, &edx);
+		if (eax & 0xf) {
+			sgx_epc_banks[sgx_nr_epc_banks].start =
+				(((u64) (ebx & 0xfffff)) << 32) +
+				(u64) (eax & 0xfffff000);
+			size = (((u64) (edx & 0xfffff)) << 32) +
+				(u64) (ecx & 0xfffff000);
+			sgx_epc_banks[sgx_nr_epc_banks].end =
+				sgx_epc_banks[sgx_nr_epc_banks].start + size;
+			if (!sgx_epc_banks[sgx_nr_epc_banks].start)
+				return -ENODEV;
+			sgx_nr_epc_banks++;
+		} else {
+			break;
+		}
+	} while (sgx_nr_epc_banks < SGX_MAX_EPC_BANKS);
 
-	if (!sgx_epc_base)
-		return -ENODEV;
+	/* There should be at least one EPC area or something is wrong. */
+	if (!sgx_nr_epc_banks) {
+		WARN_ON(1);
+		return 1;
+	}
 
 	return 0;
 }
@@ -251,6 +262,7 @@  static int sgx_dev_init(struct device *dev)
 {
 	unsigned int wq_flags;
 	int ret;
+	int i;
 
 	pr_info("intel_sgx: " DRV_DESCRIPTION " v" DRV_VERSION "\n");
 
@@ -261,18 +273,27 @@  static int sgx_dev_init(struct device *dev)
 	if (ret)
 		return ret;
 
-	pr_info("intel_sgx: EPC memory range 0x%lx-0x%lx\n", sgx_epc_base,
-		sgx_epc_base + sgx_epc_size);
+	pr_info("intel_sgx: Number of EPCs %d\n", sgx_nr_epc_banks);
 
+	for (i = 0; i < sgx_nr_epc_banks; i++) {
+		pr_info("intel_sgx: EPC memory range 0x%lx-0x%lx\n",
+			sgx_epc_banks[i].start, sgx_epc_banks[i].end);
 #ifdef CONFIG_X86_64
-	sgx_epc_mem = ioremap_cache(sgx_epc_base, sgx_epc_size);
-	if (!sgx_epc_mem)
-		return -ENOMEM;
+		sgx_epc_banks[i].mem = ioremap_cache(sgx_epc_banks[i].start,
+			sgx_epc_banks[i].end - sgx_epc_banks[i].start);
+		if (!sgx_epc_banks[i].mem) {
+			sgx_nr_epc_banks = i;
+			ret = -ENOMEM;
+			goto out_iounmap;
+		}
 #endif
-
-	ret = sgx_page_cache_init(sgx_epc_base, sgx_epc_size);
-	if (ret)
-		goto out_iounmap;
+		ret = sgx_page_cache_init(sgx_epc_banks[i].start,
+			sgx_epc_banks[i].end - sgx_epc_banks[i].start);
+		if (ret) {
+			sgx_nr_epc_banks = i+1;
+			goto out_iounmap;
+		}
+	}
 
 	wq_flags = WQ_UNBOUND | WQ_FREEZABLE;
 #ifdef WQ_NON_REENETRANT
@@ -297,7 +318,8 @@  static int sgx_dev_init(struct device *dev)
 	destroy_workqueue(sgx_add_page_wq);
 out_iounmap:
 #ifdef CONFIG_X86_64
-	iounmap(sgx_epc_mem);
+	for (i = 0; i < sgx_nr_epc_banks; i++)
+		iounmap(sgx_epc_banks[i].mem);
 #endif
 	return ret;
 }
@@ -352,10 +374,13 @@  static int sgx_drv_probe(struct platform_device *pdev)
 
 static int sgx_drv_remove(struct platform_device *pdev)
 {
+	int i;
+
 	misc_deregister(&sgx_dev);
 	destroy_workqueue(sgx_add_page_wq);
 #ifdef CONFIG_X86_64
-	iounmap(sgx_epc_mem);
+	for (i = 0; i < sgx_nr_epc_banks; i++)
+		iounmap(sgx_epc_banks[i].mem);
 #endif
 	sgx_page_cache_teardown();
 
diff --git a/drivers/platform/x86/intel_sgx_util.c b/drivers/platform/x86/intel_sgx_util.c
index 2c390c5..089530b 100644
--- a/drivers/platform/x86/intel_sgx_util.c
+++ b/drivers/platform/x86/intel_sgx_util.c
@@ -66,7 +66,17 @@  void *sgx_get_epc_page(struct sgx_epc_page *entry)
 #ifdef CONFIG_X86_32
 	return kmap_atomic_pfn(PFN_DOWN(entry->pa));
 #else
-	return sgx_epc_mem + (entry->pa - sgx_epc_base);
+	int i;
+
+	for (i = 0; i < sgx_nr_epc_banks; i++) {
+		if (entry->pa < sgx_epc_banks[i].end &&
+		    entry->pa >= sgx_epc_banks[i].start) {
+			return sgx_epc_banks[i].mem +
+				(entry->pa - sgx_epc_banks[i].start);
+		}
+	}
+
+	return NULL;
 #endif
 }