From 9d77db3c730780c8ef5ccd4b66403ff5675cfe4e Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Mon, 13 May 2024 10:30:14 +0000 Subject: [PATCH] modify sin led gpio --- kernel/drivers/tee/tee_shm.c | 154 +++++++++++++++++++++++++-------------------------- 1 files changed, 76 insertions(+), 78 deletions(-) diff --git a/kernel/drivers/tee/tee_shm.c b/kernel/drivers/tee/tee_shm.c index 9b9530f..6fb4400 100644 --- a/kernel/drivers/tee/tee_shm.c +++ b/kernel/drivers/tee/tee_shm.c @@ -1,15 +1,6 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2015-2017, 2019-2021 Linaro Limited - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * */ #include <linux/anon_inodes.h> #include <linux/device.h> @@ -18,7 +9,25 @@ #include <linux/sched.h> #include <linux/slab.h> #include <linux/tee_drv.h> +#include <linux/uaccess.h> +#include <linux/uio.h> #include "tee_private.h" + +static void release_registered_pages(struct tee_shm *shm) +{ + if (shm->pages) { + if (shm->flags & TEE_SHM_USER_MAPPED) { + unpin_user_pages(shm->pages, shm->num_pages); + } else { + size_t n; + + for (n = 0; n < shm->num_pages; n++) + put_page(shm->pages[n]); + } + + kfree(shm->pages); + } +} static void tee_shm_release(struct tee_device *teedev, struct tee_shm *shm) { @@ -32,40 +41,29 @@ poolm->ops->free(poolm, shm); } else if (shm->flags & TEE_SHM_REGISTER) { - size_t n; int rc = teedev->desc->ops->shm_unregister(shm->ctx, shm); if (rc) dev_err(teedev->dev.parent, "unregister shm %p failed: %d", shm, rc); - for (n = 0; n < shm->num_pages; n++) - put_page(shm->pages[n]); - - kfree(shm->pages); + release_registered_pages(shm); } - if (shm->ctx) - teedev_ctx_put(shm->ctx); + teedev_ctx_put(shm->ctx); kfree(shm); tee_device_put(teedev); } -static struct tee_shm *__tee_shm_alloc(struct tee_context *ctx, - struct tee_device *teedev, - size_t size, u32 flags) +struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) { + struct tee_device *teedev = ctx->teedev; struct tee_shm_pool_mgr *poolm = NULL; struct tee_shm *shm; void *ret; int rc; - - if (ctx && ctx->teedev != teedev) { - dev_err(teedev->dev.parent, "ctx and teedev mismatch\n"); - return ERR_PTR(-EINVAL); - } if (!(flags & TEE_SHM_MAPPED)) { dev_err(teedev->dev.parent, @@ -73,7 +71,7 @@ return ERR_PTR(-EINVAL); } - if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF))) { + if ((flags & ~(TEE_SHM_MAPPED | TEE_SHM_DMA_BUF | TEE_SHM_PRIV))) { dev_err(teedev->dev.parent, "invalid shm flags 0x%x", flags); return ERR_PTR(-EINVAL); } @@ -95,7 +93,6 @@ refcount_set(&shm->refcount, 1); shm->flags = flags | TEE_SHM_POOL; - shm->teedev = teedev; shm->ctx = ctx; if (flags & TEE_SHM_DMA_BUF) poolm = teedev->pool->dma_buf_mgr; @@ -108,20 +105,17 @@ goto err_kfree; } - mutex_lock(&teedev->mutex); - shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); - mutex_unlock(&teedev->mutex); - if (shm->id < 0) { - ret = ERR_PTR(shm->id); - goto err_pool_free; + if (flags & TEE_SHM_DMA_BUF) { + mutex_lock(&teedev->mutex); + shm->id = idr_alloc(&teedev->idr, shm, 1, 0, GFP_KERNEL); + mutex_unlock(&teedev->mutex); + if (shm->id < 0) { + ret = ERR_PTR(shm->id); + goto err_pool_free; + } } - if (ctx) { - teedev_ctx_get(ctx); - mutex_lock(&teedev->mutex); - list_add_tail(&shm->link, &ctx->list_shm); - mutex_unlock(&teedev->mutex); - } + teedev_ctx_get(ctx); return shm; err_pool_free: @@ -132,43 +126,39 @@ tee_device_put(teedev); return ret; } - -/** - * tee_shm_alloc() - Allocate shared memory - * @ctx: Context that allocates the shared memory - * @size: Requested size of shared memory - * @flags: Flags setting properties for the requested shared memory. - * - * Memory allocated as global shared memory is automatically freed when the - * TEE file pointer is closed. The @flags field uses the bits defined by - * TEE_SHM_* in <linux/tee_drv.h>. TEE_SHM_MAPPED must currently always be - * set. If TEE_SHM_DMA_BUF global shared memory will be allocated and - * associated with a dma-buf handle, else driver private memory. - */ -struct tee_shm *tee_shm_alloc(struct tee_context *ctx, size_t size, u32 flags) -{ - return __tee_shm_alloc(ctx, ctx->teedev, size, flags); -} EXPORT_SYMBOL_GPL(tee_shm_alloc); -struct tee_shm *tee_shm_priv_alloc(struct tee_device *teedev, size_t size) +/** + * tee_shm_alloc_kernel_buf() - Allocate shared memory for kernel buffer + * @ctx: Context that allocates the shared memory + * @size: Requested size of shared memory + * + * The returned memory registered in secure world and is suitable to be + * passed as a memory buffer in parameter argument to + * tee_client_invoke_func(). The memory allocated is later freed with a + * call to tee_shm_free(). + * + * @returns a pointer to 'struct tee_shm' + */ +struct tee_shm *tee_shm_alloc_kernel_buf(struct tee_context *ctx, size_t size) { - return __tee_shm_alloc(NULL, teedev, size, TEE_SHM_MAPPED); + return tee_shm_alloc(ctx, size, TEE_SHM_MAPPED); } -EXPORT_SYMBOL_GPL(tee_shm_priv_alloc); +EXPORT_SYMBOL_GPL(tee_shm_alloc_kernel_buf); struct tee_shm *tee_shm_register(struct tee_context *ctx, unsigned long addr, size_t length, u32 flags) { struct tee_device *teedev = ctx->teedev; - const u32 req_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED; + const u32 req_user_flags = TEE_SHM_DMA_BUF | TEE_SHM_USER_MAPPED; + const u32 req_kernel_flags = TEE_SHM_DMA_BUF | TEE_SHM_KERNEL_MAPPED; struct tee_shm *shm; void *ret; int rc; int num_pages; unsigned long start; - if (flags != req_flags) + if (flags != req_user_flags && flags != req_kernel_flags) return ERR_PTR(-ENOTSUPP); if (!tee_device_get(teedev)) @@ -190,7 +180,6 @@ refcount_set(&shm->refcount, 1); shm->flags = flags | TEE_SHM_REGISTER; - shm->teedev = teedev; shm->ctx = ctx; shm->id = -1; addr = untagged_addr(addr); @@ -204,7 +193,27 @@ goto err; } - rc = get_user_pages_fast(start, num_pages, 1, shm->pages); + if (flags & TEE_SHM_USER_MAPPED) { + rc = pin_user_pages_fast(start, num_pages, FOLL_WRITE, + shm->pages); + } else { + struct kvec *kiov; + int i; + + kiov = kcalloc(num_pages, sizeof(*kiov), GFP_KERNEL); + if (!kiov) { + ret = ERR_PTR(-ENOMEM); + goto err; + } + + for (i = 0; i < num_pages; i++) { + kiov[i].iov_base = (void *)(start + i * PAGE_SIZE); + kiov[i].iov_len = PAGE_SIZE; + } + + rc = get_kernel_pages(kiov, num_pages, 0, shm->pages); + kfree(kiov); + } if (rc > 0) shm->num_pages = rc; if (rc != num_pages) { @@ -230,25 +239,15 @@ goto err; } - mutex_lock(&teedev->mutex); - list_add_tail(&shm->link, &ctx->list_shm); - mutex_unlock(&teedev->mutex); - return shm; err: if (shm) { - size_t n; - if (shm->id >= 0) { mutex_lock(&teedev->mutex); idr_remove(&teedev->idr, shm->id); mutex_unlock(&teedev->mutex); } - if (shm->pages) { - for (n = 0; n < shm->num_pages; n++) - put_page(shm->pages[n]); - kfree(shm->pages); - } + release_registered_pages(shm); } kfree(shm); teedev_ctx_put(ctx); @@ -439,7 +438,7 @@ */ void tee_shm_put(struct tee_shm *shm) { - struct tee_device *teedev = shm->teedev; + struct tee_device *teedev = shm->ctx->teedev; bool do_release = false; mutex_lock(&teedev->mutex); @@ -450,9 +449,8 @@ * the refcount_inc() in tee_shm_get_from_id() never starts * from 0. */ - idr_remove(&teedev->idr, shm->id); - if (shm->ctx) - list_del(&shm->link); + if (shm->flags & TEE_SHM_DMA_BUF) + idr_remove(&teedev->idr, shm->id); do_release = true; } mutex_unlock(&teedev->mutex); -- Gitblit v1.6.2