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
 }
 
