stats: update stats for mmap() change.
[gem5.git] / src / arch / arm / isa.hh
1 /*
2 * Copyright (c) 2010, 2012-2015 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
64 /**
65 * At the moment there are 57 registers which need to be aliased/
66 * translated with other registers in the ISA. This enum helps with that
67 * translation.
68 */
69 enum translateTable {
70 miscRegTranslateCSSELR_EL1,
71 miscRegTranslateSCTLR_EL1,
72 miscRegTranslateSCTLR_EL2,
73 miscRegTranslateACTLR_EL1,
74 miscRegTranslateACTLR_EL2,
75 miscRegTranslateCPACR_EL1,
76 miscRegTranslateCPTR_EL2,
77 miscRegTranslateHCR_EL2,
78 miscRegTranslateMDCR_EL2,
79 miscRegTranslateHSTR_EL2,
80 miscRegTranslateHACR_EL2,
81 miscRegTranslateTTBR0_EL1,
82 miscRegTranslateTTBR1_EL1,
83 miscRegTranslateTTBR0_EL2,
84 miscRegTranslateVTTBR_EL2,
85 miscRegTranslateTCR_EL1,
86 miscRegTranslateTCR_EL2,
87 miscRegTranslateVTCR_EL2,
88 miscRegTranslateAFSR0_EL1,
89 miscRegTranslateAFSR1_EL1,
90 miscRegTranslateAFSR0_EL2,
91 miscRegTranslateAFSR1_EL2,
92 miscRegTranslateESR_EL2,
93 miscRegTranslateFAR_EL1,
94 miscRegTranslateFAR_EL2,
95 miscRegTranslateHPFAR_EL2,
96 miscRegTranslatePAR_EL1,
97 miscRegTranslateMAIR_EL1,
98 miscRegTranslateMAIR_EL2,
99 miscRegTranslateAMAIR_EL1,
100 miscRegTranslateVBAR_EL1,
101 miscRegTranslateVBAR_EL2,
102 miscRegTranslateCONTEXTIDR_EL1,
103 miscRegTranslateTPIDR_EL0,
104 miscRegTranslateTPIDRRO_EL0,
105 miscRegTranslateTPIDR_EL1,
106 miscRegTranslateTPIDR_EL2,
107 miscRegTranslateTEECR32_EL1,
108 miscRegTranslateCNTFRQ_EL0,
109 miscRegTranslateCNTPCT_EL0,
110 miscRegTranslateCNTVCT_EL0,
111 miscRegTranslateCNTVOFF_EL2,
112 miscRegTranslateCNTKCTL_EL1,
113 miscRegTranslateCNTHCTL_EL2,
114 miscRegTranslateCNTP_TVAL_EL0,
115 miscRegTranslateCNTP_CTL_EL0,
116 miscRegTranslateCNTP_CVAL_EL0,
117 miscRegTranslateCNTV_TVAL_EL0,
118 miscRegTranslateCNTV_CTL_EL0,
119 miscRegTranslateCNTV_CVAL_EL0,
120 miscRegTranslateCNTHP_TVAL_EL2,
121 miscRegTranslateCNTHP_CTL_EL2,
122 miscRegTranslateCNTHP_CVAL_EL2,
123 miscRegTranslateDACR32_EL2,
124 miscRegTranslateIFSR32_EL2,
125 miscRegTranslateTEEHBR32_EL1,
126 miscRegTranslateSDER32_EL3,
127 miscRegTranslateMax
128 };
129
130 class ISA : public SimObject
131 {
132 protected:
133 // Parent system
134 ArmSystem *system;
135
136 // Micro Architecture
137 const Enums::DecoderFlavour _decoderFlavour;
138
139 /** Dummy device for to handle non-existing ISA devices */
140 DummyISADevice dummyDevice;
141
142 // PMU belonging to this ISA
143 BaseISADevice *pmu;
144
145 // Generic timer interface belonging to this ISA
146 std::unique_ptr<BaseISADevice> timer;
147
148 // Cached copies of system-level properties
149 bool haveSecurity;
150 bool haveLPAE;
151 bool haveVirtualization;
152 bool haveLargeAsid64;
153 uint8_t physAddrRange64;
154
155 /** Register translation entry used in lookUpMiscReg */
156 struct MiscRegLUTEntry {
157 uint32_t lower;
158 uint32_t upper;
159 };
160
161 struct MiscRegInitializerEntry {
162 uint32_t index;
163 struct MiscRegLUTEntry entry;
164 };
165
166 /** Register table noting all translations */
167 static const struct MiscRegInitializerEntry
168 MiscRegSwitch[miscRegTranslateMax];
169
170 /** Translation table accessible via the value of the register */
171 std::vector<struct MiscRegLUTEntry> lookUpMiscReg;
172
173 MiscReg miscRegs[NumMiscRegs];
174 const IntRegIndex *intRegMap;
175
176 void
177 updateRegMap(CPSR cpsr)
178 {
179 if (cpsr.width == 0) {
180 intRegMap = IntReg64Map;
181 } else {
182 switch (cpsr.mode) {
183 case MODE_USER:
184 case MODE_SYSTEM:
185 intRegMap = IntRegUsrMap;
186 break;
187 case MODE_FIQ:
188 intRegMap = IntRegFiqMap;
189 break;
190 case MODE_IRQ:
191 intRegMap = IntRegIrqMap;
192 break;
193 case MODE_SVC:
194 intRegMap = IntRegSvcMap;
195 break;
196 case MODE_MON:
197 intRegMap = IntRegMonMap;
198 break;
199 case MODE_ABORT:
200 intRegMap = IntRegAbtMap;
201 break;
202 case MODE_HYP:
203 intRegMap = IntRegHypMap;
204 break;
205 case MODE_UNDEFINED:
206 intRegMap = IntRegUndMap;
207 break;
208 default:
209 panic("Unrecognized mode setting in CPSR.\n");
210 }
211 }
212 }
213
214 BaseISADevice &getGenericTimer(ThreadContext *tc);
215
216
217 private:
218 inline void assert32(ThreadContext *tc) {
219 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
220 assert(cpsr.width);
221 }
222
223 inline void assert64(ThreadContext *tc) {
224 CPSR cpsr M5_VAR_USED = readMiscReg(MISCREG_CPSR, tc);
225 assert(!cpsr.width);
226 }
227
228 void tlbiVA(ThreadContext *tc, MiscReg newVal, uint16_t asid,
229 bool secure_lookup, uint8_t target_el);
230
231 void tlbiALL(ThreadContext *tc, bool secure_lookup, uint8_t target_el);
232
233 void tlbiALLN(ThreadContext *tc, bool hyp, uint8_t target_el);
234
235 void tlbiMVA(ThreadContext *tc, MiscReg newVal, bool secure_lookup,
236 bool hyp, uint8_t target_el);
237
238 public:
239 void clear();
240 void clear64(const ArmISAParams *p);
241
242 MiscReg readMiscRegNoEffect(int misc_reg) const;
243 MiscReg readMiscReg(int misc_reg, ThreadContext *tc);
244 void setMiscRegNoEffect(int misc_reg, const MiscReg &val);
245 void setMiscReg(int misc_reg, const MiscReg &val, ThreadContext *tc);
246
247 int
248 flattenIntIndex(int reg) const
249 {
250 assert(reg >= 0);
251 if (reg < NUM_ARCH_INTREGS) {
252 return intRegMap[reg];
253 } else if (reg < NUM_INTREGS) {
254 return reg;
255 } else if (reg == INTREG_SPX) {
256 CPSR cpsr = miscRegs[MISCREG_CPSR];
257 ExceptionLevel el = opModeToEL(
258 (OperatingMode) (uint8_t) cpsr.mode);
259 if (!cpsr.sp && el != EL0)
260 return INTREG_SP0;
261 switch (el) {
262 case EL3:
263 return INTREG_SP3;
264 // @todo: uncomment this to enable Virtualization
265 // case EL2:
266 // return INTREG_SP2;
267 case EL1:
268 return INTREG_SP1;
269 case EL0:
270 return INTREG_SP0;
271 default:
272 panic("Invalid exception level");
273 break;
274 }
275 } else {
276 return flattenIntRegModeIndex(reg);
277 }
278 }
279
280 int
281 flattenFloatIndex(int reg) const
282 {
283 assert(reg >= 0);
284 return reg;
285 }
286
287 int
288 flattenCCIndex(int reg) const
289 {
290 assert(reg >= 0);
291 return reg;
292 }
293
294 int
295 flattenMiscIndex(int reg) const
296 {
297 assert(reg >= 0);
298 int flat_idx = reg;
299
300 if (reg == MISCREG_SPSR) {
301 CPSR cpsr = miscRegs[MISCREG_CPSR];
302 switch (cpsr.mode) {
303 case MODE_EL0T:
304 warn("User mode does not have SPSR\n");
305 flat_idx = MISCREG_SPSR;
306 break;
307 case MODE_EL1T:
308 case MODE_EL1H:
309 flat_idx = MISCREG_SPSR_EL1;
310 break;
311 case MODE_EL2T:
312 case MODE_EL2H:
313 flat_idx = MISCREG_SPSR_EL2;
314 break;
315 case MODE_EL3T:
316 case MODE_EL3H:
317 flat_idx = MISCREG_SPSR_EL3;
318 break;
319 case MODE_USER:
320 warn("User mode does not have SPSR\n");
321 flat_idx = MISCREG_SPSR;
322 break;
323 case MODE_FIQ:
324 flat_idx = MISCREG_SPSR_FIQ;
325 break;
326 case MODE_IRQ:
327 flat_idx = MISCREG_SPSR_IRQ;
328 break;
329 case MODE_SVC:
330 flat_idx = MISCREG_SPSR_SVC;
331 break;
332 case MODE_MON:
333 flat_idx = MISCREG_SPSR_MON;
334 break;
335 case MODE_ABORT:
336 flat_idx = MISCREG_SPSR_ABT;
337 break;
338 case MODE_HYP:
339 flat_idx = MISCREG_SPSR_HYP;
340 break;
341 case MODE_UNDEFINED:
342 flat_idx = MISCREG_SPSR_UND;
343 break;
344 default:
345 warn("Trying to access SPSR in an invalid mode: %d\n",
346 cpsr.mode);
347 flat_idx = MISCREG_SPSR;
348 break;
349 }
350 } else if (miscRegInfo[reg][MISCREG_MUTEX]) {
351 // Mutually exclusive CP15 register
352 switch (reg) {
353 case MISCREG_PRRR_MAIR0:
354 case MISCREG_PRRR_MAIR0_NS:
355 case MISCREG_PRRR_MAIR0_S:
356 {
357 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
358 // If the muxed reg has been flattened, work out the
359 // offset and apply it to the unmuxed reg
360 int idxOffset = reg - MISCREG_PRRR_MAIR0;
361 if (ttbcr.eae)
362 flat_idx = flattenMiscIndex(MISCREG_MAIR0 +
363 idxOffset);
364 else
365 flat_idx = flattenMiscIndex(MISCREG_PRRR +
366 idxOffset);
367 }
368 break;
369 case MISCREG_NMRR_MAIR1:
370 case MISCREG_NMRR_MAIR1_NS:
371 case MISCREG_NMRR_MAIR1_S:
372 {
373 TTBCR ttbcr = readMiscRegNoEffect(MISCREG_TTBCR);
374 // If the muxed reg has been flattened, work out the
375 // offset and apply it to the unmuxed reg
376 int idxOffset = reg - MISCREG_NMRR_MAIR1;
377 if (ttbcr.eae)
378 flat_idx = flattenMiscIndex(MISCREG_MAIR1 +
379 idxOffset);
380 else
381 flat_idx = flattenMiscIndex(MISCREG_NMRR +
382 idxOffset);
383 }
384 break;
385 case MISCREG_PMXEVTYPER_PMCCFILTR:
386 {
387 PMSELR pmselr = miscRegs[MISCREG_PMSELR];
388 if (pmselr.sel == 31)
389 flat_idx = flattenMiscIndex(MISCREG_PMCCFILTR);
390 else
391 flat_idx = flattenMiscIndex(MISCREG_PMXEVTYPER);
392 }
393 break;
394 default:
395 panic("Unrecognized misc. register.\n");
396 break;
397 }
398 } else {
399 if (miscRegInfo[reg][MISCREG_BANKED]) {
400 bool secureReg = haveSecurity &&
401 inSecureState(miscRegs[MISCREG_SCR],
402 miscRegs[MISCREG_CPSR]);
403 flat_idx += secureReg ? 2 : 1;
404 }
405 }
406 return flat_idx;
407 }
408
409 void serialize(CheckpointOut &cp) const
410 {
411 DPRINTF(Checkpoint, "Serializing Arm Misc Registers\n");
412 SERIALIZE_ARRAY(miscRegs, NumMiscRegs);
413
414 SERIALIZE_SCALAR(haveSecurity);
415 SERIALIZE_SCALAR(haveLPAE);
416 SERIALIZE_SCALAR(haveVirtualization);
417 SERIALIZE_SCALAR(haveLargeAsid64);
418 SERIALIZE_SCALAR(physAddrRange64);
419 }
420 void unserialize(CheckpointIn &cp)
421 {
422 DPRINTF(Checkpoint, "Unserializing Arm Misc Registers\n");
423 UNSERIALIZE_ARRAY(miscRegs, NumMiscRegs);
424 CPSR tmp_cpsr = miscRegs[MISCREG_CPSR];
425 updateRegMap(tmp_cpsr);
426
427 UNSERIALIZE_SCALAR(haveSecurity);
428 UNSERIALIZE_SCALAR(haveLPAE);
429 UNSERIALIZE_SCALAR(haveVirtualization);
430 UNSERIALIZE_SCALAR(haveLargeAsid64);
431 UNSERIALIZE_SCALAR(physAddrRange64);
432 }
433
434 void startup(ThreadContext *tc) {}
435
436 Enums::DecoderFlavour decoderFlavour() const { return _decoderFlavour; }
437
438 /// Explicitly import the otherwise hidden startup
439 using SimObject::startup;
440
441 typedef ArmISAParams Params;
442
443 const Params *params() const;
444
445 ISA(Params *p);
446 };
447 }
448
449 #endif