In systems with low memory configuration, memory gets fragmented
easily, and any bigger size contiguous memory allocations are likely
to fail.
Contiguous Memory Allocator (CMA) is used to overcome this
limitation, and to guarantee memory allocations.
This patch adds support for CMA area exclusive to amdtee.
The support can be enabled if kernel have CONFIG_CMA enabled.
The size can be set via the AMDTEE_CMA_SIZE config option
at compile time or with the "amdtee_cma" kernel parameter.
(e.g. "amdtee_cma=32 for 32MB").
Also, cma zone is utilized only for buffer allocation bigger than
64k bytes. When such allocation fails, there is a fallback to the
buddy allocator. Since CMA requires a boot time initialization,
it is enabled only when amdtee is built as an inbuilt driver.
Signed-off-by: Devaraj Rangasamy <Devaraj.Rangasamy@xxxxxxx>
Co-developed-by: SivaSangeetha SK <SivaSangeetha.SK@xxxxxxx>
Signed-off-by: SivaSangeetha SK <SivaSangeetha.SK@xxxxxxx>
Reviewed-by: Rijo Thomas <Rijo-john.Thomas@xxxxxxx>
---
.../admin-guide/kernel-parameters.txt | 7 ++
arch/x86/include/asm/setup.h | 6 ++
arch/x86/kernel/setup.c | 2 +
drivers/tee/amdtee/Kconfig | 9 +++
drivers/tee/amdtee/Makefile | 1 +
drivers/tee/amdtee/amdtee_private.h | 6 +-
drivers/tee/amdtee/core.c | 6 +-
drivers/tee/amdtee/shm_pool.c | 32 ++++++--
drivers/tee/amdtee/shm_pool_cma.c | 78 +++++++++++++++++++
drivers/tee/amdtee/shm_pool_cma.h | 38 +++++++++
10 files changed, 176 insertions(+), 9 deletions(-)
create mode 100644 drivers/tee/amdtee/shm_pool_cma.c
create mode 100644 drivers/tee/amdtee/shm_pool_cma.h
diff --git a/Documentation/admin-guide/kernel-parameters.txt
b/Documentation/admin-guide/kernel-parameters.txt
index 722b6eca2e93..5e38423f3d53 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -363,6 +363,13 @@
selects a performance level in this range and
appropriate
to the current workload.
+ amdtee_cma=nn [HW,TEE]
+ Sets the memory size reserved for contiguous memory
+ allocations, to be used by amdtee device driver.
+ Value is in MB and can range from 4 to 128 (MBs)
+ CMA will be active only when CMA is enabled, and amdtee is
+ built as inbuilt driver, and not loaded as module.
+
amijoy.map= [HW,JOY] Amiga joystick support
Map of devices attached to JOY0DAT and JOY1DAT
Format: <a>,<b>
diff --git a/arch/x86/include/asm/setup.h b/arch/x86/include/asm/setup.h
index f3495623ac99..bb5e4b7134a2 100644
--- a/arch/x86/include/asm/setup.h
+++ b/arch/x86/include/asm/setup.h
@@ -66,6 +66,12 @@ extern void x86_ce4100_early_setup(void);
static inline void x86_ce4100_early_setup(void) { }
#endif
+#if IS_BUILTIN(CONFIG_AMDTEE) && IS_ENABLED(CONFIG_CMA)
+void amdtee_cma_reserve(void);
+#else
+static inline void amdtee_cma_reserve(void) { }
+#endif
+
#ifndef _SETUP
#include <asm/espfix.h>
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index fd975a4a5200..e73433af3bfa 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1223,6 +1223,8 @@ void __init setup_arch(char **cmdline_p)
initmem_init();
dma_contiguous_reserve(max_pfn_mapped << PAGE_SHIFT);
+ amdtee_cma_reserve();
+
if (boot_cpu_has(X86_FEATURE_GBPAGES))
hugetlb_cma_reserve(PUD_SHIFT - PAGE_SHIFT);
diff --git a/drivers/tee/amdtee/Kconfig b/drivers/tee/amdtee/Kconfig
index 191f9715fa9a..5843c739a7b8 100644
--- a/drivers/tee/amdtee/Kconfig
+++ b/drivers/tee/amdtee/Kconfig
@@ -6,3 +6,12 @@ config AMDTEE
depends on CRYPTO_DEV_SP_PSP && CRYPTO_DEV_CCP_DD
help
This implements AMD's Trusted Execution Environment (TEE)
driver.
+
+config AMDTEE_CMA_SIZE
+ int "Size of Memory in MiB reserved in CMA for AMD-TEE"
+ default "0"
+ depends on CMA && (AMDTEE=y)
+ help
+ Specify the default amount of memory in MiB reserved in CMA
for AMD-TEE driver
+ Any amdtee shm buffer allocation larger than 64k will allocate
memory from the CMA
+ The default can be overridden with the kernel commandline
parameter "amdtee_cma".
\ No newline at end of file
diff --git a/drivers/tee/amdtee/Makefile b/drivers/tee/amdtee/Makefile
index ff1485266117..a197839cfcf3 100644
--- a/drivers/tee/amdtee/Makefile
+++ b/drivers/tee/amdtee/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_AMDTEE) += amdtee.o
amdtee-objs += core.o
amdtee-objs += call.o
amdtee-objs += shm_pool.o
+amdtee-objs += shm_pool_cma.o
diff --git a/drivers/tee/amdtee/amdtee_private.h
b/drivers/tee/amdtee/amdtee_private.h
index 6d0f7062bb87..9ba47795adb6 100644
--- a/drivers/tee/amdtee/amdtee_private.h
+++ b/drivers/tee/amdtee/amdtee_private.h
@@ -87,11 +87,13 @@ struct shmem_desc {
* struct amdtee_shm_data - Shared memory data
* @kaddr: Kernel virtual address of shared memory
* @buf_id: Buffer id of memory mapped by TEE_CMD_ID_MAP_SHARED_MEM
+ * @is_cma: Indicates whether memory is allocated from cma region
or not
*/
struct amdtee_shm_data {
struct list_head shm_node;
void *kaddr;
u32 buf_id;
+ bool is_cma;
};
/**
@@ -145,9 +147,9 @@ int amdtee_invoke_func(struct tee_context *ctx,
int amdtee_cancel_req(struct tee_context *ctx, u32 cancel_id, u32
session);
-int amdtee_map_shmem(struct tee_shm *shm);
+int amdtee_map_shmem(struct tee_shm *shm, bool is_cma);
-void amdtee_unmap_shmem(struct tee_shm *shm);
+void amdtee_unmap_shmem(struct tee_shm *shm, bool *is_cma);
int handle_load_ta(void *data, u32 size,
struct tee_ioctl_open_session_arg *arg);
diff --git a/drivers/tee/amdtee/core.c b/drivers/tee/amdtee/core.c
index 372d64756ed6..448802dccf13 100644
--- a/drivers/tee/amdtee/core.c
+++ b/drivers/tee/amdtee/core.c
@@ -336,7 +336,7 @@ int amdtee_close_session(struct tee_context *ctx,
u32 session)
return 0;
}
-int amdtee_map_shmem(struct tee_shm *shm)
+int amdtee_map_shmem(struct tee_shm *shm, bool is_cma)
{
struct amdtee_context_data *ctxdata;
struct amdtee_shm_data *shmnode;
@@ -368,6 +368,7 @@ int amdtee_map_shmem(struct tee_shm *shm)
shmnode->kaddr = shm->kaddr;
shmnode->buf_id = buf_id;
+ shmnode->is_cma = is_cma;
ctxdata = shm->ctx->data;
mutex_lock(&ctxdata->shm_mutex);
list_add(&shmnode->shm_node, &ctxdata->shm_list);
@@ -378,7 +379,7 @@ int amdtee_map_shmem(struct tee_shm *shm)
return 0;
}
-void amdtee_unmap_shmem(struct tee_shm *shm)
+void amdtee_unmap_shmem(struct tee_shm *shm, bool *is_cma)
{
struct amdtee_context_data *ctxdata;
struct amdtee_shm_data *shmnode;
@@ -395,6 +396,7 @@ void amdtee_unmap_shmem(struct tee_shm *shm)
mutex_lock(&ctxdata->shm_mutex);
list_for_each_entry(shmnode, &ctxdata->shm_list, shm_node)
if (buf_id == shmnode->buf_id) {
+ *is_cma = shmnode->is_cma;
list_del(&shmnode->shm_node);
kfree(shmnode);
break;
diff --git a/drivers/tee/amdtee/shm_pool.c
b/drivers/tee/amdtee/shm_pool.c
index f0303126f199..9aad401387be 100644
--- a/drivers/tee/amdtee/shm_pool.c
+++ b/drivers/tee/amdtee/shm_pool.c
@@ -7,19 +7,30 @@
#include <linux/tee_drv.h>
#include <linux/psp.h>
#include "amdtee_private.h"
+#include "shm_pool_cma.h"
static int pool_op_alloc(struct tee_shm_pool *pool, struct
tee_shm *shm,
size_t size, size_t align)
{
unsigned int order = get_order(size);
unsigned long va;
+ bool is_cma = false;
int rc;
/*
* Ignore alignment since this is already going to be page aligned
* and there's no need for any larger alignment.
*/
- va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+
+ /* if CMA is available, use it for higher order allocation */
+ if (amdtee_get_cma_size() && order > 6)
+ va = amdtee_alloc_from_cma(shm, order);
+
+ if (va)
+ is_cma = true;
+ else
+ va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
+
if (!va)
return -ENOMEM;
@@ -28,9 +39,13 @@ static int pool_op_alloc(struct tee_shm_pool
*pool, struct tee_shm *shm,
shm->size = PAGE_SIZE << order;
/* Map the allocated memory in to TEE */
- rc = amdtee_map_shmem(shm);
+ rc = amdtee_map_shmem(shm, is_cma);
if (rc) {
- free_pages(va, order);
+ if (is_cma)
+ amdtee_free_from_cma(shm);
+ else
+ free_pages(va, order);
+
shm->kaddr = NULL;
return rc;
}
@@ -40,9 +55,16 @@ static int pool_op_alloc(struct tee_shm_pool
*pool, struct tee_shm *shm,
static void pool_op_free(struct tee_shm_pool *pool, struct
tee_shm *shm)
{
+ bool is_cma = false;
+
/* Unmap the shared memory from TEE */
- amdtee_unmap_shmem(shm);
- free_pages((unsigned long)shm->kaddr, get_order(shm->size));
+ amdtee_unmap_shmem(shm, &is_cma);
+
+ if (is_cma)