arch-arm: Implementing SecureEL2 feature for Armv8
[gem5.git] / src / arch / arm / system.cc
1 /*
2 * Copyright (c) 2010, 2012-2013, 2015,2017-2020 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder. You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2002-2006 The Regents of The University of Michigan
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 */
40
41 #include "arch/arm/system.hh"
42
43 #include <iostream>
44
45 #include "arch/arm/fs_workload.hh"
46 #include "arch/arm/semihosting.hh"
47 #include "base/loader/object_file.hh"
48 #include "base/loader/symtab.hh"
49 #include "cpu/thread_context.hh"
50 #include "dev/arm/fvp_base_pwr_ctrl.hh"
51 #include "dev/arm/gic_v2.hh"
52 #include "mem/physical.hh"
53
54 using namespace std;
55 using namespace Linux;
56
57 ArmSystem::ArmSystem(Params *p)
58 : System(p),
59 _haveSecurity(p->have_security),
60 _haveLPAE(p->have_lpae),
61 _haveVirtualization(p->have_virtualization),
62 _haveCrypto(p->have_crypto),
63 _genericTimer(nullptr),
64 _gic(nullptr),
65 _pwrCtrl(nullptr),
66 _highestELIs64(p->highest_el_is_64),
67 _physAddrRange64(p->phys_addr_range_64),
68 _haveLargeAsid64(p->have_large_asid_64),
69 _haveSVE(p->have_sve),
70 _sveVL(p->sve_vl),
71 _haveLSE(p->have_lse),
72 _havePAN(p->have_pan),
73 _haveSecEL2(p->have_secel2),
74 semihosting(p->semihosting),
75 multiProc(p->multi_proc)
76 {
77 if (p->auto_reset_addr) {
78 _resetAddr = workload->getEntry();
79 } else {
80 _resetAddr = p->reset_addr;
81 warn_if(workload->getEntry() != _resetAddr,
82 "Workload entry point %#x and reset address %#x are different",
83 workload->getEntry(), _resetAddr);
84 }
85
86 bool wl_is_64 = (workload->getArch() == Loader::Arm64);
87 if (wl_is_64 != _highestELIs64) {
88 warn("Highest ARM exception-level set to AArch%d but the workload "
89 "is for AArch%d. Assuming you wanted these to match.",
90 _highestELIs64 ? 64 : 32, wl_is_64 ? 64 : 32);
91 _highestELIs64 = wl_is_64;
92 }
93
94 if (_highestELIs64 && (
95 _physAddrRange64 < 32 ||
96 _physAddrRange64 > 48 ||
97 (_physAddrRange64 % 4 != 0 && _physAddrRange64 != 42))) {
98 fatal("Invalid physical address range (%d)\n", _physAddrRange64);
99 }
100 }
101
102 bool
103 ArmSystem::haveSecurity(ThreadContext *tc)
104 {
105 return FullSystem? getArmSystem(tc)->haveSecurity() : false;
106 }
107
108 bool
109 ArmSystem::haveLPAE(ThreadContext *tc)
110 {
111 return FullSystem? getArmSystem(tc)->haveLPAE() : false;
112 }
113
114 bool
115 ArmSystem::haveVirtualization(ThreadContext *tc)
116 {
117 return FullSystem? getArmSystem(tc)->haveVirtualization() : false;
118 }
119
120 bool
121 ArmSystem::highestELIs64(ThreadContext *tc)
122 {
123 return FullSystem? getArmSystem(tc)->highestELIs64() : true;
124 }
125
126 ExceptionLevel
127 ArmSystem::highestEL(ThreadContext *tc)
128 {
129 return FullSystem? getArmSystem(tc)->highestEL() : EL1;
130 }
131
132 bool
133 ArmSystem::haveEL(ThreadContext *tc, ExceptionLevel el)
134 {
135 switch (el) {
136 case EL0:
137 case EL1:
138 return true;
139 case EL2:
140 return haveVirtualization(tc);
141 case EL3:
142 return haveSecurity(tc);
143 default:
144 warn("Unimplemented Exception Level\n");
145 return false;
146 }
147 }
148
149 Addr
150 ArmSystem::resetAddr(ThreadContext *tc)
151 {
152 return getArmSystem(tc)->resetAddr();
153 }
154
155 uint8_t
156 ArmSystem::physAddrRange(ThreadContext *tc)
157 {
158 return getArmSystem(tc)->physAddrRange();
159 }
160
161 Addr
162 ArmSystem::physAddrMask(ThreadContext *tc)
163 {
164 return getArmSystem(tc)->physAddrMask();
165 }
166
167 bool
168 ArmSystem::haveLargeAsid64(ThreadContext *tc)
169 {
170 return getArmSystem(tc)->haveLargeAsid64();
171 }
172
173 bool
174 ArmSystem::haveSemihosting(ThreadContext *tc)
175 {
176 return FullSystem && getArmSystem(tc)->haveSemihosting();
177 }
178
179 bool
180 ArmSystem::callSemihosting64(ThreadContext *tc, bool gem5_ops)
181 {
182 return getArmSystem(tc)->semihosting->call64(tc, gem5_ops);
183 }
184
185 bool
186 ArmSystem::callSemihosting32(ThreadContext *tc, bool gem5_ops)
187 {
188 return getArmSystem(tc)->semihosting->call32(tc, gem5_ops);
189 }
190
191 bool
192 ArmSystem::callSemihosting(ThreadContext *tc, bool gem5_ops)
193 {
194 if (ArmISA::inAArch64(tc))
195 return callSemihosting64(tc, gem5_ops);
196 else
197 return callSemihosting32(tc, gem5_ops);
198 }
199
200 void
201 ArmSystem::callSetStandByWfi(ThreadContext *tc)
202 {
203 if (FVPBasePwrCtrl *pwr_ctrl = getArmSystem(tc)->getPowerController())
204 pwr_ctrl->setStandByWfi(tc);
205 }
206
207 void
208 ArmSystem::callClearStandByWfi(ThreadContext *tc)
209 {
210 if (FVPBasePwrCtrl *pwr_ctrl = getArmSystem(tc)->getPowerController())
211 pwr_ctrl->clearStandByWfi(tc);
212 }
213
214 bool
215 ArmSystem::callSetWakeRequest(ThreadContext *tc)
216 {
217 if (FVPBasePwrCtrl *pwr_ctrl = getArmSystem(tc)->getPowerController())
218 return pwr_ctrl->setWakeRequest(tc);
219 else
220 return true;
221 }
222
223 void
224 ArmSystem::callClearWakeRequest(ThreadContext *tc)
225 {
226 if (FVPBasePwrCtrl *pwr_ctrl = getArmSystem(tc)->getPowerController())
227 pwr_ctrl->clearWakeRequest(tc);
228 }
229
230 ArmSystem *
231 ArmSystemParams::create()
232 {
233 return new ArmSystem(this);
234 }