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