1 // SPDX-License-Identifier: BSD-2-Clause
2 /*
3 * Copyright 2019, 2023-2024 NXP
4 */
5 #include <caam_common.h>
6 #include <caam_hal_ctrl.h>
7 #include <caam_hal_sm.h>
8 #include <caam_jr.h>
9 #include <caam_status.h>
10 #include <caam_sm.h>
11 #include <tee_api_defines.h>
12
13 /*
14 * Secure memory module private data
15 */
16 static struct sm_privdata {
17 vaddr_t baseaddr; /* Secure memory base address */
18 vaddr_t ctrl_addr; /* CAAM base address */
19 vaddr_t jr_addr; /* Job Ring base address */
20 paddr_t jr_offset; /* Job Ring offset */
21 } sm_privdata;
22
caam_sm_alloc(const struct caam_sm_page_desc * page_desc,struct caam_sm_page_addr * page_addr)23 enum caam_status caam_sm_alloc(const struct caam_sm_page_desc *page_desc,
24 struct caam_sm_page_addr *page_addr)
25 {
26 enum caam_status ret = CAAM_FAILURE;
27
28 if (!page_desc || !page_addr)
29 return TEE_ERROR_BAD_PARAMETERS;
30
31 ret = caam_hal_sm_check_page_partition(sm_privdata.jr_addr, page_desc);
32 if (ret != CAAM_NO_ERROR) {
33 SM_TRACE("Pages %u to %u or partition %u are out of bounds",
34 page_desc->page,
35 page_desc->page + page_desc->page_count - 1,
36 page_desc->partition);
37 return ret;
38 }
39
40 /* Check if partition is already allocated */
41 if (!caam_hal_sm_prtn_is_free(sm_privdata.jr_addr,
42 page_desc->partition)) {
43 SM_TRACE("Partition %u not available", page_desc->partition);
44 return CAAM_BUSY;
45 }
46
47 /* Open secure memory partition to all groups */
48 caam_hal_sm_open_access_perm(sm_privdata.jr_addr, page_desc->partition);
49 caam_hal_sm_set_access_all_group(sm_privdata.jr_addr,
50 page_desc->partition);
51
52 ret = caam_hal_sm_allocate_page(sm_privdata.jr_addr, page_desc);
53 if (ret != CAAM_NO_ERROR) {
54 SM_TRACE("Error allocation Pages %u to %u into partition %u",
55 page_desc->page,
56 page_desc->page + page_desc->page_count - 1,
57 page_desc->partition);
58
59 /* Free all potientiel pages allocated before failure */
60 return caam_hal_sm_deallocate_pages(sm_privdata.jr_addr,
61 page_desc);
62 }
63
64 page_addr->paddr = caam_hal_ctrl_get_smvaddr(sm_privdata.ctrl_addr,
65 sm_privdata.jr_offset) +
66 caam_hal_sm_get_pages_size(sm_privdata.jr_addr,
67 page_desc->page);
68 page_addr->vaddr = sm_privdata.baseaddr +
69 caam_hal_sm_get_pages_size(sm_privdata.jr_addr,
70 page_desc->page);
71
72 SM_TRACE("Partition %u Pages %u to %u allocated @0x%" PRIxVA
73 " (phys 0x@%" PRIxPA,
74 page_desc->partition, page_desc->page,
75 page_desc->page + page_desc->page_count - 1, page_addr->vaddr,
76 page_addr->paddr);
77
78 return CAAM_NO_ERROR;
79 }
80
caam_sm_free(const struct caam_sm_page_desc * page_desc)81 enum caam_status caam_sm_free(const struct caam_sm_page_desc *page_desc)
82 {
83 enum caam_status ret = CAAM_FAILURE;
84
85 SM_TRACE("Free Secure Memory pages %u to %u from partition %u",
86 page_desc->page, page_desc->page + page_desc->page_count,
87 page_desc->partition);
88
89 /*
90 * De-allocate partition. It automatically releases partition's pages
91 * to the pool of available pages. if the partition if marked as CSP,
92 * pages will be zeroized. If the partition is marked as PSP,
93 * partition and pages will not be de-allocated and a PSP will be
94 * returned.
95 */
96 if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr,
97 page_desc->partition)) {
98 SM_TRACE("Partition %u not owned by used JR",
99 page_desc->partition);
100 return TEE_ERROR_ACCESS_DENIED;
101 }
102
103 ret = caam_hal_sm_deallocate_pages(sm_privdata.jr_addr, page_desc);
104 if (ret) {
105 SM_TRACE("De-alloc pages %u to %u error 0x%" PRIx32,
106 page_desc->page,
107 page_desc->page + page_desc->page_count, ret);
108
109 return ret;
110 }
111
112 ret = caam_hal_sm_deallocate_partition(sm_privdata.jr_addr,
113 page_desc->partition);
114 if (ret) {
115 SM_TRACE("De-alloc partition %u error 0x%" PRIx32,
116 page_desc->partition, ret);
117 return ret;
118 }
119
120 return CAAM_NO_ERROR;
121 }
122
123 enum caam_status
caam_sm_set_access_perm(const struct caam_sm_page_desc * page_desc,unsigned int grp1_perm,unsigned int grp2_perm)124 caam_sm_set_access_perm(const struct caam_sm_page_desc *page_desc,
125 unsigned int grp1_perm, unsigned int grp2_perm)
126 {
127 uint32_t grp1 = 0;
128 uint32_t grp2 = 0;
129
130 if (!page_desc)
131 return CAAM_BAD_PARAM;
132
133 /* Check if the partition is already owned */
134 if (!caam_hal_sm_prtn_is_owned(sm_privdata.jr_addr,
135 page_desc->partition)) {
136 SM_TRACE("Partition %d not owned by current JR",
137 page_desc->partition);
138 return CAAM_FAILURE;
139 }
140
141 /*
142 * Set ourself to access Secure Memory group 1 and/or group 2
143 * function if @grp1_perm and/or @grp2_perm not equal 0.
144 *
145 * The Access Group is related to the Job Ring owner setting without
146 * the Secure Bit setting already managed by the Job Ring.
147 *
148 * If any group permissions are set, need to enable Secure World MID
149 * access in SMAG1/2 registers.
150 * Since both Non-Secure/Secure world has same MID, using JROWN_ARM_NS
151 * and if any grp1_perm/grp2_perm is set, need to enable permission
152 * for Secure World for partition in SMAG1/2 Registers.
153 */
154 if (grp1_perm)
155 grp1 = SHIFT_U32(1, JROWN_ARM_NS);
156
157 if (grp2_perm)
158 grp2 = SHIFT_U32(1, JROWN_ARM_NS);
159
160 caam_hal_sm_set_access_group(sm_privdata.jr_addr, page_desc->partition,
161 grp1, grp2);
162 caam_hal_sm_set_access_perm(sm_privdata.jr_addr, page_desc->partition,
163 grp1_perm, grp2_perm);
164
165 return CAAM_NO_ERROR;
166 }
167
caam_sm_init(struct caam_jrcfg * jrcfg)168 enum caam_status caam_sm_init(struct caam_jrcfg *jrcfg)
169 {
170 if (!jrcfg)
171 return CAAM_FAILURE;
172
173 sm_privdata.ctrl_addr = jrcfg->base;
174 sm_privdata.jr_addr = jrcfg->base + jrcfg->offset;
175 sm_privdata.jr_offset = jrcfg->offset;
176 sm_privdata.baseaddr = caam_hal_sm_get_base();
177
178 if (!sm_privdata.baseaddr)
179 return CAAM_FAILURE;
180
181 SM_TRACE("Secure Memory Base address = 0x%" PRIxVA,
182 sm_privdata.baseaddr);
183 SM_TRACE("CAAM controller address = 0x%" PRIxVA, sm_privdata.ctrl_addr);
184 SM_TRACE("CAAM Job Ring address = 0x%" PRIxVA, sm_privdata.jr_addr);
185
186 return CAAM_NO_ERROR;
187 }
188