1 /*
2 * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <assert.h>
8 #include <common/debug.h>
9 #include <errno.h>
10 #include <inttypes.h>
11 #include <platform_def.h>
12 #include <stddef.h>
13 #include <trusty/arm_ffa.h>
14 #include <trusty/ffa_helpers.h>
15
16 #define NS_DRAM0_BITMAP_SIZE DIV_ROUND_UP_2EVAL(NS_DRAM0_SIZE, PAGE_SIZE * 8)
17 static uint8_t trusty_shmem_shared[NS_DRAM0_BITMAP_SIZE];
18 static uint8_t trusty_shmem_secure[NS_DRAM0_BITMAP_SIZE];
19
read_bit(uint8_t * bit_mask,size_t bit_num)20 static bool read_bit(uint8_t *bit_mask, size_t bit_num)
21 {
22 size_t i = bit_num / 8;
23 size_t m = 1U << (bit_num % 8);
24 return !!(bit_mask[i] & m);
25 }
26
write_bit(uint8_t * bit_mask,size_t bit_num,bool val)27 static void write_bit(uint8_t *bit_mask, size_t bit_num, bool val)
28 {
29 size_t i = bit_num / 8;
30 size_t m = 1U << (bit_num % 8);
31 if (val) {
32 bit_mask[i] |= m;
33 } else {
34 bit_mask[i] &= ~m;
35 }
36 }
37
mem_set_shared(bool shared,bool secure,unsigned long long base_pa,size_t size)38 static int mem_set_shared(bool shared, bool secure, unsigned long long base_pa,
39 size_t size)
40 {
41 unsigned long long page;
42 size_t i;
43
44 assert((size % PAGE_SIZE) == 0);
45
46 if (base_pa < NS_DRAM0_BASE ||
47 (base_pa - NS_DRAM0_BASE) + size > NS_DRAM0_SIZE) {
48 NOTICE("%s(%d, %d, 0x%llx, 0x%zx) invalid address range\n",
49 __func__, shared, secure, base_pa, size);
50 return -EINVAL;
51 }
52 for (page = (base_pa - NS_DRAM0_BASE) / PAGE_SIZE, i = 0;
53 i < size / PAGE_SIZE; page++, i++) {
54 bool was_shared = read_bit(trusty_shmem_shared, page);
55 bool was_secure = read_bit(trusty_shmem_secure, page);
56 assert(!was_secure || was_shared);
57 if (was_shared == shared) {
58 /* already shared or reclaimed */
59 NOTICE("%s(%d, %d, 0x%llx, 0x%zx) already set\n",
60 __func__, shared, secure, base_pa, size);
61 goto err;
62 }
63 assert(was_secure == (secure && !shared));
64 write_bit(trusty_shmem_shared, page, shared);
65 if (secure) {
66 /*
67 * For emulator testing purposes the memory
68 * is marked as secure, and communicated to
69 * Trusty as such, even though it is not.
70 */
71 write_bit(trusty_shmem_secure, page, shared);
72 }
73 }
74 return 0;
75
76 err:
77 while (i > 0) {
78 i--;
79 page--;
80 write_bit(trusty_shmem_shared, page, !shared);
81 if (secure) {
82 write_bit(trusty_shmem_secure, page, !shared);
83 }
84 }
85 return -EBUSY;
86 }
87
88
plat_mem_set_shared(struct ffa_mtd * mtd,bool shared)89 int plat_mem_set_shared(struct ffa_mtd *mtd, bool shared)
90 {
91 struct ffa_comp_mrd *comp = trusty_ffa_mtd_get_comp_mrd(mtd);
92 size_t count = comp->address_range_count;
93 struct ffa_cons_mrd *cons_mrd;
94 int ret = 0;
95 size_t i;
96 bool secure;
97
98 secure = trusty_ffa_should_be_secure(mtd);
99
100 for (i = 0, cons_mrd = comp->address_range_array; i < count;
101 i++, cons_mrd++) {
102 ret = mem_set_shared(shared, secure, cons_mrd->address,
103 cons_mrd->page_count * PAGE_SIZE);
104 if (ret) {
105 goto err;
106 }
107 }
108
109 if (secure) {
110 mtd->memory_region_attributes &= ~FFA_MEM_ATTR_NONSECURE;
111 }
112 return 0;
113
114 err:
115 NOTICE("%s: %zu/%zu: failed to set shared %d secure %d for %"
116 PRIx64 " (%x)\n",
117 __func__, i, count, shared, secure, cons_mrd->address,
118 cons_mrd->page_count);
119 while (i > 0) {
120 i--;
121 cons_mrd--;
122 if (mem_set_shared(!shared, secure, cons_mrd->address,
123 cons_mrd->page_count * PAGE_SIZE)) {
124 /* Failed to revert change */
125 panic();
126 }
127 }
128 return ret;
129 }
130