1*185b4595SMarouene Boubakri // SPDX-License-Identifier: BSD-2-Clause 2*185b4595SMarouene Boubakri /* 3*185b4595SMarouene Boubakri * Copyright (c) 2016-2017, Linaro Limited 4*185b4595SMarouene Boubakri */ 5*185b4595SMarouene Boubakri 6*185b4595SMarouene Boubakri #include <assert.h> 7*185b4595SMarouene Boubakri #include <initcall.h> 8*185b4595SMarouene Boubakri #include <keep.h> 9*185b4595SMarouene Boubakri #include <kernel/linker.h> 10*185b4595SMarouene Boubakri #include <kernel/mutex.h> 11*185b4595SMarouene Boubakri #include <kernel/panic.h> 12*185b4595SMarouene Boubakri #include <kernel/refcount.h> 13*185b4595SMarouene Boubakri #include <kernel/spinlock.h> 14*185b4595SMarouene Boubakri #include <kernel/tee_misc.h> 15*185b4595SMarouene Boubakri #include <mm/core_mmu.h> 16*185b4595SMarouene Boubakri #include <mm/mobj.h> 17*185b4595SMarouene Boubakri #include <mm/tee_pager.h> 18*185b4595SMarouene Boubakri #include <mm/vm.h> 19*185b4595SMarouene Boubakri #include <optee_msg.h> 20*185b4595SMarouene Boubakri #include <sm/optee_smc.h> 21*185b4595SMarouene Boubakri #include <stdlib.h> 22*185b4595SMarouene Boubakri #include <tee_api_types.h> 23*185b4595SMarouene Boubakri #include <types_ext.h> 24*185b4595SMarouene Boubakri #include <util.h> 25*185b4595SMarouene Boubakri 26*185b4595SMarouene Boubakri struct mobj *mobj_sec_ddr; 27*185b4595SMarouene Boubakri struct mobj *mobj_tee_ram; 28*185b4595SMarouene Boubakri 29*185b4595SMarouene Boubakri /* 30*185b4595SMarouene Boubakri * mobj_phys implementation 31*185b4595SMarouene Boubakri */ 32*185b4595SMarouene Boubakri 33*185b4595SMarouene Boubakri struct mobj_phys { 34*185b4595SMarouene Boubakri struct mobj mobj; 35*185b4595SMarouene Boubakri enum buf_is_attr battr; 36*185b4595SMarouene Boubakri uint32_t cattr; /* Defined by TEE_MATTR_CACHE_* in tee_mmu_types.h */ 37*185b4595SMarouene Boubakri vaddr_t va; 38*185b4595SMarouene Boubakri paddr_t pa; 39*185b4595SMarouene Boubakri }; 40*185b4595SMarouene Boubakri 41*185b4595SMarouene Boubakri static struct mobj_phys *to_mobj_phys(struct mobj *mobj); 42*185b4595SMarouene Boubakri 43*185b4595SMarouene Boubakri static void *mobj_phys_get_va(struct mobj *mobj, size_t offset) 44*185b4595SMarouene Boubakri { 45*185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 46*185b4595SMarouene Boubakri 47*185b4595SMarouene Boubakri if (!moph->va || offset >= mobj->size) 48*185b4595SMarouene Boubakri return NULL; 49*185b4595SMarouene Boubakri 50*185b4595SMarouene Boubakri return (void *)(moph->va + offset); 51*185b4595SMarouene Boubakri } 52*185b4595SMarouene Boubakri 53*185b4595SMarouene Boubakri static TEE_Result mobj_phys_get_pa(struct mobj *mobj, size_t offs, 54*185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 55*185b4595SMarouene Boubakri { 56*185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 57*185b4595SMarouene Boubakri paddr_t p; 58*185b4595SMarouene Boubakri 59*185b4595SMarouene Boubakri if (!pa) 60*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 61*185b4595SMarouene Boubakri 62*185b4595SMarouene Boubakri p = moph->pa + offs; 63*185b4595SMarouene Boubakri 64*185b4595SMarouene Boubakri if (granule) { 65*185b4595SMarouene Boubakri if (granule != SMALL_PAGE_SIZE && 66*185b4595SMarouene Boubakri granule != CORE_MMU_PGDIR_SIZE) 67*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 68*185b4595SMarouene Boubakri p &= ~(granule - 1); 69*185b4595SMarouene Boubakri } 70*185b4595SMarouene Boubakri 71*185b4595SMarouene Boubakri *pa = p; 72*185b4595SMarouene Boubakri return TEE_SUCCESS; 73*185b4595SMarouene Boubakri } 74*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_phys_get_pa); 75*185b4595SMarouene Boubakri 76*185b4595SMarouene Boubakri static TEE_Result mobj_phys_get_cattr(struct mobj *mobj, uint32_t *cattr) 77*185b4595SMarouene Boubakri { 78*185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 79*185b4595SMarouene Boubakri 80*185b4595SMarouene Boubakri if (!cattr) 81*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 82*185b4595SMarouene Boubakri 83*185b4595SMarouene Boubakri *cattr = moph->cattr; 84*185b4595SMarouene Boubakri return TEE_SUCCESS; 85*185b4595SMarouene Boubakri } 86*185b4595SMarouene Boubakri 87*185b4595SMarouene Boubakri static bool mobj_phys_matches(struct mobj *mobj, enum buf_is_attr attr) 88*185b4595SMarouene Boubakri { 89*185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 90*185b4595SMarouene Boubakri enum buf_is_attr a; 91*185b4595SMarouene Boubakri 92*185b4595SMarouene Boubakri a = moph->battr; 93*185b4595SMarouene Boubakri 94*185b4595SMarouene Boubakri switch (attr) { 95*185b4595SMarouene Boubakri case CORE_MEM_SEC: 96*185b4595SMarouene Boubakri return a == CORE_MEM_SEC || a == CORE_MEM_TEE_RAM || 97*185b4595SMarouene Boubakri a == CORE_MEM_TA_RAM || a == CORE_MEM_SDP_MEM; 98*185b4595SMarouene Boubakri case CORE_MEM_NON_SEC: 99*185b4595SMarouene Boubakri return a == CORE_MEM_NSEC_SHM; 100*185b4595SMarouene Boubakri case CORE_MEM_TEE_RAM: 101*185b4595SMarouene Boubakri case CORE_MEM_TA_RAM: 102*185b4595SMarouene Boubakri case CORE_MEM_NSEC_SHM: 103*185b4595SMarouene Boubakri case CORE_MEM_SDP_MEM: 104*185b4595SMarouene Boubakri return attr == a; 105*185b4595SMarouene Boubakri default: 106*185b4595SMarouene Boubakri return false; 107*185b4595SMarouene Boubakri } 108*185b4595SMarouene Boubakri } 109*185b4595SMarouene Boubakri 110*185b4595SMarouene Boubakri static void mobj_phys_free(struct mobj *mobj) 111*185b4595SMarouene Boubakri { 112*185b4595SMarouene Boubakri struct mobj_phys *moph = to_mobj_phys(mobj); 113*185b4595SMarouene Boubakri 114*185b4595SMarouene Boubakri free(moph); 115*185b4595SMarouene Boubakri } 116*185b4595SMarouene Boubakri 117*185b4595SMarouene Boubakri static const struct mobj_ops mobj_phys_ops __rodata_unpaged = { 118*185b4595SMarouene Boubakri .get_va = mobj_phys_get_va, 119*185b4595SMarouene Boubakri .get_pa = mobj_phys_get_pa, 120*185b4595SMarouene Boubakri .get_phys_offs = NULL, /* only offset 0 */ 121*185b4595SMarouene Boubakri .get_cattr = mobj_phys_get_cattr, 122*185b4595SMarouene Boubakri .matches = mobj_phys_matches, 123*185b4595SMarouene Boubakri .free = mobj_phys_free, 124*185b4595SMarouene Boubakri }; 125*185b4595SMarouene Boubakri 126*185b4595SMarouene Boubakri static struct mobj_phys *to_mobj_phys(struct mobj *mobj) 127*185b4595SMarouene Boubakri { 128*185b4595SMarouene Boubakri assert(mobj->ops == &mobj_phys_ops); 129*185b4595SMarouene Boubakri return container_of(mobj, struct mobj_phys, mobj); 130*185b4595SMarouene Boubakri } 131*185b4595SMarouene Boubakri 132*185b4595SMarouene Boubakri struct mobj *mobj_phys_alloc(paddr_t pa, size_t size, uint32_t cattr, 133*185b4595SMarouene Boubakri enum buf_is_attr battr) 134*185b4595SMarouene Boubakri { 135*185b4595SMarouene Boubakri struct mobj_phys *moph; 136*185b4595SMarouene Boubakri enum teecore_memtypes area_type; 137*185b4595SMarouene Boubakri void *va; 138*185b4595SMarouene Boubakri 139*185b4595SMarouene Boubakri if ((pa & CORE_MMU_USER_PARAM_MASK) || 140*185b4595SMarouene Boubakri (size & CORE_MMU_USER_PARAM_MASK)) { 141*185b4595SMarouene Boubakri DMSG("Expect %#x alignment", CORE_MMU_USER_PARAM_SIZE); 142*185b4595SMarouene Boubakri return NULL; 143*185b4595SMarouene Boubakri } 144*185b4595SMarouene Boubakri 145*185b4595SMarouene Boubakri switch (battr) { 146*185b4595SMarouene Boubakri case CORE_MEM_TEE_RAM: 147*185b4595SMarouene Boubakri area_type = MEM_AREA_TEE_RAM_RW_DATA; 148*185b4595SMarouene Boubakri break; 149*185b4595SMarouene Boubakri case CORE_MEM_TA_RAM: 150*185b4595SMarouene Boubakri area_type = MEM_AREA_TA_RAM; 151*185b4595SMarouene Boubakri break; 152*185b4595SMarouene Boubakri case CORE_MEM_NSEC_SHM: 153*185b4595SMarouene Boubakri area_type = MEM_AREA_NSEC_SHM; 154*185b4595SMarouene Boubakri break; 155*185b4595SMarouene Boubakri case CORE_MEM_SDP_MEM: 156*185b4595SMarouene Boubakri area_type = MEM_AREA_SDP_MEM; 157*185b4595SMarouene Boubakri break; 158*185b4595SMarouene Boubakri default: 159*185b4595SMarouene Boubakri DMSG("can't allocate with specified attribute"); 160*185b4595SMarouene Boubakri return NULL; 161*185b4595SMarouene Boubakri } 162*185b4595SMarouene Boubakri 163*185b4595SMarouene Boubakri /* Only SDP memory may not have a virtual address */ 164*185b4595SMarouene Boubakri va = phys_to_virt(pa, area_type); 165*185b4595SMarouene Boubakri if (!va && battr != CORE_MEM_SDP_MEM) 166*185b4595SMarouene Boubakri return NULL; 167*185b4595SMarouene Boubakri 168*185b4595SMarouene Boubakri moph = calloc(1, sizeof(*moph)); 169*185b4595SMarouene Boubakri if (!moph) 170*185b4595SMarouene Boubakri return NULL; 171*185b4595SMarouene Boubakri 172*185b4595SMarouene Boubakri moph->battr = battr; 173*185b4595SMarouene Boubakri moph->cattr = cattr; 174*185b4595SMarouene Boubakri moph->mobj.size = size; 175*185b4595SMarouene Boubakri moph->mobj.ops = &mobj_phys_ops; 176*185b4595SMarouene Boubakri refcount_set(&moph->mobj.refc, 1); 177*185b4595SMarouene Boubakri moph->pa = pa; 178*185b4595SMarouene Boubakri moph->va = (vaddr_t)va; 179*185b4595SMarouene Boubakri 180*185b4595SMarouene Boubakri return &moph->mobj; 181*185b4595SMarouene Boubakri } 182*185b4595SMarouene Boubakri 183*185b4595SMarouene Boubakri /* 184*185b4595SMarouene Boubakri * mobj_virt implementation 185*185b4595SMarouene Boubakri */ 186*185b4595SMarouene Boubakri 187*185b4595SMarouene Boubakri static void mobj_virt_assert_type(struct mobj *mobj); 188*185b4595SMarouene Boubakri 189*185b4595SMarouene Boubakri static void *mobj_virt_get_va(struct mobj *mobj, size_t offset) 190*185b4595SMarouene Boubakri { 191*185b4595SMarouene Boubakri mobj_virt_assert_type(mobj); 192*185b4595SMarouene Boubakri 193*185b4595SMarouene Boubakri return (void *)(vaddr_t)offset; 194*185b4595SMarouene Boubakri } 195*185b4595SMarouene Boubakri 196*185b4595SMarouene Boubakri static const struct mobj_ops mobj_virt_ops __rodata_unpaged = { 197*185b4595SMarouene Boubakri .get_va = mobj_virt_get_va, 198*185b4595SMarouene Boubakri }; 199*185b4595SMarouene Boubakri 200*185b4595SMarouene Boubakri static void mobj_virt_assert_type(struct mobj *mobj __maybe_unused) 201*185b4595SMarouene Boubakri { 202*185b4595SMarouene Boubakri assert(mobj->ops == &mobj_virt_ops); 203*185b4595SMarouene Boubakri } 204*185b4595SMarouene Boubakri 205*185b4595SMarouene Boubakri struct mobj mobj_virt = { .ops = &mobj_virt_ops, .size = SIZE_MAX }; 206*185b4595SMarouene Boubakri 207*185b4595SMarouene Boubakri /* 208*185b4595SMarouene Boubakri * mobj_mm implementation 209*185b4595SMarouene Boubakri */ 210*185b4595SMarouene Boubakri 211*185b4595SMarouene Boubakri struct mobj_mm { 212*185b4595SMarouene Boubakri tee_mm_entry_t *mm; 213*185b4595SMarouene Boubakri struct mobj *parent_mobj; 214*185b4595SMarouene Boubakri struct mobj mobj; 215*185b4595SMarouene Boubakri }; 216*185b4595SMarouene Boubakri 217*185b4595SMarouene Boubakri static struct mobj_mm *to_mobj_mm(struct mobj *mobj); 218*185b4595SMarouene Boubakri 219*185b4595SMarouene Boubakri static size_t mobj_mm_offs(struct mobj *mobj, size_t offs) 220*185b4595SMarouene Boubakri { 221*185b4595SMarouene Boubakri tee_mm_entry_t *mm = to_mobj_mm(mobj)->mm; 222*185b4595SMarouene Boubakri 223*185b4595SMarouene Boubakri return (mm->offset << mm->pool->shift) + offs; 224*185b4595SMarouene Boubakri } 225*185b4595SMarouene Boubakri 226*185b4595SMarouene Boubakri static void *mobj_mm_get_va(struct mobj *mobj, size_t offs) 227*185b4595SMarouene Boubakri { 228*185b4595SMarouene Boubakri return mobj_get_va(to_mobj_mm(mobj)->parent_mobj, 229*185b4595SMarouene Boubakri mobj_mm_offs(mobj, offs)); 230*185b4595SMarouene Boubakri } 231*185b4595SMarouene Boubakri 232*185b4595SMarouene Boubakri 233*185b4595SMarouene Boubakri static TEE_Result mobj_mm_get_pa(struct mobj *mobj, size_t offs, 234*185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 235*185b4595SMarouene Boubakri { 236*185b4595SMarouene Boubakri return mobj_get_pa(to_mobj_mm(mobj)->parent_mobj, 237*185b4595SMarouene Boubakri mobj_mm_offs(mobj, offs), granule, pa); 238*185b4595SMarouene Boubakri } 239*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_mm_get_pa); 240*185b4595SMarouene Boubakri 241*185b4595SMarouene Boubakri static size_t mobj_mm_get_phys_offs(struct mobj *mobj, size_t granule) 242*185b4595SMarouene Boubakri { 243*185b4595SMarouene Boubakri return mobj_get_phys_offs(to_mobj_mm(mobj)->parent_mobj, granule); 244*185b4595SMarouene Boubakri } 245*185b4595SMarouene Boubakri 246*185b4595SMarouene Boubakri static TEE_Result mobj_mm_get_cattr(struct mobj *mobj, uint32_t *cattr) 247*185b4595SMarouene Boubakri { 248*185b4595SMarouene Boubakri return mobj_get_cattr(to_mobj_mm(mobj)->parent_mobj, cattr); 249*185b4595SMarouene Boubakri } 250*185b4595SMarouene Boubakri 251*185b4595SMarouene Boubakri static bool mobj_mm_matches(struct mobj *mobj, enum buf_is_attr attr) 252*185b4595SMarouene Boubakri { 253*185b4595SMarouene Boubakri return mobj_matches(to_mobj_mm(mobj)->parent_mobj, attr); 254*185b4595SMarouene Boubakri } 255*185b4595SMarouene Boubakri 256*185b4595SMarouene Boubakri static void mobj_mm_free(struct mobj *mobj) 257*185b4595SMarouene Boubakri { 258*185b4595SMarouene Boubakri struct mobj_mm *m = to_mobj_mm(mobj); 259*185b4595SMarouene Boubakri 260*185b4595SMarouene Boubakri tee_mm_free(m->mm); 261*185b4595SMarouene Boubakri free(m); 262*185b4595SMarouene Boubakri } 263*185b4595SMarouene Boubakri 264*185b4595SMarouene Boubakri static const struct mobj_ops mobj_mm_ops __rodata_unpaged = { 265*185b4595SMarouene Boubakri .get_va = mobj_mm_get_va, 266*185b4595SMarouene Boubakri .get_pa = mobj_mm_get_pa, 267*185b4595SMarouene Boubakri .get_phys_offs = mobj_mm_get_phys_offs, 268*185b4595SMarouene Boubakri .get_cattr = mobj_mm_get_cattr, 269*185b4595SMarouene Boubakri .matches = mobj_mm_matches, 270*185b4595SMarouene Boubakri .free = mobj_mm_free, 271*185b4595SMarouene Boubakri }; 272*185b4595SMarouene Boubakri 273*185b4595SMarouene Boubakri static struct mobj_mm *to_mobj_mm(struct mobj *mobj) 274*185b4595SMarouene Boubakri { 275*185b4595SMarouene Boubakri assert(mobj->ops == &mobj_mm_ops); 276*185b4595SMarouene Boubakri return container_of(mobj, struct mobj_mm, mobj); 277*185b4595SMarouene Boubakri } 278*185b4595SMarouene Boubakri 279*185b4595SMarouene Boubakri struct mobj *mobj_mm_alloc(struct mobj *mobj_parent, size_t size, 280*185b4595SMarouene Boubakri tee_mm_pool_t *pool) 281*185b4595SMarouene Boubakri { 282*185b4595SMarouene Boubakri struct mobj_mm *m = calloc(1, sizeof(*m)); 283*185b4595SMarouene Boubakri 284*185b4595SMarouene Boubakri if (!m) 285*185b4595SMarouene Boubakri return NULL; 286*185b4595SMarouene Boubakri 287*185b4595SMarouene Boubakri m->mm = tee_mm_alloc(pool, size); 288*185b4595SMarouene Boubakri if (!m->mm) { 289*185b4595SMarouene Boubakri free(m); 290*185b4595SMarouene Boubakri return NULL; 291*185b4595SMarouene Boubakri } 292*185b4595SMarouene Boubakri 293*185b4595SMarouene Boubakri m->parent_mobj = mobj_parent; 294*185b4595SMarouene Boubakri m->mobj.size = size; 295*185b4595SMarouene Boubakri m->mobj.ops = &mobj_mm_ops; 296*185b4595SMarouene Boubakri refcount_set(&m->mobj.refc, 1); 297*185b4595SMarouene Boubakri 298*185b4595SMarouene Boubakri return &m->mobj; 299*185b4595SMarouene Boubakri } 300*185b4595SMarouene Boubakri 301*185b4595SMarouene Boubakri 302*185b4595SMarouene Boubakri /* 303*185b4595SMarouene Boubakri * mobj_shm implementation. mobj_shm represents buffer in predefined shm region 304*185b4595SMarouene Boubakri * - it is physically contiguous. 305*185b4595SMarouene Boubakri * - it is identified in static physical layout as MEM_AREA_NSEC_SHM. 306*185b4595SMarouene Boubakri * - it creates mobjs that match specific CORE_MEM_NSEC_SHM and non secure 307*185b4595SMarouene Boubakri * generic CORE_MEM_NON_SEC. 308*185b4595SMarouene Boubakri */ 309*185b4595SMarouene Boubakri 310*185b4595SMarouene Boubakri struct mobj_shm { 311*185b4595SMarouene Boubakri struct mobj mobj; 312*185b4595SMarouene Boubakri paddr_t pa; 313*185b4595SMarouene Boubakri uint64_t cookie; 314*185b4595SMarouene Boubakri }; 315*185b4595SMarouene Boubakri 316*185b4595SMarouene Boubakri static struct mobj_shm *to_mobj_shm(struct mobj *mobj); 317*185b4595SMarouene Boubakri 318*185b4595SMarouene Boubakri static void *mobj_shm_get_va(struct mobj *mobj, size_t offset) 319*185b4595SMarouene Boubakri { 320*185b4595SMarouene Boubakri struct mobj_shm *m = to_mobj_shm(mobj); 321*185b4595SMarouene Boubakri 322*185b4595SMarouene Boubakri if (offset >= mobj->size) 323*185b4595SMarouene Boubakri return NULL; 324*185b4595SMarouene Boubakri 325*185b4595SMarouene Boubakri return phys_to_virt(m->pa + offset, MEM_AREA_NSEC_SHM); 326*185b4595SMarouene Boubakri } 327*185b4595SMarouene Boubakri 328*185b4595SMarouene Boubakri static TEE_Result mobj_shm_get_pa(struct mobj *mobj, size_t offs, 329*185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 330*185b4595SMarouene Boubakri { 331*185b4595SMarouene Boubakri struct mobj_shm *m = to_mobj_shm(mobj); 332*185b4595SMarouene Boubakri paddr_t p; 333*185b4595SMarouene Boubakri 334*185b4595SMarouene Boubakri if (!pa || offs >= mobj->size) 335*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 336*185b4595SMarouene Boubakri 337*185b4595SMarouene Boubakri p = m->pa + offs; 338*185b4595SMarouene Boubakri 339*185b4595SMarouene Boubakri if (granule) { 340*185b4595SMarouene Boubakri if (granule != SMALL_PAGE_SIZE && 341*185b4595SMarouene Boubakri granule != CORE_MMU_PGDIR_SIZE) 342*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 343*185b4595SMarouene Boubakri p &= ~(granule - 1); 344*185b4595SMarouene Boubakri } 345*185b4595SMarouene Boubakri 346*185b4595SMarouene Boubakri *pa = p; 347*185b4595SMarouene Boubakri return TEE_SUCCESS; 348*185b4595SMarouene Boubakri } 349*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_shm_get_pa); 350*185b4595SMarouene Boubakri 351*185b4595SMarouene Boubakri static size_t mobj_shm_get_phys_offs(struct mobj *mobj, size_t granule) 352*185b4595SMarouene Boubakri { 353*185b4595SMarouene Boubakri assert(IS_POWER_OF_TWO(granule)); 354*185b4595SMarouene Boubakri return to_mobj_shm(mobj)->pa & (granule - 1); 355*185b4595SMarouene Boubakri } 356*185b4595SMarouene Boubakri 357*185b4595SMarouene Boubakri static bool mobj_shm_matches(struct mobj *mobj __unused, enum buf_is_attr attr) 358*185b4595SMarouene Boubakri { 359*185b4595SMarouene Boubakri return attr == CORE_MEM_NSEC_SHM || attr == CORE_MEM_NON_SEC; 360*185b4595SMarouene Boubakri } 361*185b4595SMarouene Boubakri 362*185b4595SMarouene Boubakri static void mobj_shm_free(struct mobj *mobj) 363*185b4595SMarouene Boubakri { 364*185b4595SMarouene Boubakri struct mobj_shm *m = to_mobj_shm(mobj); 365*185b4595SMarouene Boubakri 366*185b4595SMarouene Boubakri free(m); 367*185b4595SMarouene Boubakri } 368*185b4595SMarouene Boubakri 369*185b4595SMarouene Boubakri static uint64_t mobj_shm_get_cookie(struct mobj *mobj) 370*185b4595SMarouene Boubakri { 371*185b4595SMarouene Boubakri return to_mobj_shm(mobj)->cookie; 372*185b4595SMarouene Boubakri } 373*185b4595SMarouene Boubakri 374*185b4595SMarouene Boubakri static const struct mobj_ops mobj_shm_ops __rodata_unpaged = { 375*185b4595SMarouene Boubakri .get_va = mobj_shm_get_va, 376*185b4595SMarouene Boubakri .get_pa = mobj_shm_get_pa, 377*185b4595SMarouene Boubakri .get_phys_offs = mobj_shm_get_phys_offs, 378*185b4595SMarouene Boubakri .matches = mobj_shm_matches, 379*185b4595SMarouene Boubakri .free = mobj_shm_free, 380*185b4595SMarouene Boubakri .get_cookie = mobj_shm_get_cookie, 381*185b4595SMarouene Boubakri }; 382*185b4595SMarouene Boubakri 383*185b4595SMarouene Boubakri static struct mobj_shm *to_mobj_shm(struct mobj *mobj) 384*185b4595SMarouene Boubakri { 385*185b4595SMarouene Boubakri assert(mobj->ops == &mobj_shm_ops); 386*185b4595SMarouene Boubakri return container_of(mobj, struct mobj_shm, mobj); 387*185b4595SMarouene Boubakri } 388*185b4595SMarouene Boubakri 389*185b4595SMarouene Boubakri struct mobj *mobj_shm_alloc(paddr_t pa, size_t size, uint64_t cookie) 390*185b4595SMarouene Boubakri { 391*185b4595SMarouene Boubakri struct mobj_shm *m; 392*185b4595SMarouene Boubakri 393*185b4595SMarouene Boubakri if (!core_pbuf_is(CORE_MEM_NSEC_SHM, pa, size)) 394*185b4595SMarouene Boubakri return NULL; 395*185b4595SMarouene Boubakri 396*185b4595SMarouene Boubakri m = calloc(1, sizeof(*m)); 397*185b4595SMarouene Boubakri if (!m) 398*185b4595SMarouene Boubakri return NULL; 399*185b4595SMarouene Boubakri 400*185b4595SMarouene Boubakri m->mobj.size = size; 401*185b4595SMarouene Boubakri m->mobj.ops = &mobj_shm_ops; 402*185b4595SMarouene Boubakri refcount_set(&m->mobj.refc, 1); 403*185b4595SMarouene Boubakri m->pa = pa; 404*185b4595SMarouene Boubakri m->cookie = cookie; 405*185b4595SMarouene Boubakri 406*185b4595SMarouene Boubakri return &m->mobj; 407*185b4595SMarouene Boubakri } 408*185b4595SMarouene Boubakri 409*185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA 410*185b4595SMarouene Boubakri /* 411*185b4595SMarouene Boubakri * mobj_seccpy_shm implementation 412*185b4595SMarouene Boubakri */ 413*185b4595SMarouene Boubakri 414*185b4595SMarouene Boubakri struct mobj_seccpy_shm { 415*185b4595SMarouene Boubakri struct user_ta_ctx *utc; 416*185b4595SMarouene Boubakri vaddr_t va; 417*185b4595SMarouene Boubakri struct mobj mobj; 418*185b4595SMarouene Boubakri struct fobj *fobj; 419*185b4595SMarouene Boubakri }; 420*185b4595SMarouene Boubakri 421*185b4595SMarouene Boubakri static bool __maybe_unused mobj_is_seccpy_shm(struct mobj *mobj); 422*185b4595SMarouene Boubakri 423*185b4595SMarouene Boubakri static struct mobj_seccpy_shm *to_mobj_seccpy_shm(struct mobj *mobj) 424*185b4595SMarouene Boubakri { 425*185b4595SMarouene Boubakri assert(mobj_is_seccpy_shm(mobj)); 426*185b4595SMarouene Boubakri return container_of(mobj, struct mobj_seccpy_shm, mobj); 427*185b4595SMarouene Boubakri } 428*185b4595SMarouene Boubakri 429*185b4595SMarouene Boubakri static void *mobj_seccpy_shm_get_va(struct mobj *mobj, size_t offs) 430*185b4595SMarouene Boubakri { 431*185b4595SMarouene Boubakri struct mobj_seccpy_shm *m = to_mobj_seccpy_shm(mobj); 432*185b4595SMarouene Boubakri 433*185b4595SMarouene Boubakri if (&m->utc->ta_ctx.ts_ctx != thread_get_tsd()->ctx) 434*185b4595SMarouene Boubakri return NULL; 435*185b4595SMarouene Boubakri 436*185b4595SMarouene Boubakri if (offs >= mobj->size) 437*185b4595SMarouene Boubakri return NULL; 438*185b4595SMarouene Boubakri return (void *)(m->va + offs); 439*185b4595SMarouene Boubakri } 440*185b4595SMarouene Boubakri 441*185b4595SMarouene Boubakri static bool mobj_seccpy_shm_matches(struct mobj *mobj __maybe_unused, 442*185b4595SMarouene Boubakri enum buf_is_attr attr) 443*185b4595SMarouene Boubakri { 444*185b4595SMarouene Boubakri assert(mobj_is_seccpy_shm(mobj)); 445*185b4595SMarouene Boubakri 446*185b4595SMarouene Boubakri return attr == CORE_MEM_SEC || attr == CORE_MEM_TEE_RAM; 447*185b4595SMarouene Boubakri } 448*185b4595SMarouene Boubakri 449*185b4595SMarouene Boubakri static void mobj_seccpy_shm_free(struct mobj *mobj) 450*185b4595SMarouene Boubakri { 451*185b4595SMarouene Boubakri struct mobj_seccpy_shm *m = to_mobj_seccpy_shm(mobj); 452*185b4595SMarouene Boubakri 453*185b4595SMarouene Boubakri tee_pager_rem_um_region(&m->utc->uctx, m->va, mobj->size); 454*185b4595SMarouene Boubakri vm_rem_rwmem(&m->utc->uctx, mobj, m->va); 455*185b4595SMarouene Boubakri fobj_put(m->fobj); 456*185b4595SMarouene Boubakri free(m); 457*185b4595SMarouene Boubakri } 458*185b4595SMarouene Boubakri 459*185b4595SMarouene Boubakri static struct fobj *mobj_seccpy_shm_get_fobj(struct mobj *mobj) 460*185b4595SMarouene Boubakri { 461*185b4595SMarouene Boubakri return fobj_get(to_mobj_seccpy_shm(mobj)->fobj); 462*185b4595SMarouene Boubakri } 463*185b4595SMarouene Boubakri 464*185b4595SMarouene Boubakri static const struct mobj_ops mobj_seccpy_shm_ops __rodata_unpaged = { 465*185b4595SMarouene Boubakri .get_va = mobj_seccpy_shm_get_va, 466*185b4595SMarouene Boubakri .matches = mobj_seccpy_shm_matches, 467*185b4595SMarouene Boubakri .free = mobj_seccpy_shm_free, 468*185b4595SMarouene Boubakri .get_fobj = mobj_seccpy_shm_get_fobj, 469*185b4595SMarouene Boubakri }; 470*185b4595SMarouene Boubakri 471*185b4595SMarouene Boubakri static bool mobj_is_seccpy_shm(struct mobj *mobj) 472*185b4595SMarouene Boubakri { 473*185b4595SMarouene Boubakri return mobj && mobj->ops == &mobj_seccpy_shm_ops; 474*185b4595SMarouene Boubakri } 475*185b4595SMarouene Boubakri 476*185b4595SMarouene Boubakri struct mobj *mobj_seccpy_shm_alloc(size_t size) 477*185b4595SMarouene Boubakri { 478*185b4595SMarouene Boubakri struct thread_specific_data *tsd = thread_get_tsd(); 479*185b4595SMarouene Boubakri struct mobj_seccpy_shm *m; 480*185b4595SMarouene Boubakri struct user_ta_ctx *utc; 481*185b4595SMarouene Boubakri vaddr_t va = 0; 482*185b4595SMarouene Boubakri 483*185b4595SMarouene Boubakri if (!is_user_ta_ctx(tsd->ctx)) 484*185b4595SMarouene Boubakri return NULL; 485*185b4595SMarouene Boubakri utc = to_user_ta_ctx(tsd->ctx); 486*185b4595SMarouene Boubakri 487*185b4595SMarouene Boubakri m = calloc(1, sizeof(*m)); 488*185b4595SMarouene Boubakri if (!m) 489*185b4595SMarouene Boubakri return NULL; 490*185b4595SMarouene Boubakri 491*185b4595SMarouene Boubakri m->mobj.size = size; 492*185b4595SMarouene Boubakri m->mobj.ops = &mobj_seccpy_shm_ops; 493*185b4595SMarouene Boubakri refcount_set(&m->mobj.refc, 1); 494*185b4595SMarouene Boubakri 495*185b4595SMarouene Boubakri if (vm_add_rwmem(&utc->uctx, &m->mobj, &va) != TEE_SUCCESS) 496*185b4595SMarouene Boubakri goto bad; 497*185b4595SMarouene Boubakri 498*185b4595SMarouene Boubakri m->fobj = fobj_rw_paged_alloc(ROUNDUP(size, SMALL_PAGE_SIZE) / 499*185b4595SMarouene Boubakri SMALL_PAGE_SIZE); 500*185b4595SMarouene Boubakri if (tee_pager_add_um_area(&utc->uctx, va, m->fobj, 501*185b4595SMarouene Boubakri TEE_MATTR_PRW | TEE_MATTR_URW)) 502*185b4595SMarouene Boubakri goto bad; 503*185b4595SMarouene Boubakri 504*185b4595SMarouene Boubakri m->va = va; 505*185b4595SMarouene Boubakri m->utc = to_user_ta_ctx(tsd->ctx); 506*185b4595SMarouene Boubakri return &m->mobj; 507*185b4595SMarouene Boubakri bad: 508*185b4595SMarouene Boubakri if (va) 509*185b4595SMarouene Boubakri vm_rem_rwmem(&utc->uctx, &m->mobj, va); 510*185b4595SMarouene Boubakri fobj_put(m->fobj); 511*185b4595SMarouene Boubakri free(m); 512*185b4595SMarouene Boubakri return NULL; 513*185b4595SMarouene Boubakri } 514*185b4595SMarouene Boubakri 515*185b4595SMarouene Boubakri 516*185b4595SMarouene Boubakri #endif /*CFG_PAGED_USER_TA*/ 517*185b4595SMarouene Boubakri 518*185b4595SMarouene Boubakri struct mobj_with_fobj { 519*185b4595SMarouene Boubakri struct fobj *fobj; 520*185b4595SMarouene Boubakri struct file *file; 521*185b4595SMarouene Boubakri struct mobj mobj; 522*185b4595SMarouene Boubakri }; 523*185b4595SMarouene Boubakri 524*185b4595SMarouene Boubakri static const struct mobj_ops mobj_with_fobj_ops; 525*185b4595SMarouene Boubakri 526*185b4595SMarouene Boubakri struct mobj *mobj_with_fobj_alloc(struct fobj *fobj, struct file *file) 527*185b4595SMarouene Boubakri { 528*185b4595SMarouene Boubakri struct mobj_with_fobj *m = NULL; 529*185b4595SMarouene Boubakri 530*185b4595SMarouene Boubakri if (!fobj) 531*185b4595SMarouene Boubakri return NULL; 532*185b4595SMarouene Boubakri 533*185b4595SMarouene Boubakri m = calloc(1, sizeof(*m)); 534*185b4595SMarouene Boubakri if (!m) 535*185b4595SMarouene Boubakri return NULL; 536*185b4595SMarouene Boubakri 537*185b4595SMarouene Boubakri m->mobj.ops = &mobj_with_fobj_ops; 538*185b4595SMarouene Boubakri refcount_set(&m->mobj.refc, 1); 539*185b4595SMarouene Boubakri m->mobj.size = fobj->num_pages * SMALL_PAGE_SIZE; 540*185b4595SMarouene Boubakri m->mobj.phys_granule = SMALL_PAGE_SIZE; 541*185b4595SMarouene Boubakri m->fobj = fobj_get(fobj); 542*185b4595SMarouene Boubakri m->file = file_get(file); 543*185b4595SMarouene Boubakri 544*185b4595SMarouene Boubakri return &m->mobj; 545*185b4595SMarouene Boubakri } 546*185b4595SMarouene Boubakri 547*185b4595SMarouene Boubakri static struct mobj_with_fobj *to_mobj_with_fobj(struct mobj *mobj) 548*185b4595SMarouene Boubakri { 549*185b4595SMarouene Boubakri assert(mobj && mobj->ops == &mobj_with_fobj_ops); 550*185b4595SMarouene Boubakri 551*185b4595SMarouene Boubakri return container_of(mobj, struct mobj_with_fobj, mobj); 552*185b4595SMarouene Boubakri } 553*185b4595SMarouene Boubakri 554*185b4595SMarouene Boubakri static bool mobj_with_fobj_matches(struct mobj *mobj __maybe_unused, 555*185b4595SMarouene Boubakri enum buf_is_attr attr) 556*185b4595SMarouene Boubakri { 557*185b4595SMarouene Boubakri assert(to_mobj_with_fobj(mobj)); 558*185b4595SMarouene Boubakri 559*185b4595SMarouene Boubakri /* 560*185b4595SMarouene Boubakri * All fobjs are supposed to be mapped secure so classify it as 561*185b4595SMarouene Boubakri * CORE_MEM_SEC. Stay out of CORE_MEM_TEE_RAM etc, if that information 562*185b4595SMarouene Boubakri * needed it can probably be carried in another way than to put the 563*185b4595SMarouene Boubakri * burden directly on fobj. 564*185b4595SMarouene Boubakri */ 565*185b4595SMarouene Boubakri return attr == CORE_MEM_SEC; 566*185b4595SMarouene Boubakri } 567*185b4595SMarouene Boubakri 568*185b4595SMarouene Boubakri static void mobj_with_fobj_free(struct mobj *mobj) 569*185b4595SMarouene Boubakri { 570*185b4595SMarouene Boubakri struct mobj_with_fobj *m = to_mobj_with_fobj(mobj); 571*185b4595SMarouene Boubakri 572*185b4595SMarouene Boubakri fobj_put(m->fobj); 573*185b4595SMarouene Boubakri file_put(m->file); 574*185b4595SMarouene Boubakri free(m); 575*185b4595SMarouene Boubakri } 576*185b4595SMarouene Boubakri 577*185b4595SMarouene Boubakri static struct fobj *mobj_with_fobj_get_fobj(struct mobj *mobj) 578*185b4595SMarouene Boubakri { 579*185b4595SMarouene Boubakri return fobj_get(to_mobj_with_fobj(mobj)->fobj); 580*185b4595SMarouene Boubakri } 581*185b4595SMarouene Boubakri 582*185b4595SMarouene Boubakri static TEE_Result mobj_with_fobj_get_cattr(struct mobj *mobj __unused, 583*185b4595SMarouene Boubakri uint32_t *cattr) 584*185b4595SMarouene Boubakri { 585*185b4595SMarouene Boubakri if (!cattr) 586*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 587*185b4595SMarouene Boubakri 588*185b4595SMarouene Boubakri /* All fobjs are mapped as normal cached memory */ 589*185b4595SMarouene Boubakri *cattr = TEE_MATTR_CACHE_CACHED; 590*185b4595SMarouene Boubakri 591*185b4595SMarouene Boubakri return TEE_SUCCESS; 592*185b4595SMarouene Boubakri } 593*185b4595SMarouene Boubakri 594*185b4595SMarouene Boubakri static TEE_Result mobj_with_fobj_get_pa(struct mobj *mobj, size_t offs, 595*185b4595SMarouene Boubakri size_t granule, paddr_t *pa) 596*185b4595SMarouene Boubakri { 597*185b4595SMarouene Boubakri struct mobj_with_fobj *f = to_mobj_with_fobj(mobj); 598*185b4595SMarouene Boubakri paddr_t p = 0; 599*185b4595SMarouene Boubakri 600*185b4595SMarouene Boubakri if (!f->fobj->ops->get_pa) { 601*185b4595SMarouene Boubakri assert(mobj_is_paged(mobj)); 602*185b4595SMarouene Boubakri return TEE_ERROR_NOT_SUPPORTED; 603*185b4595SMarouene Boubakri } 604*185b4595SMarouene Boubakri 605*185b4595SMarouene Boubakri p = f->fobj->ops->get_pa(f->fobj, offs / SMALL_PAGE_SIZE) + 606*185b4595SMarouene Boubakri offs % SMALL_PAGE_SIZE; 607*185b4595SMarouene Boubakri 608*185b4595SMarouene Boubakri if (granule) { 609*185b4595SMarouene Boubakri if (granule != SMALL_PAGE_SIZE && 610*185b4595SMarouene Boubakri granule != CORE_MMU_PGDIR_SIZE) 611*185b4595SMarouene Boubakri return TEE_ERROR_GENERIC; 612*185b4595SMarouene Boubakri p &= ~(granule - 1); 613*185b4595SMarouene Boubakri } 614*185b4595SMarouene Boubakri 615*185b4595SMarouene Boubakri *pa = p; 616*185b4595SMarouene Boubakri 617*185b4595SMarouene Boubakri return TEE_SUCCESS; 618*185b4595SMarouene Boubakri } 619*185b4595SMarouene Boubakri DECLARE_KEEP_PAGER(mobj_with_fobj_get_pa); 620*185b4595SMarouene Boubakri 621*185b4595SMarouene Boubakri static const struct mobj_ops mobj_with_fobj_ops __rodata_unpaged = { 622*185b4595SMarouene Boubakri .matches = mobj_with_fobj_matches, 623*185b4595SMarouene Boubakri .free = mobj_with_fobj_free, 624*185b4595SMarouene Boubakri .get_fobj = mobj_with_fobj_get_fobj, 625*185b4595SMarouene Boubakri .get_cattr = mobj_with_fobj_get_cattr, 626*185b4595SMarouene Boubakri .get_pa = mobj_with_fobj_get_pa, 627*185b4595SMarouene Boubakri }; 628*185b4595SMarouene Boubakri 629*185b4595SMarouene Boubakri #ifdef CFG_PAGED_USER_TA 630*185b4595SMarouene Boubakri bool mobj_is_paged(struct mobj *mobj) 631*185b4595SMarouene Boubakri { 632*185b4595SMarouene Boubakri if (mobj->ops == &mobj_seccpy_shm_ops) 633*185b4595SMarouene Boubakri return true; 634*185b4595SMarouene Boubakri 635*185b4595SMarouene Boubakri if (mobj->ops == &mobj_with_fobj_ops && 636*185b4595SMarouene Boubakri !to_mobj_with_fobj(mobj)->fobj->ops->get_pa) 637*185b4595SMarouene Boubakri return true; 638*185b4595SMarouene Boubakri 639*185b4595SMarouene Boubakri return false; 640*185b4595SMarouene Boubakri } 641*185b4595SMarouene Boubakri #endif /*CFG_PAGED_USER_TA*/ 642*185b4595SMarouene Boubakri 643*185b4595SMarouene Boubakri static TEE_Result mobj_init(void) 644*185b4595SMarouene Boubakri { 645*185b4595SMarouene Boubakri mobj_sec_ddr = mobj_phys_alloc(tee_mm_sec_ddr.lo, 646*185b4595SMarouene Boubakri tee_mm_sec_ddr.hi - tee_mm_sec_ddr.lo, 647*185b4595SMarouene Boubakri OPTEE_SMC_SHM_CACHED, CORE_MEM_TA_RAM); 648*185b4595SMarouene Boubakri if (!mobj_sec_ddr) 649*185b4595SMarouene Boubakri panic("Failed to register secure ta ram"); 650*185b4595SMarouene Boubakri 651*185b4595SMarouene Boubakri mobj_tee_ram = mobj_phys_alloc(TEE_RAM_START, 652*185b4595SMarouene Boubakri VCORE_UNPG_RW_PA + VCORE_UNPG_RW_SZ - 653*185b4595SMarouene Boubakri TEE_RAM_START, 654*185b4595SMarouene Boubakri TEE_MATTR_CACHE_CACHED, 655*185b4595SMarouene Boubakri CORE_MEM_TEE_RAM); 656*185b4595SMarouene Boubakri if (!mobj_tee_ram) 657*185b4595SMarouene Boubakri panic("Failed to register tee ram"); 658*185b4595SMarouene Boubakri 659*185b4595SMarouene Boubakri return TEE_SUCCESS; 660*185b4595SMarouene Boubakri } 661*185b4595SMarouene Boubakri 662*185b4595SMarouene Boubakri driver_init_late(mobj_init); 663