arch-arm: GenericTimer arch regs, perms/trapping
[gem5.git] / src / arch / arm / insts / misc64.cc
1 /*
2 * Copyright (c) 2011-2013,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 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions are
16 * met: redistributions of source code must retain the above copyright
17 * notice, this list of conditions and the following disclaimer;
18 * redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in the
20 * documentation and/or other materials provided with the distribution;
21 * neither the name of the copyright holders nor the names of its
22 * contributors may be used to endorse or promote products derived from
23 * this software without specific prior written permission.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
28 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
29 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
30 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
31 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
32 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
33 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
34 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
35 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36 */
37
38 #include "arch/arm/insts/misc64.hh"
39 #include "arch/arm/isa.hh"
40
41 std::string
42 ImmOp64::generateDisassembly(Addr pc, const SymbolTable *symtab) const
43 {
44 std::stringstream ss;
45 printMnemonic(ss, "", false);
46 ccprintf(ss, "#0x%x", imm);
47 return ss.str();
48 }
49
50 std::string
51 RegRegImmImmOp64::generateDisassembly(Addr pc, const SymbolTable *symtab) const
52 {
53 std::stringstream ss;
54 printMnemonic(ss, "", false);
55 printIntReg(ss, dest);
56 ss << ", ";
57 printIntReg(ss, op1);
58 ccprintf(ss, ", #%d, #%d", imm1, imm2);
59 return ss.str();
60 }
61
62 std::string
63 RegRegRegImmOp64::generateDisassembly(
64 Addr pc, const SymbolTable *symtab) const
65 {
66 std::stringstream ss;
67 printMnemonic(ss, "", false);
68 printIntReg(ss, dest);
69 ss << ", ";
70 printIntReg(ss, op1);
71 ss << ", ";
72 printIntReg(ss, op2);
73 ccprintf(ss, ", #%d", imm);
74 return ss.str();
75 }
76
77 std::string
78 UnknownOp64::generateDisassembly(Addr pc, const SymbolTable *symtab) const
79 {
80 return csprintf("%-10s (inst %#08x)", "unknown", encoding());
81 }
82
83 Fault
84 MiscRegOp64::trap(ThreadContext *tc, MiscRegIndex misc_reg,
85 ExceptionLevel el, uint32_t immediate) const
86 {
87 ExceptionClass ec = EC_TRAPPED_MSR_MRS_64;
88
89 // Check for traps to supervisor (FP/SIMD regs)
90 if (el <= EL1 && checkEL1Trap(tc, misc_reg, el, ec, immediate)) {
91 return std::make_shared<SupervisorTrap>(machInst, immediate, ec);
92 }
93
94 // Check for traps to hypervisor
95 if ((ArmSystem::haveVirtualization(tc) && el <= EL2) &&
96 checkEL2Trap(tc, misc_reg, el, ec, immediate)) {
97 return std::make_shared<HypervisorTrap>(machInst, immediate, ec);
98 }
99
100 // Check for traps to secure monitor
101 if ((ArmSystem::haveSecurity(tc) && el <= EL3) &&
102 checkEL3Trap(tc, misc_reg, el, ec, immediate)) {
103 return std::make_shared<SecureMonitorTrap>(machInst, immediate, ec);
104 }
105
106 return NoFault;
107 }
108
109 bool
110 MiscRegOp64::checkEL1Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
111 ExceptionLevel el, ExceptionClass &ec,
112 uint32_t &immediate) const
113 {
114 const CPACR cpacr = tc->readMiscReg(MISCREG_CPACR_EL1);
115
116 bool trap_to_sup = false;
117 switch (misc_reg) {
118 case MISCREG_FPCR:
119 case MISCREG_FPSR:
120 case MISCREG_FPEXC32_EL2:
121 if ((el == EL0 && cpacr.fpen != 0x3) ||
122 (el == EL1 && !(cpacr.fpen & 0x1))) {
123 trap_to_sup = true;
124 ec = EC_TRAPPED_SIMD_FP;
125 immediate = 0x1E00000;
126 }
127 break;
128 // Generic Timer
129 case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
130 trap_to_sup = el == EL0 &&
131 isGenericTimerSystemAccessTrapEL1(misc_reg, tc);
132 break;
133 default:
134 break;
135 }
136 return trap_to_sup;
137 }
138
139 bool
140 MiscRegOp64::checkEL2Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
141 ExceptionLevel el, ExceptionClass &ec,
142 uint32_t &immediate) const
143 {
144 const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL2);
145 const HCR hcr = tc->readMiscReg(MISCREG_HCR_EL2);
146 const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
147 const CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
148
149 bool trap_to_hyp = false;
150
151 if (!inSecureState(scr, cpsr) && (el != EL2)) {
152 switch (misc_reg) {
153 // FP/SIMD regs
154 case MISCREG_FPCR:
155 case MISCREG_FPSR:
156 case MISCREG_FPEXC32_EL2:
157 trap_to_hyp = cptr.tfp;
158 ec = EC_TRAPPED_SIMD_FP;
159 immediate = 0x1E00000;
160 break;
161 // CPACR
162 case MISCREG_CPACR_EL1:
163 trap_to_hyp = cptr.tcpac && el == EL1;
164 break;
165 // Virtual memory control regs
166 case MISCREG_SCTLR_EL1:
167 case MISCREG_TTBR0_EL1:
168 case MISCREG_TTBR1_EL1:
169 case MISCREG_TCR_EL1:
170 case MISCREG_ESR_EL1:
171 case MISCREG_FAR_EL1:
172 case MISCREG_AFSR0_EL1:
173 case MISCREG_AFSR1_EL1:
174 case MISCREG_MAIR_EL1:
175 case MISCREG_AMAIR_EL1:
176 case MISCREG_CONTEXTIDR_EL1:
177 trap_to_hyp =
178 ((hcr.trvm && miscRead) || (hcr.tvm && !miscRead)) &&
179 el == EL1;
180 break;
181 // TLB maintenance instructions
182 case MISCREG_TLBI_VMALLE1:
183 case MISCREG_TLBI_VAE1_Xt:
184 case MISCREG_TLBI_ASIDE1_Xt:
185 case MISCREG_TLBI_VAAE1_Xt:
186 case MISCREG_TLBI_VALE1_Xt:
187 case MISCREG_TLBI_VAALE1_Xt:
188 case MISCREG_TLBI_VMALLE1IS:
189 case MISCREG_TLBI_VAE1IS_Xt:
190 case MISCREG_TLBI_ASIDE1IS_Xt:
191 case MISCREG_TLBI_VAAE1IS_Xt:
192 case MISCREG_TLBI_VALE1IS_Xt:
193 case MISCREG_TLBI_VAALE1IS_Xt:
194 trap_to_hyp = hcr.ttlb && el == EL1;
195 break;
196 // Cache maintenance instructions to the point of unification
197 case MISCREG_IC_IVAU_Xt:
198 case MISCREG_ICIALLU:
199 case MISCREG_ICIALLUIS:
200 case MISCREG_DC_CVAU_Xt:
201 trap_to_hyp = hcr.tpu && el <= EL1;
202 break;
203 // Data/Unified cache maintenance instructions to the
204 // point of coherency
205 case MISCREG_DC_IVAC_Xt:
206 case MISCREG_DC_CIVAC_Xt:
207 case MISCREG_DC_CVAC_Xt:
208 trap_to_hyp = hcr.tpc && el <= EL1;
209 break;
210 // Data/Unified cache maintenance instructions by set/way
211 case MISCREG_DC_ISW_Xt:
212 case MISCREG_DC_CSW_Xt:
213 case MISCREG_DC_CISW_Xt:
214 trap_to_hyp = hcr.tsw && el == EL1;
215 break;
216 // ACTLR
217 case MISCREG_ACTLR_EL1:
218 trap_to_hyp = hcr.tacr && el == EL1;
219 break;
220
221 case MISCREG_APDAKeyHi_EL1:
222 case MISCREG_APDAKeyLo_EL1:
223 case MISCREG_APDBKeyHi_EL1:
224 case MISCREG_APDBKeyLo_EL1:
225 case MISCREG_APGAKeyHi_EL1:
226 case MISCREG_APGAKeyLo_EL1:
227 case MISCREG_APIAKeyHi_EL1:
228 case MISCREG_APIAKeyLo_EL1:
229 case MISCREG_APIBKeyHi_EL1:
230 case MISCREG_APIBKeyLo_EL1:
231 trap_to_hyp = el==EL1 && hcr.apk == 0;
232 break;
233 // @todo: Trap implementation-dependent functionality based on
234 // hcr.tidcp
235
236 // ID regs, group 3
237 case MISCREG_ID_PFR0_EL1:
238 case MISCREG_ID_PFR1_EL1:
239 case MISCREG_ID_DFR0_EL1:
240 case MISCREG_ID_AFR0_EL1:
241 case MISCREG_ID_MMFR0_EL1:
242 case MISCREG_ID_MMFR1_EL1:
243 case MISCREG_ID_MMFR2_EL1:
244 case MISCREG_ID_MMFR3_EL1:
245 case MISCREG_ID_ISAR0_EL1:
246 case MISCREG_ID_ISAR1_EL1:
247 case MISCREG_ID_ISAR2_EL1:
248 case MISCREG_ID_ISAR3_EL1:
249 case MISCREG_ID_ISAR4_EL1:
250 case MISCREG_ID_ISAR5_EL1:
251 case MISCREG_MVFR0_EL1:
252 case MISCREG_MVFR1_EL1:
253 case MISCREG_MVFR2_EL1:
254 case MISCREG_ID_AA64PFR0_EL1:
255 case MISCREG_ID_AA64PFR1_EL1:
256 case MISCREG_ID_AA64DFR0_EL1:
257 case MISCREG_ID_AA64DFR1_EL1:
258 case MISCREG_ID_AA64ISAR0_EL1:
259 case MISCREG_ID_AA64ISAR1_EL1:
260 case MISCREG_ID_AA64MMFR0_EL1:
261 case MISCREG_ID_AA64MMFR1_EL1:
262 case MISCREG_ID_AA64MMFR2_EL1:
263 case MISCREG_ID_AA64AFR0_EL1:
264 case MISCREG_ID_AA64AFR1_EL1:
265 assert(miscRead);
266 trap_to_hyp = hcr.tid3 && el == EL1;
267 break;
268 // ID regs, group 2
269 case MISCREG_CTR_EL0:
270 case MISCREG_CCSIDR_EL1:
271 case MISCREG_CLIDR_EL1:
272 case MISCREG_CSSELR_EL1:
273 trap_to_hyp = hcr.tid2 && el <= EL1;
274 break;
275 // ID regs, group 1
276 case MISCREG_AIDR_EL1:
277 case MISCREG_REVIDR_EL1:
278 assert(miscRead);
279 trap_to_hyp = hcr.tid1 && el == EL1;
280 break;
281 case MISCREG_IMPDEF_UNIMPL:
282 trap_to_hyp = hcr.tidcp && el == EL1;
283 break;
284 // GICv3 regs
285 case MISCREG_ICC_SGI0R_EL1:
286 {
287 auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
288 if (isa->haveGICv3CpuIfc())
289 trap_to_hyp = hcr.fmo && el == EL1;
290 }
291 break;
292 case MISCREG_ICC_SGI1R_EL1:
293 case MISCREG_ICC_ASGI1R_EL1:
294 {
295 auto *isa = static_cast<ArmISA::ISA *>(tc->getIsaPtr());
296 if (isa->haveGICv3CpuIfc())
297 trap_to_hyp = hcr.imo && el == EL1;
298 }
299 break;
300 // Generic Timer
301 case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
302 trap_to_hyp = el <= EL1 &&
303 isGenericTimerSystemAccessTrapEL2(misc_reg, tc);
304 break;
305 default:
306 break;
307 }
308 }
309 return trap_to_hyp;
310 }
311
312 bool
313 MiscRegOp64::checkEL3Trap(ThreadContext *tc, const MiscRegIndex misc_reg,
314 ExceptionLevel el, ExceptionClass &ec,
315 uint32_t &immediate) const
316 {
317 const CPTR cptr = tc->readMiscReg(MISCREG_CPTR_EL3);
318 const SCR scr = tc->readMiscReg(MISCREG_SCR_EL3);
319 bool trap_to_mon = false;
320
321 switch (misc_reg) {
322 // FP/SIMD regs
323 case MISCREG_FPCR:
324 case MISCREG_FPSR:
325 case MISCREG_FPEXC32_EL2:
326 trap_to_mon = cptr.tfp;
327 ec = EC_TRAPPED_SIMD_FP;
328 immediate = 0x1E00000;
329 break;
330 // CPACR, CPTR
331 case MISCREG_CPACR_EL1:
332 if (el == EL1 || el == EL2) {
333 trap_to_mon = cptr.tcpac;
334 }
335 break;
336 case MISCREG_CPTR_EL2:
337 if (el == EL2) {
338 trap_to_mon = cptr.tcpac;
339 }
340 break;
341 case MISCREG_APDAKeyHi_EL1:
342 case MISCREG_APDAKeyLo_EL1:
343 case MISCREG_APDBKeyHi_EL1:
344 case MISCREG_APDBKeyLo_EL1:
345 case MISCREG_APGAKeyHi_EL1:
346 case MISCREG_APGAKeyLo_EL1:
347 case MISCREG_APIAKeyHi_EL1:
348 case MISCREG_APIAKeyLo_EL1:
349 case MISCREG_APIBKeyHi_EL1:
350 case MISCREG_APIBKeyLo_EL1:
351 trap_to_mon = (el==EL1 || el==EL2) && scr.apk==0 && ELIs64(tc, EL3);
352 break;
353 // Generic Timer
354 case MISCREG_CNTFRQ_EL0 ... MISCREG_CNTVOFF_EL2:
355 trap_to_mon = el == EL1 &&
356 isGenericTimerSystemAccessTrapEL3(misc_reg, tc);
357 break;
358 default:
359 break;
360 }
361 return trap_to_mon;
362 }
363
364 RegVal
365 MiscRegImmOp64::miscRegImm() const
366 {
367 if (dest == MISCREG_SPSEL) {
368 return imm & 0x1;
369 } else if (dest == MISCREG_PAN) {
370 return (imm & 0x1) << 22;
371 } else {
372 panic("Not a valid PSTATE field register\n");
373 }
374 }
375
376 std::string
377 MiscRegImmOp64::generateDisassembly(Addr pc, const SymbolTable *symtab) const
378 {
379 std::stringstream ss;
380 printMnemonic(ss);
381 printMiscReg(ss, dest);
382 ss << ", ";
383 ccprintf(ss, "#0x%x", imm);
384 return ss.str();
385 }
386
387 std::string
388 MiscRegRegImmOp64::generateDisassembly(
389 Addr pc, const SymbolTable *symtab) const
390 {
391 std::stringstream ss;
392 printMnemonic(ss);
393 printMiscReg(ss, dest);
394 ss << ", ";
395 printIntReg(ss, op1);
396 return ss.str();
397 }
398
399 std::string
400 RegMiscRegImmOp64::generateDisassembly(
401 Addr pc, const SymbolTable *symtab) const
402 {
403 std::stringstream ss;
404 printMnemonic(ss);
405 printIntReg(ss, dest);
406 ss << ", ";
407 printMiscReg(ss, op1);
408 return ss.str();
409 }
410
411 Fault
412 MiscRegImplDefined64::execute(ExecContext *xc,
413 Trace::InstRecord *traceData) const
414 {
415 auto tc = xc->tcBase();
416 const CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
417 const ExceptionLevel el = (ExceptionLevel) (uint8_t) cpsr.el;
418
419 Fault fault = trap(tc, miscReg, el, imm);
420
421 if (fault != NoFault) {
422 return fault;
423
424 } else if (warning) {
425 warn_once("\tinstruction '%s' unimplemented\n", fullMnemonic.c_str());
426 return NoFault;
427
428 } else {
429 return std::make_shared<UndefinedInstruction>(machInst, false,
430 mnemonic);
431 }
432 }
433
434 std::string
435 MiscRegImplDefined64::generateDisassembly(Addr pc,
436 const SymbolTable *symtab) const
437 {
438 return csprintf("%-10s (implementation defined)", fullMnemonic.c_str());
439 }