Deleted Added
sdiff udiff text old ( 12106:7784fac1b159 ) new ( 12109:f29e9c5418aa )
full compact
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
55struct ArmISAParams;
56struct DummyArmISADeviceParams;
57class ThreadContext;
58class Checkpoint;
59class EventManager;
60
61namespace 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 RegId
181 flattenRegId(const RegId& regId) const
182 {
183 switch (regId.classValue()) {
184 case IntRegClass:
185 return RegId(IntRegClass, flattenIntIndex(regId.index()));
186 case FloatRegClass:
187 return RegId(FloatRegClass, flattenFloatIndex(regId.index()));
188 case CCRegClass:
189 return RegId(CCRegClass, flattenCCIndex(regId.index()));
190 case MiscRegClass:
191 return RegId(MiscRegClass, flattenMiscIndex(regId.index()));
192 }
193 return RegId();
194 }
195
196 int
197 flattenIntIndex(int reg) const
198 {
199 assert(reg >= 0);
200 if (reg < NUM_ARCH_INTREGS) {
201 return intRegMap[reg];
202 } else if (reg < NUM_INTREGS) {
203 return reg;
204 } else if (reg == INTREG_SPX) {
205 CPSR cpsr = miscRegs[MISCREG_CPSR];
206 ExceptionLevel el = opModeToEL(
207 (OperatingMode) (uint8_t) cpsr.mode);
208 if (!cpsr.sp && el != EL0)
209 return INTREG_SP0;
210 switch (el) {
211 case EL3:
212 return INTREG_SP3;
213 case EL2:
214 return INTREG_SP2;
215 case EL1:
216 return INTREG_SP1;
217 case EL0:
218 return INTREG_SP0;
219 default:
220 panic("Invalid exception level");
221 break;
222 }
223 } else {
224 return flattenIntRegModeIndex(reg);
225 }
226 }
227
228 int
229 flattenFloatIndex(int reg) const
230 {
231 assert(reg >= 0);
232 return reg;
233 }
234
235 int
236 flattenCCIndex(int reg) const
237 {
238 assert(reg >= 0);
239 return reg;
240 }
241
242 int
243 flattenMiscIndex(int reg) const
244 {
245 assert(reg >= 0);
246 int flat_idx = reg;
247
248 if (reg == MISCREG_SPSR) {
249 CPSR cpsr = miscRegs[MISCREG_CPSR];
250 switch (cpsr.mode) {
251 case MODE_EL0T:
252 warn("User mode does not have SPSR\n");
253 flat_idx = MISCREG_SPSR;
254 break;
255 case MODE_EL1T:
256 case MODE_EL1H:
257 flat_idx = MISCREG_SPSR_EL1;
258 break;
259 case MODE_EL2T:
260 case MODE_EL2H:
261 flat_idx = MISCREG_SPSR_EL2;
262 break;
263 case MODE_EL3T:
264 case MODE_EL3H:
265 flat_idx = MISCREG_SPSR_EL3;
266 break;
267 case MODE_USER:
268 warn("User mode does not have SPSR\n");
269 flat_idx = MISCREG_SPSR;
270 break;
271 case MODE_FIQ:
272 flat_idx = MISCREG_SPSR_FIQ;
273 break;
274 case MODE_IRQ:
275 flat_idx = MISCREG_SPSR_IRQ;
276 break;
277 case MODE_SVC:
278 flat_idx = MISCREG_SPSR_SVC;
279 break;
280 case MODE_MON:
281 flat_idx = MISCREG_SPSR_MON;
282 break;
283 case MODE_ABORT:
284 flat_idx = MISCREG_SPSR_ABT;
285 break;
286 case MODE_HYP:
287 flat_idx = MISCREG_SPSR_HYP;
288 break;
289 case MODE_UNDEFINED:
290 flat_idx = MISCREG_SPSR_UND;
291 break;
292 default:
293 warn("Trying to access SPSR in an invalid mode: %d\n",
294 cpsr.mode);
295 flat_idx = MISCREG_SPSR;
296 break;
297 }
298 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
299 // Mutually exclusive CP15 register
300 switch (reg) {
301 case MISCREG_PRRR_MAIR0:
302 case MISCREG_PRRR_MAIR0_NS:
303 case MISCREG_PRRR_MAIR0_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_PRRR_MAIR0;
309 if (ttbcr.eae)
310 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
311 idxOffset);
312 else
313 flat_idx = flattenMiscIndex(MISCREG_PRRR +
314 idxOffset);
315 }
316 break;
317 case MISCREG_NMRR_MAIR1:
318 case MISCREG_NMRR_MAIR1_NS:
319 case MISCREG_NMRR_MAIR1_S:
320 {
321 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
322 // If the muxed reg has been flattened, work out the
323 // offset and apply it to the unmuxed reg
324 int idxOffset = reg - MISCREG_NMRR_MAIR1;
325 if (ttbcr.eae)
326 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
327 idxOffset);
328 else
329 flat_idx = flattenMiscIndex(MISCREG_NMRR +
330 idxOffset);
331 }
332 break;
333 case MISCREG_PMXEVTYPER_PMCCFILTR:
334 {
335 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
336 if (pmselr.sel == 31)
337 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
338 else
339 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
340 }
341 break;
342 default:
343 panic("Unrecognized misc. register.\n");
344 break;
345 }
346 } else {
347 if (miscRegInfo[reg][MISCREG_BANKED]) {
348 bool secureReg = haveSecurity && !highestELIs64 &&
349 inSecureState(miscRegs[MISCREG_SCR],
350 miscRegs[MISCREG_CPSR]);
351 flat_idx += secureReg ? 2 : 1;
352 }
353 }
354 return flat_idx;
355 }
356
357 std::pair<int,int> getMiscIndices(int misc_reg) const
358 {
359 // Note: indexes of AArch64 registers are left unchanged
360 int flat_idx = flattenMiscIndex(misc_reg);
361
362 if (lookUpMiscReg[flat_idx].lower == 0) {
363 return std::make_pair(flat_idx, 0);
364 }
365
366 // do additional S/NS flattenings if mapped to NS while in S
367 bool S = haveSecurity && !highestELIs64 &&
368 inSecureState(miscRegs[MISCREG_SCR],
369 miscRegs[MISCREG_CPSR]);
370 int lower = lookUpMiscReg[flat_idx].lower;
371 int upper = lookUpMiscReg[flat_idx].upper;
372 // upper == 0, which is CPSR, is not MISCREG_BANKED_CHILD (no-op)
373 lower += S && miscRegInfo[lower][MISCREG_BANKED_CHILD];
374 upper += S && miscRegInfo[upper][MISCREG_BANKED_CHILD];
375 return std::make_pair(lower, upper);
376 }
377
378 void serialize(CheckpointOut &cp) const
379 {
380 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
381 SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
382
383 SERIALIZE_SCALAR(highestELIs64);
384 SERIALIZE_SCALAR(haveSecurity);
385 SERIALIZE_SCALAR(haveLPAE);
386 SERIALIZE_SCALAR(haveVirtualization);
387 SERIALIZE_SCALAR(haveLargeAsid64);
388 SERIALIZE_SCALAR(physAddrRange64);
389 }
390 void unserialize(CheckpointIn &cp)
391 {
392 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
393 UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
394 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
395 updateRegMap(tmp_cpsr);
396
397 UNSERIALIZE_SCALAR(highestELIs64);
398 UNSERIALIZE_SCALAR(haveSecurity);
399 UNSERIALIZE_SCALAR(haveLPAE);
400 UNSERIALIZE_SCALAR(haveVirtualization);
401 UNSERIALIZE_SCALAR(haveLargeAsid64);
402 UNSERIALIZE_SCALAR(physAddrRange64);
403 }
404
405 void startup(ThreadContext *tc) {}
406
407 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
408
409 /// Explicitly import the otherwise hidden startup
410 using SimObject::startup;
411
412 typedef ArmISAParams Params;
413
414 const Params *params() const;
415
416 ISA(Params *p);
417 };
418}
419
420#endif