162306a36Sopenharmony_ci// SPDX-License-Identifier: MIT
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2019 Advanced Micro Devices, Inc.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#include <linux/slab.h>
762306a36Sopenharmony_ci#include <linux/tee_drv.h>
862306a36Sopenharmony_ci#include <linux/psp.h>
962306a36Sopenharmony_ci#include "amdtee_private.h"
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_cistatic int pool_op_alloc(struct tee_shm_pool *pool, struct tee_shm *shm,
1262306a36Sopenharmony_ci			 size_t size, size_t align)
1362306a36Sopenharmony_ci{
1462306a36Sopenharmony_ci	unsigned int order = get_order(size);
1562306a36Sopenharmony_ci	unsigned long va;
1662306a36Sopenharmony_ci	int rc;
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci	/*
1962306a36Sopenharmony_ci	 * Ignore alignment since this is already going to be page aligned
2062306a36Sopenharmony_ci	 * and there's no need for any larger alignment.
2162306a36Sopenharmony_ci	 */
2262306a36Sopenharmony_ci	va = __get_free_pages(GFP_KERNEL | __GFP_ZERO, order);
2362306a36Sopenharmony_ci	if (!va)
2462306a36Sopenharmony_ci		return -ENOMEM;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	shm->kaddr = (void *)va;
2762306a36Sopenharmony_ci	shm->paddr = __psp_pa((void *)va);
2862306a36Sopenharmony_ci	shm->size = PAGE_SIZE << order;
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	/* Map the allocated memory in to TEE */
3162306a36Sopenharmony_ci	rc = amdtee_map_shmem(shm);
3262306a36Sopenharmony_ci	if (rc) {
3362306a36Sopenharmony_ci		free_pages(va, order);
3462306a36Sopenharmony_ci		shm->kaddr = NULL;
3562306a36Sopenharmony_ci		return rc;
3662306a36Sopenharmony_ci	}
3762306a36Sopenharmony_ci
3862306a36Sopenharmony_ci	return 0;
3962306a36Sopenharmony_ci}
4062306a36Sopenharmony_ci
4162306a36Sopenharmony_cistatic void pool_op_free(struct tee_shm_pool *pool, struct tee_shm *shm)
4262306a36Sopenharmony_ci{
4362306a36Sopenharmony_ci	/* Unmap the shared memory from TEE */
4462306a36Sopenharmony_ci	amdtee_unmap_shmem(shm);
4562306a36Sopenharmony_ci	free_pages((unsigned long)shm->kaddr, get_order(shm->size));
4662306a36Sopenharmony_ci	shm->kaddr = NULL;
4762306a36Sopenharmony_ci}
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistatic void pool_op_destroy_pool(struct tee_shm_pool *pool)
5062306a36Sopenharmony_ci{
5162306a36Sopenharmony_ci	kfree(pool);
5262306a36Sopenharmony_ci}
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_cistatic const struct tee_shm_pool_ops pool_ops = {
5562306a36Sopenharmony_ci	.alloc = pool_op_alloc,
5662306a36Sopenharmony_ci	.free = pool_op_free,
5762306a36Sopenharmony_ci	.destroy_pool = pool_op_destroy_pool,
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct tee_shm_pool *amdtee_config_shm(void)
6162306a36Sopenharmony_ci{
6262306a36Sopenharmony_ci	struct tee_shm_pool *pool = kzalloc(sizeof(*pool), GFP_KERNEL);
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_ci	if (!pool)
6562306a36Sopenharmony_ci		return ERR_PTR(-ENOMEM);
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	pool->ops = &pool_ops;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	return pool;
7062306a36Sopenharmony_ci}
71