scons: Group Source-s based on what SConscript included them.
[gem5.git] / src / arch / arm / isa.hh
1 /*
2 * Copyright (c) 2010, 2012-2016 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) 2009 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 * Authors: Gabe Black
41 */
42
43 #ifndef __ARCH_ARM_ISA_HH__
44 #define __ARCH_ARM_ISA_HH__
45
46 #include "arch/arm/isa_device.hh"
47 #include "arch/arm/registers.hh"
48 #include "arch/arm/system.hh"
49 #include "arch/arm/tlb.hh"
50 #include "arch/arm/types.hh"
51 #include "debug/Checkpoint.hh"
52 #include "sim/sim_object.hh"
53 #include "enums/DecoderFlavour.hh"
54
55 struct ArmISAParams;
56 struct DummyArmISADeviceParams;
57 class ThreadContext;
58 class Checkpoint;
59 class EventManager;
60
61 namespace ArmISA
62 {
63 class ISA : public SimObject
64 {
65 protected:
66 // Parent system
67 ArmSystem *system;
68
69 // Micro Architecture
70 const Enums::DecoderFlavour _decoderFlavour;
71
72 /** Dummy device for to handle non-existing ISA devices */
73 DummyISADevice dummyDevice;
74
75 // PMU belonging to this ISA
76 BaseISADevice *pmu;
77
78 // Generic timer interface belonging to this ISA
79 std::unique_ptr<BaseISADevice> timer;
80
81 // Cached copies of system-level properties
82 bool highestELIs64;
83 bool haveSecurity;
84 bool haveLPAE;
85 bool haveVirtualization;
86 bool haveLargeAsid64;
87 uint8_t physAddrRange64;
88
89 /** Register translation entry used in lookUpMiscReg */
90 struct MiscRegLUTEntry {
91 uint32_t lower;
92 uint32_t upper;
93 };
94
95 struct MiscRegInitializerEntry {
96 uint32_t index;
97 struct MiscRegLUTEntry entry;
98 };
99
100 /** Register table noting all translations */
101 static const struct MiscRegInitializerEntry MiscRegSwitch[];
102
103 /** Translation table accessible via the value of the register */
104 std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
105
106 MiscReg miscRegs[NumMiscRegs];
107 const IntRegIndex *intRegMap;
108
109 void
110 updateRegMap(CPSR cpsr)
111 {
112 if (cpsr.width == 0) {
113 intRegMap = IntReg64Map;
114 } else {
115 switch (cpsr.mode) {
116 case MODE_USER:
117 case MODE_SYSTEM:
118 intRegMap = IntRegUsrMap;
119 break;
120 case MODE_FIQ:
121 intRegMap = IntRegFiqMap;
122 break;
123 case MODE_IRQ:
124 intRegMap = IntRegIrqMap;
125 break;
126 case MODE_SVC:
127 intRegMap = IntRegSvcMap;
128 break;
129 case MODE_MON:
130 intRegMap = IntRegMonMap;
131 break;
132 case MODE_ABORT:
133 intRegMap = IntRegAbtMap;
134 break;
135 case MODE_HYP:
136 intRegMap = IntRegHypMap;
137 break;
138 case MODE_UNDEFINED:
139 intRegMap = IntRegUndMap;
140 break;
141 default:
142 panic("Unrecognized mode setting in CPSR.\n");
143 }
144 }
145 }
146
147 BaseISADevice &getGenericTimer(ThreadContext *tc);
148
149
150 private:
151 inline void assert32(ThreadContext *tc) {
152 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
153 assert(cpsr.width);
154 }
155
156 inline void assert64(ThreadContext *tc) {
157 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
158 assert(!cpsr.width);
159 }
160
161 void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
162 bool secure_lookup, uint8_t target_el);
163
164 void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
165
166 void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
167
168 void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
169 bool hyp, uint8_t target_el);
170
171 public:
172 void clear();
173 void clear64(const ArmISAParams *p);
174
175 MiscReg readMiscRegNoEffect(int misc_reg) const;
176 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
177 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
178 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
179
180 int
181 flattenIntIndex(int reg) const
182 {
183 assert(reg >= 0);
184 if (reg < NUM_ARCH_INTREGS) {
185 return intRegMap[reg];
186 } else if (reg < NUM_INTREGS) {
187 return reg;
188 } else if (reg == INTREG_SPX) {
189 CPSR cpsr = miscRegs[MISCREG_CPSR];
190 ExceptionLevel el = opModeToEL(
191 (OperatingMode) (uint8_t) cpsr.mode);
192 if (!cpsr.sp && el != EL0)
193 return INTREG_SP0;
194 switch (el) {
195 case EL3:
196 return INTREG_SP3;
197 case EL2:
198 return INTREG_SP2;
199 case EL1:
200 return INTREG_SP1;
201 case EL0:
202 return INTREG_SP0;
203 default:
204 panic("Invalid exception level");
205 break;
206 }
207 } else {
208 return flattenIntRegModeIndex(reg);
209 }
210 }
211
212 int
213 flattenFloatIndex(int reg) const
214 {
215 assert(reg >= 0);
216 return reg;
217 }
218
219 int
220 flattenCCIndex(int reg) const
221 {
222 assert(reg >= 0);
223 return reg;
224 }
225
226 int
227 flattenMiscIndex(int reg) const
228 {
229 assert(reg >= 0);
230 int flat_idx = reg;
231
232 if (reg == MISCREG_SPSR) {
233 CPSR cpsr = miscRegs[MISCREG_CPSR];
234 switch (cpsr.mode) {
235 case MODE_EL0T:
236 warn("User mode does not have SPSR\n");
237 flat_idx = MISCREG_SPSR;
238 break;
239 case MODE_EL1T:
240 case MODE_EL1H:
241 flat_idx = MISCREG_SPSR_EL1;
242 break;
243 case MODE_EL2T:
244 case MODE_EL2H:
245 flat_idx = MISCREG_SPSR_EL2;
246 break;
247 case MODE_EL3T:
248 case MODE_EL3H:
249 flat_idx = MISCREG_SPSR_EL3;
250 break;
251 case MODE_USER:
252 warn("User mode does not have SPSR\n");
253 flat_idx = MISCREG_SPSR;
254 break;
255 case MODE_FIQ:
256 flat_idx = MISCREG_SPSR_FIQ;
257 break;
258 case MODE_IRQ:
259 flat_idx = MISCREG_SPSR_IRQ;
260 break;
261 case MODE_SVC:
262 flat_idx = MISCREG_SPSR_SVC;
263 break;
264 case MODE_MON:
265 flat_idx = MISCREG_SPSR_MON;
266 break;
267 case MODE_ABORT:
268 flat_idx = MISCREG_SPSR_ABT;
269 break;
270 case MODE_HYP:
271 flat_idx = MISCREG_SPSR_HYP;
272 break;
273 case MODE_UNDEFINED:
274 flat_idx = MISCREG_SPSR_UND;
275 break;
276 default:
277 warn("Trying to access SPSR in an invalid mode: %d\n",
278 cpsr.mode);
279 flat_idx = MISCREG_SPSR;
280 break;
281 }
282 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
283 // Mutually exclusive CP15 register
284 switch (reg) {
285 case MISCREG_PRRR_MAIR0:
286 case MISCREG_PRRR_MAIR0_NS:
287 case MISCREG_PRRR_MAIR0_S:
288 {
289 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
290 // If the muxed reg has been flattened, work out the
291 // offset and apply it to the unmuxed reg
292 int idxOffset = reg - MISCREG_PRRR_MAIR0;
293 if (ttbcr.eae)
294 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
295 idxOffset);
296 else
297 flat_idx = flattenMiscIndex(MISCREG_PRRR +
298 idxOffset);
299 }
300 break;
301 case MISCREG_NMRR_MAIR1:
302 case MISCREG_NMRR_MAIR1_NS:
303 case MISCREG_NMRR_MAIR1_S:
304 {
305 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
306 // If the muxed reg has been flattened, work out the
307 // offset and apply it to the unmuxed reg
308 int idxOffset = reg - MISCREG_NMRR_MAIR1;
309 if (ttbcr.eae)
310 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
311 idxOffset);
312 else
313 flat_idx = flattenMiscIndex(MISCREG_NMRR +
314 idxOffset);
315 }
316 break;
317 case MISCREG_PMXEVTYPER_PMCCFILTR:
318 {
319 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
320 if (pmselr.sel == 31)
321 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
322 else
323 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
324 }
325 break;
326 default:
327 panic("Unrecognized misc. register.\n");
328 break;
329 }
330 } else {
331 if (miscRegInfo[reg][MISCREG_BANKED]) {
332 bool secureReg = haveSecurity && !highestELIs64 &&
333 inSecureState(miscRegs[MISCREG_SCR],
334 miscRegs[MISCREG_CPSR]);
335 flat_idx += secureReg ? 2 : 1;
336 }
337 }
338 return flat_idx;
339 }
340
341 std::pair<int,int> getMiscIndices(int misc_reg) const
342 {
343 // Note: indexes of AArch64 registers are left unchanged
344 int flat_idx = flattenMiscIndex(misc_reg);
345
346 if (lookUpMiscReg[flat_idx].lower == 0) {
347 return std::make_pair(flat_idx, 0);
348 }
349
350 // do additional S/NS flattenings if mapped to NS while in S
351 bool S = haveSecurity && !highestELIs64 &&
352 inSecureState(miscRegs[MISCREG_SCR],
353 miscRegs[MISCREG_CPSR]);
354 int lower = lookUpMiscReg[flat_idx].lower;
355 int upper = lookUpMiscReg[flat_idx].upper;
356 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
357 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
358 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
359 return std::make_pair(lower, upper);
360 }
361
362 void serialize(CheckpointOut &cp) const
363 {
364 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
365 SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
366
367 SERIALIZE_SCALAR(highestELIs64);
368 SERIALIZE_SCALAR(haveSecurity);
369 SERIALIZE_SCALAR(haveLPAE);
370 SERIALIZE_SCALAR(haveVirtualization);
371 SERIALIZE_SCALAR(haveLargeAsid64);
372 SERIALIZE_SCALAR(physAddrRange64);
373 }
374 void unserialize(CheckpointIn &cp)
375 {
376 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
377 UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
378 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
379 updateRegMap(tmp_cpsr);
380
381 UNSERIALIZE_SCALAR(highestELIs64);
382 UNSERIALIZE_SCALAR(haveSecurity);
383 UNSERIALIZE_SCALAR(haveLPAE);
384 UNSERIALIZE_SCALAR(haveVirtualization);
385 UNSERIALIZE_SCALAR(haveLargeAsid64);
386 UNSERIALIZE_SCALAR(physAddrRange64);
387 }
388
389 void startup(ThreadContext *tc) {}
390
391 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
392
393 /// Explicitly import the otherwise hidden startup
394 using SimObject::startup;
395
396 typedef ArmISAParams Params;
397
398 const Params *params() const;
399
400 ISA(Params *p);
401 };
402 }
403
404 #endif