1 /*
2 * Copyright (c) 2015 Google Inc. All rights reserved
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23
24 #include <arch/mmu.h>
25 #include <assert.h>
26 #include <debug.h>
27 #include <err.h>
28 #include <inttypes.h>
29 #include <lib/sm.h>
30 #include <trace.h>
31
32 #define LOCAL_TRACE 0
33
34 /* 48-bit physical address 47:12 */
35 #define NS_PTE_PHYSADDR_MASK (0xFFFFFFFFF000ULL)
36 #define NS_PTE_PHYSADDR(pte) ((pte) & (NS_PTE_PHYSADDR_MASK))
37 #define NS_PTE_ATTR(pte) ((pte) & ~(NS_PTE_PHYSADDR_MASK))
38
39 /* Access permissions AP[2:1]
40 * EL0 EL1
41 * 00 None RW
42 * 01 RW RW
43 * 10 None RO
44 * 11 RO RO
45 */
46 #define NS_PTE_AP(pte) (((pte) >> 6) & 0x3)
47 #define NS_PTE_AP_U_RW(pte) (NS_PTE_AP(pte) == 0x1)
48 #define NS_PTE_AP_U(pte) (NS_PTE_AP(pte) & 0x1)
49 #define NS_PTE_AP_RO(pte) (NS_PTE_AP(pte) & 0x2)
50
51 /* Shareablility attrs */
52 #define NS_PTE_ATTR_SHAREABLE(pte) (((pte) >> 8) & 0x3)
53
54 /* cache attrs encoded in the top bits 55:49 of the PTE*/
55 #define NS_PTE_ATTR_MAIR(pte) (((pte) >> 48) & 0xFF)
56
57 /* Inner cache attrs MAIR_ATTR_N[3:0] */
58 #define NS_PTE_ATTR_INNER(pte) ((NS_PTE_ATTR_MAIR(pte)) & 0xF)
59
60 /* Outer cache attrs MAIR_ATTR_N[7:4] */
61 #define NS_PTE_ATTR_OUTER(pte) (((NS_PTE_ATTR_MAIR(pte)) & 0xF0) >> 4)
62
63 /* Normal memory */
64 /* inner and outer write back read/write allocate */
65 #define NS_MAIR_NORMAL_CACHED_WB_RWA 0xFF
66 /* inner and outer write back read/write allocate tagged */
67 #define NS_MAIR_NORMAL_CACHED_WB_RWA_TAGGED 0xF0
68 /* inner and outer write through read allocate */
69 #define NS_MAIR_NORMAL_CACHED_WT_RA 0xAA
70 /* inner and outer wriet back, read allocate */
71 #define NS_MAIR_NORMAL_CACHED_WB_RA 0xEE
72 /* uncached */
73 #define NS_MAIR_NORMAL_UNCACHED 0x44
74
75 /* Device memory */
76 /* nGnRnE (strongly ordered) */
77 #define NS_MAIR_DEVICE_STRONGLY_ORDERED 0x00
78 /* nGnRE (device) */
79 #define NS_MAIR_DEVICE 0x04
80 /* GRE */
81 #define NS_MAIR_DEVICE_GRE 0x0C
82
83 /* sharaeble attributes */
84 #define NS_NON_SHAREABLE 0x0
85 #define NS_OUTER_SHAREABLE 0x2
86 #define NS_INNER_SHAREABLE 0x3
87
88 #define NS_PTE_ATTR_DEFAULT_CACHED \
89 ((uint64_t)NS_MAIR_NORMAL_CACHED_WB_RWA << 48 | NS_INNER_SHAREABLE << 8)
90
91 /* helper function to decode ns memory attrubutes */
sm_decode_ns_memory_attr(struct ns_page_info * pinf,ns_addr_t * ppa,uint * pmmu)92 status_t sm_decode_ns_memory_attr(struct ns_page_info* pinf,
93 ns_addr_t* ppa,
94 uint* pmmu) {
95 uint mmu_flags = 0;
96
97 if (!pinf)
98 return ERR_INVALID_ARGS;
99
100 LTRACEF("raw=0x%" PRIx64 ": pa=0x%llx: mair=0x%x, sharable=0x%x\n",
101 pinf->attr, NS_PTE_PHYSADDR(pinf->attr),
102 (uint)NS_PTE_ATTR_MAIR(pinf->attr),
103 (uint)NS_PTE_ATTR_SHAREABLE(pinf->attr));
104
105 if (ppa)
106 *ppa = (ns_addr_t)NS_PTE_PHYSADDR(pinf->attr);
107
108 if (pmmu) {
109 uint64_t attr = NS_PTE_ATTR(pinf->attr);
110 if (attr == 0) {
111 if (sm_get_api_version() >= TRUSTY_API_VERSION_PHYS_MEM_OBJ) {
112 LTRACEF("Unsupported 0 memory attr\n");
113 return ERR_NOT_SUPPORTED;
114 }
115 /*
116 * Some existing clients don't pass attibutes and assume cached
117 * write-able memory.
118 */
119 attr = NS_PTE_ATTR_DEFAULT_CACHED;
120 }
121
122 /* match settings to mmu flags */
123 switch ((uint)NS_PTE_ATTR_MAIR(attr)) {
124 /*
125 * Normal tagged memory and normal untagged memory can be treated the
126 * same here, because we only ever map it as untagged in Trusty. This
127 * is enforced in vmm by only allowing pmm objecs to be tagged.
128 */
129 case NS_MAIR_NORMAL_CACHED_WB_RWA:
130 case NS_MAIR_NORMAL_CACHED_WB_RWA_TAGGED:
131 mmu_flags |= ARCH_MMU_FLAG_CACHED;
132 break;
133 case NS_MAIR_NORMAL_UNCACHED:
134 mmu_flags |= ARCH_MMU_FLAG_UNCACHED;
135 break;
136 default:
137 LTRACEF("Unsupported memory attr 0x%x\n",
138 (uint)NS_PTE_ATTR_MAIR(attr));
139 return ERR_NOT_SUPPORTED;
140 }
141 #if WITH_SMP | WITH_SHAREABLE_CACHE
142 if (mmu_flags == ARCH_MMU_FLAG_CACHED) {
143 if (NS_PTE_ATTR_SHAREABLE(attr) != NS_INNER_SHAREABLE) {
144 LTRACEF("Unsupported sharable attr 0x%x\n",
145 (uint)NS_PTE_ATTR_SHAREABLE(attr));
146 return ERR_NOT_SUPPORTED;
147 }
148 }
149 #endif
150 if (NS_PTE_AP_U(attr))
151 mmu_flags |= ARCH_MMU_FLAG_PERM_USER;
152
153 if (NS_PTE_AP_RO(attr))
154 mmu_flags |= ARCH_MMU_FLAG_PERM_RO;
155
156 *pmmu = mmu_flags | ARCH_MMU_FLAG_NS | ARCH_MMU_FLAG_PERM_NO_EXECUTE;
157 }
158
159 return NO_ERROR;
160 }
161