1c40a6505SJens Wiklander // SPDX-License-Identifier: BSD-2-Clause 2c40a6505SJens Wiklander /* 3c40a6505SJens Wiklander * Copyright (c) 2014, STMicroelectronics International N.V. 4c40a6505SJens Wiklander * Copyright (c) 2015-2020 Linaro Limited 5c40a6505SJens Wiklander */ 6c40a6505SJens Wiklander 7c40a6505SJens Wiklander #include <initcall.h> 8c40a6505SJens Wiklander #include <kernel/linker.h> 9c40a6505SJens Wiklander #include <kernel/user_access.h> 10*c185655eSJelle Sels #include <kernel/user_mode_ctx.h> 1189c9728dSJens Wiklander #include <mm/vm.h> 12c40a6505SJens Wiklander #include <string.h> 13c40a6505SJens Wiklander #include <tee_api_types.h> 14c40a6505SJens Wiklander #include <types_ext.h> 15c40a6505SJens Wiklander 167e4100f3SJens Wiklander static TEE_Result check_access(uint32_t flags, vaddr_t va, size_t len) 17c40a6505SJens Wiklander { 1800b3b9a2SJens Wiklander struct ts_session *s = ts_get_current_session(); 197e4100f3SJens Wiklander 20*c185655eSJelle Sels return vm_check_access_rights(to_user_mode_ctx(s->ctx), flags, va, len); 21c40a6505SJens Wiklander } 22c40a6505SJens Wiklander 23c40a6505SJens Wiklander TEE_Result copy_from_user(void *kaddr, const void *uaddr, size_t len) 24c40a6505SJens Wiklander { 257e4100f3SJens Wiklander uint32_t flags = TEE_MEMORY_ACCESS_READ | TEE_MEMORY_ACCESS_ANY_OWNER; 267e4100f3SJens Wiklander TEE_Result res = check_access(flags, (vaddr_t)uaddr, len); 27c40a6505SJens Wiklander 287e4100f3SJens Wiklander if (!res) 29c40a6505SJens Wiklander memcpy(kaddr, uaddr, len); 307e4100f3SJens Wiklander 317e4100f3SJens Wiklander return res; 32c40a6505SJens Wiklander } 33c40a6505SJens Wiklander 34c40a6505SJens Wiklander TEE_Result copy_to_user(void *uaddr, const void *kaddr, size_t len) 35c40a6505SJens Wiklander { 367e4100f3SJens Wiklander uint32_t flags = TEE_MEMORY_ACCESS_WRITE | TEE_MEMORY_ACCESS_ANY_OWNER; 377e4100f3SJens Wiklander TEE_Result res = check_access(flags, (vaddr_t)uaddr, len); 38c40a6505SJens Wiklander 397e4100f3SJens Wiklander if (!res) 40c40a6505SJens Wiklander memcpy(uaddr, kaddr, len); 417e4100f3SJens Wiklander 427e4100f3SJens Wiklander return res; 437e4100f3SJens Wiklander } 447e4100f3SJens Wiklander 457e4100f3SJens Wiklander TEE_Result copy_from_user_private(void *kaddr, const void *uaddr, size_t len) 467e4100f3SJens Wiklander { 477e4100f3SJens Wiklander uint32_t flags = TEE_MEMORY_ACCESS_READ; 487e4100f3SJens Wiklander TEE_Result res = check_access(flags, (vaddr_t)uaddr, len); 497e4100f3SJens Wiklander 507e4100f3SJens Wiklander if (!res) 517e4100f3SJens Wiklander memcpy(kaddr, uaddr, len); 527e4100f3SJens Wiklander 537e4100f3SJens Wiklander return res; 547e4100f3SJens Wiklander } 557e4100f3SJens Wiklander 567e4100f3SJens Wiklander TEE_Result copy_to_user_private(void *uaddr, const void *kaddr, size_t len) 577e4100f3SJens Wiklander { 587e4100f3SJens Wiklander uint32_t flags = TEE_MEMORY_ACCESS_WRITE; 597e4100f3SJens Wiklander TEE_Result res = check_access(flags, (vaddr_t)uaddr, len); 607e4100f3SJens Wiklander 617e4100f3SJens Wiklander if (!res) 627e4100f3SJens Wiklander memcpy(uaddr, kaddr, len); 637e4100f3SJens Wiklander 647e4100f3SJens Wiklander return res; 65c40a6505SJens Wiklander } 66c40a6505SJens Wiklander 67c40a6505SJens Wiklander TEE_Result copy_kaddr_to_uref(uint32_t *uref, void *kaddr) 68c40a6505SJens Wiklander { 69c40a6505SJens Wiklander uint32_t ref = kaddr_to_uref(kaddr); 70c40a6505SJens Wiklander 717e4100f3SJens Wiklander return copy_to_user_private(uref, &ref, sizeof(ref)); 72c40a6505SJens Wiklander } 73c40a6505SJens Wiklander 74c40a6505SJens Wiklander uint32_t kaddr_to_uref(void *kaddr) 75c40a6505SJens Wiklander { 76c40a6505SJens Wiklander assert(((vaddr_t)kaddr - VCORE_START_VA) < UINT32_MAX); 77c40a6505SJens Wiklander return (vaddr_t)kaddr - VCORE_START_VA; 78c40a6505SJens Wiklander } 79c40a6505SJens Wiklander 80c40a6505SJens Wiklander vaddr_t uref_to_vaddr(uint32_t uref) 81c40a6505SJens Wiklander { 82c40a6505SJens Wiklander return VCORE_START_VA + uref; 83c40a6505SJens Wiklander } 84