18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: MIT
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright 2019 Advanced Micro Devices, Inc.
48c2ecf20Sopenharmony_ci */
58c2ecf20Sopenharmony_ci
68c2ecf20Sopenharmony_ci#include <linux/slab.h>
78c2ecf20Sopenharmony_ci#include <linux/tee_drv.h>
88c2ecf20Sopenharmony_ci#include <linux/psp-sev.h>
98c2ecf20Sopenharmony_ci#include "amdtee_private.h"
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_cistatic int pool_op_alloc(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm,
128c2ecf20Sopenharmony_ci			 size_t size)
138c2ecf20Sopenharmony_ci{
148c2ecf20Sopenharmony_ci	unsigned int order = get_order(size);
158c2ecf20Sopenharmony_ci	unsigned long va;
168c2ecf20Sopenharmony_ci	int rc;
178c2ecf20Sopenharmony_ci
188c2ecf20Sopenharmony_ci	va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
198c2ecf20Sopenharmony_ci	if (!va)
208c2ecf20Sopenharmony_ci		return -ENOMEM;
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci	shm->kaddr = (void *)va;
238c2ecf20Sopenharmony_ci	shm->paddr = __psp_pa((void *)va);
248c2ecf20Sopenharmony_ci	shm->size = PAGE_SIZE << order;
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci	/* Map the allocated memory in to TEE */
278c2ecf20Sopenharmony_ci	rc = amdtee_map_shmem(shm);
288c2ecf20Sopenharmony_ci	if (rc) {
298c2ecf20Sopenharmony_ci		free_pages(va, order);
308c2ecf20Sopenharmony_ci		shm->kaddr = NULL;
318c2ecf20Sopenharmony_ci		return rc;
328c2ecf20Sopenharmony_ci	}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	return 0;
358c2ecf20Sopenharmony_ci}
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_cistatic void pool_op_free(struct tee_shm_pool_mgr *poolm, struct tee_shm *shm)
388c2ecf20Sopenharmony_ci{
398c2ecf20Sopenharmony_ci	/* Unmap the shared memory from TEE */
408c2ecf20Sopenharmony_ci	amdtee_unmap_shmem(shm);
418c2ecf20Sopenharmony_ci	free_pages((unsigned long)shm->kaddr, get_order(shm->size));
428c2ecf20Sopenharmony_ci	shm->kaddr = NULL;
438c2ecf20Sopenharmony_ci}
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cistatic void pool_op_destroy_poolmgr(struct tee_shm_pool_mgr *poolm)
468c2ecf20Sopenharmony_ci{
478c2ecf20Sopenharmony_ci	kfree(poolm);
488c2ecf20Sopenharmony_ci}
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistatic const struct tee_shm_pool_mgr_ops pool_ops = {
518c2ecf20Sopenharmony_ci	.alloc = pool_op_alloc,
528c2ecf20Sopenharmony_ci	.free = pool_op_free,
538c2ecf20Sopenharmony_ci	.destroy_poolmgr = pool_op_destroy_poolmgr,
548c2ecf20Sopenharmony_ci};
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_cistatic struct tee_shm_pool_mgr *pool_mem_mgr_alloc(void)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	struct tee_shm_pool_mgr *mgr = kzalloc(sizeof(*mgr), GFP_KERNEL);
598c2ecf20Sopenharmony_ci
608c2ecf20Sopenharmony_ci	if (!mgr)
618c2ecf20Sopenharmony_ci		return ERR_PTR(-ENOMEM);
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci	mgr->ops = &pool_ops;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	return mgr;
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistruct tee_shm_pool *amdtee_config_shm(void)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	struct tee_shm_pool_mgr *priv_mgr;
718c2ecf20Sopenharmony_ci	struct tee_shm_pool_mgr *dmabuf_mgr;
728c2ecf20Sopenharmony_ci	void *rc;
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci	rc = pool_mem_mgr_alloc();
758c2ecf20Sopenharmony_ci	if (IS_ERR(rc))
768c2ecf20Sopenharmony_ci		return rc;
778c2ecf20Sopenharmony_ci	priv_mgr = rc;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci	rc = pool_mem_mgr_alloc();
808c2ecf20Sopenharmony_ci	if (IS_ERR(rc)) {
818c2ecf20Sopenharmony_ci		tee_shm_pool_mgr_destroy(priv_mgr);
828c2ecf20Sopenharmony_ci		return rc;
838c2ecf20Sopenharmony_ci	}
848c2ecf20Sopenharmony_ci	dmabuf_mgr = rc;
858c2ecf20Sopenharmony_ci
868c2ecf20Sopenharmony_ci	rc = tee_shm_pool_alloc(priv_mgr, dmabuf_mgr);
878c2ecf20Sopenharmony_ci	if (IS_ERR(rc)) {
888c2ecf20Sopenharmony_ci		tee_shm_pool_mgr_destroy(priv_mgr);
898c2ecf20Sopenharmony_ci		tee_shm_pool_mgr_destroy(dmabuf_mgr);
908c2ecf20Sopenharmony_ci	}
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ci	return rc;
938c2ecf20Sopenharmony_ci}
94