1185b4595SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 2185b4595SMarouene Boubakri /* 36105aa86SJens Wiklander * Copyright (c) 2016-2022, Linaro Limited 4185b4595SMarouene Boubakri */ 5185b4595SMarouene Boubakri 6185b4595SMarouene Boubakri #include <assert.h> 7ff01e245SAnton Rybakov #include <config.h> 8185b4595SMarouene Boubakri #include <initcall.h> 9185b4595SMarouene Boubakri #include <keep.h> 10185b4595SMarouene Boubakri #include <kernel/linker.h> 11185b4595SMarouene Boubakri #include <kernel/mutex.h> 12185b4595SMarouene Boubakri #include <kernel/panic.h> 13185b4595SMarouene Boubakri #include <kernel/refcount.h> 14185b4595SMarouene Boubakri #include <kernel/spinlock.h> 15185b4595SMarouene Boubakri #include <mm/core_mmu.h> 16185b4595SMarouene Boubakri #include <mm/mobj.h> 17185b4595SMarouene Boubakri #include <mm/tee_pager.h> 18185b4595SMarouene Boubakri #include <optee_msg.h> 19185b4595SMarouene Boubakri #include <stdlib.h> 20185b4595SMarouene Boubakri #include <tee_api_types.h> 21185b4595SMarouene Boubakri #include <types_ext.h> 22185b4595SMarouene Boubakri #include <util.h> 23185b4595SMarouene Boubakri 24ff01e245SAnton Rybakov struct mobj *mobj_tee_ram_rx; 25ff01e245SAnton Rybakov struct mobj *mobj_tee_ram_rw; 26185b4595SMarouene Boubakri 27185b4595SMarouene Boubakri /* 28185b4595SMarouene Boubakri * mobj_phys implementation 29185b4595SMarouene Boubakri */ 30185b4595SMarouene Boubakri 31185b4595SMarouene Boubakri struct mobj_phys { 32185b4595SMarouene Boubakri struct mobj mobj; 33185b4595SMarouene Boubakri enum buf_is_attr battr; 348afe7a7cSJens Wiklander /* Defined by TEE_MATTR_MEM_TYPE_* in tee_mmu_types.h */ 358afe7a7cSJens Wiklander uint32_t mem_type; 36185b4595SMarouene Boubakri vaddr_t va; 37185b4595SMarouene Boubakri paddr_t pa; 38185b4595SMarouene Boubakri }; 39185b4595SMarouene Boubakri 40185b4595SMarouene Boubakri static struct mobj_phys *to_mobj_phys(struct mobj *mobj); 41185b4595SMarouene Boubakri 429c4aaf67SJens Wiklander static void *mobj_phys_get_va(struct mobj *mobj, size_t offset, size_t len) 43185b4595SMarouene Boubakri { 44185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 45185b4595SMarouene Boubakri 469c4aaf67SJens Wiklander if (!moph->va || !mobj_check_offset_and_len(mobj, offset, len)) 47185b4595SMarouene Boubakri return NULL; 48185b4595SMarouene Boubakri 49185b4595SMarouene Boubakri return (void *)(moph->va + offset); 50185b4595SMarouene Boubakri } 51185b4595SMarouene Boubakri 52185b4595SMarouene Boubakri static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs, 53185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 54185b4595SMarouene Boubakri { 55185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 56185b4595SMarouene Boubakri paddr_t p; 57185b4595SMarouene Boubakri 58185b4595SMarouene Boubakri if (!pa) 59185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 60185b4595SMarouene Boubakri 61185b4595SMarouene Boubakri p = moph->pa + offs; 62185b4595SMarouene Boubakri 63185b4595SMarouene Boubakri if (granule) { 64185b4595SMarouene Boubakri if (granule != SMALL_PAGE_SIZE && 65185b4595SMarouene Boubakri granule != CORE_MMU_PGDIR_SIZE) 66185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 67185b4595SMarouene Boubakri p &= ~(granule - 1); 68185b4595SMarouene Boubakri } 69185b4595SMarouene Boubakri 70185b4595SMarouene Boubakri *pa = p; 71185b4595SMarouene Boubakri return TEE_SUCCESS; 72185b4595SMarouene Boubakri } 73185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_phys_get_pa); 74185b4595SMarouene Boubakri 758afe7a7cSJens Wiklander static TEE_Result mobj_phys_get_mem_type(struct mobj *mobj, uint32_t *mem_type) 76185b4595SMarouene Boubakri { 77185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 78185b4595SMarouene Boubakri 798afe7a7cSJens Wiklander if (!mem_type) 80185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 81185b4595SMarouene Boubakri 828afe7a7cSJens Wiklander *mem_type = moph->mem_type; 83185b4595SMarouene Boubakri return TEE_SUCCESS; 84185b4595SMarouene Boubakri } 85185b4595SMarouene Boubakri 86185b4595SMarouene Boubakri static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr) 87185b4595SMarouene Boubakri { 88185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 89185b4595SMarouene Boubakri enum buf_is_attr a; 90185b4595SMarouene Boubakri 91185b4595SMarouene Boubakri a = moph->battr; 92185b4595SMarouene Boubakri 93185b4595SMarouene Boubakri switch (attr) { 94185b4595SMarouene Boubakri case CORE_MEM_SEC: 95185b4595SMarouene Boubakri return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM || 96185b4595SMarouene Boubakri a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM; 97185b4595SMarouene Boubakri case CORE_MEM_NON_SEC: 98185b4595SMarouene Boubakri return a == CORE_MEM_NSEC_SHM; 99185b4595SMarouene Boubakri case CORE_MEM_TEE_RAM: 100185b4595SMarouene Boubakri case CORE_MEM_TA_RAM: 101185b4595SMarouene Boubakri case CORE_MEM_NSEC_SHM: 102185b4595SMarouene Boubakri case CORE_MEM_SDP_MEM: 103185b4595SMarouene Boubakri return attr == a; 104185b4595SMarouene Boubakri default: 105185b4595SMarouene Boubakri return false; 106185b4595SMarouene Boubakri } 107185b4595SMarouene Boubakri } 108185b4595SMarouene Boubakri 109185b4595SMarouene Boubakri static void mobj_phys_free(struct mobj *mobj) 110185b4595SMarouene Boubakri { 111185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 112185b4595SMarouene Boubakri 113185b4595SMarouene Boubakri free(moph); 114185b4595SMarouene Boubakri } 115185b4595SMarouene Boubakri 11600361c18SJens Wiklander /* 11700361c18SJens Wiklander * Note: this variable is weak just to ease breaking its dependency chain 11800361c18SJens Wiklander * when added to the unpaged area. 11900361c18SJens Wiklander */ 12039e8c200SJerome Forissier const struct mobj_ops mobj_phys_ops 12139e8c200SJerome Forissier __weak __relrodata_unpaged("mobj_phys_ops") = { 122185b4595SMarouene Boubakri .get_va = mobj_phys_get_va, 123185b4595SMarouene Boubakri .get_pa = mobj_phys_get_pa, 124185b4595SMarouene Boubakri .get_phys_offs = NULL, /* only offset 0 */ 1258afe7a7cSJens Wiklander .get_mem_type = mobj_phys_get_mem_type, 126185b4595SMarouene Boubakri .matches = mobj_phys_matches, 127185b4595SMarouene Boubakri .free = mobj_phys_free, 128185b4595SMarouene Boubakri }; 129185b4595SMarouene Boubakri 130185b4595SMarouene Boubakri static struct mobj_phys *to_mobj_phys(struct mobj *mobj) 131185b4595SMarouene Boubakri { 132185b4595SMarouene Boubakri assert(mobj->ops == &mobj_phys_ops); 133185b4595SMarouene Boubakri return container_of(mobj, struct mobj_phys, mobj); 134185b4595SMarouene Boubakri } 135185b4595SMarouene Boubakri 1368afe7a7cSJens Wiklander static struct mobj *mobj_phys_init(paddr_t pa, size_t size, uint32_t mem_type, 137ff01e245SAnton Rybakov enum buf_is_attr battr, 138ff01e245SAnton Rybakov enum teecore_memtypes area_type) 139185b4595SMarouene Boubakri { 140ff01e245SAnton Rybakov void *va = NULL; 141ff01e245SAnton Rybakov struct mobj_phys *moph = NULL; 142b715a420SAnton Rybakov struct tee_mmap_region *map = NULL; 143185b4595SMarouene Boubakri 144185b4595SMarouene Boubakri if ((pa & CORE_MMU_USER_PARAM_MASK) || 145185b4595SMarouene Boubakri (size & CORE_MMU_USER_PARAM_MASK)) { 146185b4595SMarouene Boubakri DMSG("Expect %#x alignment", CORE_MMU_USER_PARAM_SIZE); 147185b4595SMarouene Boubakri return NULL; 148185b4595SMarouene Boubakri } 149185b4595SMarouene Boubakri 150b715a420SAnton Rybakov if (pa) { 151c2e4eb43SAnton Rybakov va = phys_to_virt(pa, area_type, size); 152b715a420SAnton Rybakov } else { 153b715a420SAnton Rybakov map = core_mmu_find_mapping_exclusive(area_type, size); 154b715a420SAnton Rybakov if (!map) 155b715a420SAnton Rybakov return NULL; 156b715a420SAnton Rybakov 157b715a420SAnton Rybakov pa = map->pa; 158b715a420SAnton Rybakov va = (void *)map->va; 159b715a420SAnton Rybakov } 160b715a420SAnton Rybakov 161b715a420SAnton Rybakov /* Only SDP memory may not have a virtual address */ 162185b4595SMarouene Boubakri if (!va && battr != CORE_MEM_SDP_MEM) 163185b4595SMarouene Boubakri return NULL; 164185b4595SMarouene Boubakri 165185b4595SMarouene Boubakri moph = calloc(1, sizeof(*moph)); 166185b4595SMarouene Boubakri if (!moph) 167185b4595SMarouene Boubakri return NULL; 168185b4595SMarouene Boubakri 169185b4595SMarouene Boubakri moph->battr = battr; 1708afe7a7cSJens Wiklander moph->mem_type = mem_type; 171185b4595SMarouene Boubakri moph->mobj.size = size; 172185b4595SMarouene Boubakri moph->mobj.ops = &mobj_phys_ops; 173185b4595SMarouene Boubakri refcount_set(&moph->mobj.refc, 1); 174185b4595SMarouene Boubakri moph->pa = pa; 175185b4595SMarouene Boubakri moph->va = (vaddr_t)va; 176185b4595SMarouene Boubakri 177185b4595SMarouene Boubakri return &moph->mobj; 178185b4595SMarouene Boubakri } 179185b4595SMarouene Boubakri 1808afe7a7cSJens Wiklander struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t mem_type, 181ff01e245SAnton Rybakov enum buf_is_attr battr) 182ff01e245SAnton Rybakov { 183ff01e245SAnton Rybakov enum teecore_memtypes area_type; 184ff01e245SAnton Rybakov 185ff01e245SAnton Rybakov switch (battr) { 186ff01e245SAnton Rybakov case CORE_MEM_NSEC_SHM: 187ff01e245SAnton Rybakov area_type = MEM_AREA_NSEC_SHM; 188ff01e245SAnton Rybakov break; 189ff01e245SAnton Rybakov case CORE_MEM_SDP_MEM: 190ff01e245SAnton Rybakov area_type = MEM_AREA_SDP_MEM; 191ff01e245SAnton Rybakov break; 192ff01e245SAnton Rybakov default: 193ff01e245SAnton Rybakov DMSG("can't allocate with specified attribute"); 194ff01e245SAnton Rybakov return NULL; 195ff01e245SAnton Rybakov } 196ff01e245SAnton Rybakov 1978afe7a7cSJens Wiklander return mobj_phys_init(pa, size, mem_type, battr, area_type); 198ff01e245SAnton Rybakov } 199ff01e245SAnton Rybakov 200185b4595SMarouene Boubakri /* 201185b4595SMarouene Boubakri * mobj_virt implementation 202185b4595SMarouene Boubakri */ 203185b4595SMarouene Boubakri 204185b4595SMarouene Boubakri static void mobj_virt_assert_type(struct mobj *mobj); 205185b4595SMarouene Boubakri 2069c4aaf67SJens Wiklander static void *mobj_virt_get_va(struct mobj *mobj, size_t offset, 2079c4aaf67SJens Wiklander size_t len __maybe_unused) 208185b4595SMarouene Boubakri { 209185b4595SMarouene Boubakri mobj_virt_assert_type(mobj); 2109c4aaf67SJens Wiklander assert(mobj_check_offset_and_len(mobj, offset, len)); 211185b4595SMarouene Boubakri 212185b4595SMarouene Boubakri return (void *)(vaddr_t)offset; 213185b4595SMarouene Boubakri } 214185b4595SMarouene Boubakri 21500361c18SJens Wiklander /* 21600361c18SJens Wiklander * Note: this variable is weak just to ease breaking its dependency chain 21700361c18SJens Wiklander * when added to the unpaged area. 21800361c18SJens Wiklander */ 21939e8c200SJerome Forissier const struct mobj_ops mobj_virt_ops 22039e8c200SJerome Forissier __weak __relrodata_unpaged("mobj_virt_ops") = { 221185b4595SMarouene Boubakri .get_va = mobj_virt_get_va, 222185b4595SMarouene Boubakri }; 223185b4595SMarouene Boubakri 224185b4595SMarouene Boubakri static void mobj_virt_assert_type(struct mobj *mobj __maybe_unused) 225185b4595SMarouene Boubakri { 226185b4595SMarouene Boubakri assert(mobj->ops == &mobj_virt_ops); 227185b4595SMarouene Boubakri } 228185b4595SMarouene Boubakri 229185b4595SMarouene Boubakri struct mobj mobj_virt = { .ops = &mobj_virt_ops, .size = SIZE_MAX }; 230185b4595SMarouene Boubakri 231185b4595SMarouene Boubakri /* 232185b4595SMarouene Boubakri * mobj_shm implementation. mobj_shm represents buffer in predefined shm region 233185b4595SMarouene Boubakri * - it is physically contiguous. 234185b4595SMarouene Boubakri * - it is identified in static physical layout as MEM_AREA_NSEC_SHM. 235185b4595SMarouene Boubakri * - it creates mobjs that match specific CORE_MEM_NSEC_SHM and non secure 236185b4595SMarouene Boubakri * generic CORE_MEM_NON_SEC. 237185b4595SMarouene Boubakri */ 238185b4595SMarouene Boubakri 239185b4595SMarouene Boubakri struct mobj_shm { 240185b4595SMarouene Boubakri struct mobj mobj; 241185b4595SMarouene Boubakri paddr_t pa; 242185b4595SMarouene Boubakri uint64_t cookie; 243185b4595SMarouene Boubakri }; 244185b4595SMarouene Boubakri 245185b4595SMarouene Boubakri static struct mobj_shm *to_mobj_shm(struct mobj *mobj); 246185b4595SMarouene Boubakri 2479c4aaf67SJens Wiklander static void *mobj_shm_get_va(struct mobj *mobj, size_t offset, size_t len) 248185b4595SMarouene Boubakri { 249185b4595SMarouene Boubakri struct mobj_shm *m = to_mobj_shm(mobj); 250185b4595SMarouene Boubakri 2519c4aaf67SJens Wiklander if (!mobj_check_offset_and_len(mobj, offset, len)) 252185b4595SMarouene Boubakri return NULL; 253185b4595SMarouene Boubakri 254c2e4eb43SAnton Rybakov return phys_to_virt(m->pa + offset, MEM_AREA_NSEC_SHM, 255c2e4eb43SAnton Rybakov mobj->size - offset); 256185b4595SMarouene Boubakri } 257185b4595SMarouene Boubakri 258185b4595SMarouene Boubakri static TEE_Result mobj_shm_get_pa(struct mobj *mobj, size_t offs, 259185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 260185b4595SMarouene Boubakri { 261185b4595SMarouene Boubakri struct mobj_shm *m = to_mobj_shm(mobj); 262185b4595SMarouene Boubakri paddr_t p; 263185b4595SMarouene Boubakri 264185b4595SMarouene Boubakri if (!pa || offs >= mobj->size) 265185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 266185b4595SMarouene Boubakri 267185b4595SMarouene Boubakri p = m->pa + offs; 268185b4595SMarouene Boubakri 269185b4595SMarouene Boubakri if (granule) { 270185b4595SMarouene Boubakri if (granule != SMALL_PAGE_SIZE && 271185b4595SMarouene Boubakri granule != CORE_MMU_PGDIR_SIZE) 272185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 273185b4595SMarouene Boubakri p &= ~(granule - 1); 274185b4595SMarouene Boubakri } 275185b4595SMarouene Boubakri 276185b4595SMarouene Boubakri *pa = p; 277185b4595SMarouene Boubakri return TEE_SUCCESS; 278185b4595SMarouene Boubakri } 279185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_shm_get_pa); 280185b4595SMarouene Boubakri 281185b4595SMarouene Boubakri static size_t mobj_shm_get_phys_offs(struct mobj *mobj, size_t granule) 282185b4595SMarouene Boubakri { 283185b4595SMarouene Boubakri assert(IS_POWER_OF_TWO(granule)); 284185b4595SMarouene Boubakri return to_mobj_shm(mobj)->pa & (granule - 1); 285185b4595SMarouene Boubakri } 286185b4595SMarouene Boubakri 287185b4595SMarouene Boubakri static bool mobj_shm_matches(struct mobj *mobj __unused, enum buf_is_attr attr) 288185b4595SMarouene Boubakri { 289185b4595SMarouene Boubakri return attr == CORE_MEM_NSEC_SHM || attr == CORE_MEM_NON_SEC; 290185b4595SMarouene Boubakri } 291185b4595SMarouene Boubakri 2928afe7a7cSJens Wiklander static TEE_Result mobj_shm_get_mem_type(struct mobj *mobj __unused, 2938afe7a7cSJens Wiklander uint32_t *mem_type) 294e31a75b3SLejia Zhang { 2958afe7a7cSJens Wiklander if (!mem_type) 296e31a75b3SLejia Zhang return TEE_ERROR_GENERIC; 297e31a75b3SLejia Zhang 2988afe7a7cSJens Wiklander *mem_type = TEE_MATTR_MEM_TYPE_CACHED; 299e31a75b3SLejia Zhang 300e31a75b3SLejia Zhang return TEE_SUCCESS; 301e31a75b3SLejia Zhang } 302e31a75b3SLejia Zhang 303185b4595SMarouene Boubakri static void mobj_shm_free(struct mobj *mobj) 304185b4595SMarouene Boubakri { 305185b4595SMarouene Boubakri struct mobj_shm *m = to_mobj_shm(mobj); 306185b4595SMarouene Boubakri 307185b4595SMarouene Boubakri free(m); 308185b4595SMarouene Boubakri } 309185b4595SMarouene Boubakri 310185b4595SMarouene Boubakri static uint64_t mobj_shm_get_cookie(struct mobj *mobj) 311185b4595SMarouene Boubakri { 312185b4595SMarouene Boubakri return to_mobj_shm(mobj)->cookie; 313185b4595SMarouene Boubakri } 314185b4595SMarouene Boubakri 31500361c18SJens Wiklander /* 31600361c18SJens Wiklander * Note: this variable is weak just to ease breaking its dependency chain 31700361c18SJens Wiklander * when added to the unpaged area. 31800361c18SJens Wiklander */ 31939e8c200SJerome Forissier const struct mobj_ops mobj_shm_ops 32039e8c200SJerome Forissier __weak __relrodata_unpaged("mobj_shm_ops") = { 321185b4595SMarouene Boubakri .get_va = mobj_shm_get_va, 322185b4595SMarouene Boubakri .get_pa = mobj_shm_get_pa, 323185b4595SMarouene Boubakri .get_phys_offs = mobj_shm_get_phys_offs, 3248afe7a7cSJens Wiklander .get_mem_type = mobj_shm_get_mem_type, 325185b4595SMarouene Boubakri .matches = mobj_shm_matches, 326185b4595SMarouene Boubakri .free = mobj_shm_free, 327185b4595SMarouene Boubakri .get_cookie = mobj_shm_get_cookie, 328185b4595SMarouene Boubakri }; 329185b4595SMarouene Boubakri 330185b4595SMarouene Boubakri static struct mobj_shm *to_mobj_shm(struct mobj *mobj) 331185b4595SMarouene Boubakri { 332185b4595SMarouene Boubakri assert(mobj->ops == &mobj_shm_ops); 333185b4595SMarouene Boubakri return container_of(mobj, struct mobj_shm, mobj); 334185b4595SMarouene Boubakri } 335185b4595SMarouene Boubakri 336185b4595SMarouene Boubakri struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie) 337185b4595SMarouene Boubakri { 338185b4595SMarouene Boubakri struct mobj_shm *m; 339185b4595SMarouene Boubakri 340185b4595SMarouene Boubakri if (!core_pbuf_is(CORE_MEM_NSEC_SHM, pa, size)) 341185b4595SMarouene Boubakri return NULL; 342185b4595SMarouene Boubakri 343185b4595SMarouene Boubakri m = calloc(1, sizeof(*m)); 344185b4595SMarouene Boubakri if (!m) 345185b4595SMarouene Boubakri return NULL; 346185b4595SMarouene Boubakri 347185b4595SMarouene Boubakri m->mobj.size = size; 348185b4595SMarouene Boubakri m->mobj.ops = &mobj_shm_ops; 349e31a75b3SLejia Zhang m->mobj.phys_granule = SMALL_PAGE_SIZE; 350185b4595SMarouene Boubakri refcount_set(&m->mobj.refc, 1); 351185b4595SMarouene Boubakri m->pa = pa; 352185b4595SMarouene Boubakri m->cookie = cookie; 353185b4595SMarouene Boubakri 354185b4595SMarouene Boubakri return &m->mobj; 355185b4595SMarouene Boubakri } 356185b4595SMarouene Boubakri 357185b4595SMarouene Boubakri struct mobj_with_fobj { 358185b4595SMarouene Boubakri struct fobj *fobj; 359185b4595SMarouene Boubakri struct file *file; 360185b4595SMarouene Boubakri struct mobj mobj; 3616105aa86SJens Wiklander uint8_t mem_type; 362185b4595SMarouene Boubakri }; 363185b4595SMarouene Boubakri 36400361c18SJens Wiklander const struct mobj_ops mobj_with_fobj_ops; 365185b4595SMarouene Boubakri 3666105aa86SJens Wiklander struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file, 3676105aa86SJens Wiklander uint32_t mem_type) 368185b4595SMarouene Boubakri { 369185b4595SMarouene Boubakri struct mobj_with_fobj *m = NULL; 370185b4595SMarouene Boubakri 3716105aa86SJens Wiklander assert(!(mem_type & ~TEE_MATTR_MEM_TYPE_MASK)); 3726105aa86SJens Wiklander 373185b4595SMarouene Boubakri if (!fobj) 374185b4595SMarouene Boubakri return NULL; 3756105aa86SJens Wiklander if (mem_type > UINT8_MAX) 3766105aa86SJens Wiklander return NULL; 377185b4595SMarouene Boubakri 378185b4595SMarouene Boubakri m = calloc(1, sizeof(*m)); 379185b4595SMarouene Boubakri if (!m) 380185b4595SMarouene Boubakri return NULL; 381185b4595SMarouene Boubakri 382185b4595SMarouene Boubakri m->mobj.ops = &mobj_with_fobj_ops; 383185b4595SMarouene Boubakri refcount_set(&m->mobj.refc, 1); 384185b4595SMarouene Boubakri m->mobj.size = fobj->num_pages * SMALL_PAGE_SIZE; 385185b4595SMarouene Boubakri m->mobj.phys_granule = SMALL_PAGE_SIZE; 386185b4595SMarouene Boubakri m->fobj = fobj_get(fobj); 387185b4595SMarouene Boubakri m->file = file_get(file); 3886105aa86SJens Wiklander m->mem_type = mem_type; 389185b4595SMarouene Boubakri 390185b4595SMarouene Boubakri return &m->mobj; 391185b4595SMarouene Boubakri } 392185b4595SMarouene Boubakri 393185b4595SMarouene Boubakri static struct mobj_with_fobj *to_mobj_with_fobj(struct mobj *mobj) 394185b4595SMarouene Boubakri { 395185b4595SMarouene Boubakri assert(mobj && mobj->ops == &mobj_with_fobj_ops); 396185b4595SMarouene Boubakri 397185b4595SMarouene Boubakri return container_of(mobj, struct mobj_with_fobj, mobj); 398185b4595SMarouene Boubakri } 399185b4595SMarouene Boubakri 400185b4595SMarouene Boubakri static bool mobj_with_fobj_matches(struct mobj *mobj __maybe_unused, 401185b4595SMarouene Boubakri enum buf_is_attr attr) 402185b4595SMarouene Boubakri { 403185b4595SMarouene Boubakri assert(to_mobj_with_fobj(mobj)); 404185b4595SMarouene Boubakri 405185b4595SMarouene Boubakri /* 406185b4595SMarouene Boubakri * All fobjs are supposed to be mapped secure so classify it as 407185b4595SMarouene Boubakri * CORE_MEM_SEC. Stay out of CORE_MEM_TEE_RAM etc, if that information 408185b4595SMarouene Boubakri * needed it can probably be carried in another way than to put the 409185b4595SMarouene Boubakri * burden directly on fobj. 410185b4595SMarouene Boubakri */ 411185b4595SMarouene Boubakri return attr == CORE_MEM_SEC; 412185b4595SMarouene Boubakri } 413185b4595SMarouene Boubakri 414185b4595SMarouene Boubakri static void mobj_with_fobj_free(struct mobj *mobj) 415185b4595SMarouene Boubakri { 416185b4595SMarouene Boubakri struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); 417185b4595SMarouene Boubakri 418185b4595SMarouene Boubakri fobj_put(m->fobj); 419185b4595SMarouene Boubakri file_put(m->file); 420185b4595SMarouene Boubakri free(m); 421185b4595SMarouene Boubakri } 422185b4595SMarouene Boubakri 423185b4595SMarouene Boubakri static struct fobj *mobj_with_fobj_get_fobj(struct mobj *mobj) 424185b4595SMarouene Boubakri { 425185b4595SMarouene Boubakri return fobj_get(to_mobj_with_fobj(mobj)->fobj); 426185b4595SMarouene Boubakri } 427185b4595SMarouene Boubakri 4286105aa86SJens Wiklander static TEE_Result mobj_with_fobj_get_mem_type(struct mobj *mobj, 4298afe7a7cSJens Wiklander uint32_t *mem_type) 430185b4595SMarouene Boubakri { 4316105aa86SJens Wiklander struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); 4326105aa86SJens Wiklander 4338afe7a7cSJens Wiklander if (!mem_type) 434185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 435185b4595SMarouene Boubakri 4366105aa86SJens Wiklander *mem_type = m->mem_type; 437185b4595SMarouene Boubakri 438185b4595SMarouene Boubakri return TEE_SUCCESS; 439185b4595SMarouene Boubakri } 440185b4595SMarouene Boubakri 441185b4595SMarouene Boubakri static TEE_Result mobj_with_fobj_get_pa(struct mobj *mobj, size_t offs, 442185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 443185b4595SMarouene Boubakri { 444185b4595SMarouene Boubakri struct mobj_with_fobj *f = to_mobj_with_fobj(mobj); 445185b4595SMarouene Boubakri paddr_t p = 0; 446185b4595SMarouene Boubakri 447185b4595SMarouene Boubakri if (!f->fobj->ops->get_pa) { 448185b4595SMarouene Boubakri assert(mobj_is_paged(mobj)); 449185b4595SMarouene Boubakri return TEE_ERROR_NOT_SUPPORTED; 450185b4595SMarouene Boubakri } 451185b4595SMarouene Boubakri 452185b4595SMarouene Boubakri p = f->fobj->ops->get_pa(f->fobj, offs / SMALL_PAGE_SIZE) + 453185b4595SMarouene Boubakri offs % SMALL_PAGE_SIZE; 454185b4595SMarouene Boubakri 455185b4595SMarouene Boubakri if (granule) { 456185b4595SMarouene Boubakri if (granule != SMALL_PAGE_SIZE && 457185b4595SMarouene Boubakri granule != CORE_MMU_PGDIR_SIZE) 458185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 459185b4595SMarouene Boubakri p &= ~(granule - 1); 460185b4595SMarouene Boubakri } 461185b4595SMarouene Boubakri 462185b4595SMarouene Boubakri *pa = p; 463185b4595SMarouene Boubakri 464185b4595SMarouene Boubakri return TEE_SUCCESS; 465185b4595SMarouene Boubakri } 466185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_with_fobj_get_pa); 467185b4595SMarouene Boubakri 46800361c18SJens Wiklander /* 46900361c18SJens Wiklander * Note: this variable is weak just to ease breaking its dependency chain 47000361c18SJens Wiklander * when added to the unpaged area. 47100361c18SJens Wiklander */ 47200361c18SJens Wiklander const struct mobj_ops mobj_with_fobj_ops 47339e8c200SJerome Forissier __weak __relrodata_unpaged("mobj_with_fobj_ops") = { 474185b4595SMarouene Boubakri .matches = mobj_with_fobj_matches, 475185b4595SMarouene Boubakri .free = mobj_with_fobj_free, 476185b4595SMarouene Boubakri .get_fobj = mobj_with_fobj_get_fobj, 4778afe7a7cSJens Wiklander .get_mem_type = mobj_with_fobj_get_mem_type, 478185b4595SMarouene Boubakri .get_pa = mobj_with_fobj_get_pa, 479185b4595SMarouene Boubakri }; 480185b4595SMarouene Boubakri 481185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA 482185b4595SMarouene Boubakri bool mobj_is_paged(struct mobj *mobj) 483185b4595SMarouene Boubakri { 484185b4595SMarouene Boubakri if (mobj->ops == &mobj_with_fobj_ops && 485185b4595SMarouene Boubakri !to_mobj_with_fobj(mobj)->fobj->ops->get_pa) 486185b4595SMarouene Boubakri return true; 487185b4595SMarouene Boubakri 488185b4595SMarouene Boubakri return false; 489185b4595SMarouene Boubakri } 490185b4595SMarouene Boubakri #endif /*CFG_PAGED_USER_TA*/ 491185b4595SMarouene Boubakri 492185b4595SMarouene Boubakri static TEE_Result mobj_init(void) 493185b4595SMarouene Boubakri { 494ff01e245SAnton Rybakov if (IS_ENABLED(CFG_CORE_RWDATA_NOEXEC)) { 495b715a420SAnton Rybakov mobj_tee_ram_rx = mobj_phys_init(0, 496ff01e245SAnton Rybakov VCORE_UNPG_RX_SZ, 4978b427282SJelle Sels TEE_MATTR_MEM_TYPE_CACHED, 498ff01e245SAnton Rybakov CORE_MEM_TEE_RAM, 499ff01e245SAnton Rybakov MEM_AREA_TEE_RAM_RX); 500ff01e245SAnton Rybakov if (!mobj_tee_ram_rx) 501ff01e245SAnton Rybakov panic("Failed to register tee ram rx"); 502ff01e245SAnton Rybakov 503b715a420SAnton Rybakov mobj_tee_ram_rw = mobj_phys_init(0, 504ff01e245SAnton Rybakov VCORE_UNPG_RW_SZ, 5058b427282SJelle Sels TEE_MATTR_MEM_TYPE_CACHED, 506ff01e245SAnton Rybakov CORE_MEM_TEE_RAM, 507ff01e245SAnton Rybakov MEM_AREA_TEE_RAM_RW_DATA); 508ff01e245SAnton Rybakov if (!mobj_tee_ram_rw) 509ff01e245SAnton Rybakov panic("Failed to register tee ram rw"); 510ff01e245SAnton Rybakov } else { 511ff01e245SAnton Rybakov mobj_tee_ram_rw = mobj_phys_init(TEE_RAM_START, 512ff01e245SAnton Rybakov VCORE_UNPG_RW_PA + 513ff01e245SAnton Rybakov VCORE_UNPG_RW_SZ - 514*3de913f6SJens Wiklander VCORE_START_VA, 5158b427282SJelle Sels TEE_MATTR_MEM_TYPE_CACHED, 516ff01e245SAnton Rybakov CORE_MEM_TEE_RAM, 517ff01e245SAnton Rybakov MEM_AREA_TEE_RAM_RW_DATA); 518ff01e245SAnton Rybakov if (!mobj_tee_ram_rw) 519185b4595SMarouene Boubakri panic("Failed to register tee ram"); 520185b4595SMarouene Boubakri 521ff01e245SAnton Rybakov mobj_tee_ram_rx = mobj_tee_ram_rw; 522ff01e245SAnton Rybakov } 523ff01e245SAnton Rybakov 524185b4595SMarouene Boubakri return TEE_SUCCESS; 525185b4595SMarouene Boubakri } 526185b4595SMarouene Boubakri 527185b4595SMarouene Boubakri driver_init_late(mobj_init); 528