arch-arm: Implementing SecureEL2 feature for Armv8
[gem5.git] / src / arch / arm / self_debug.hh
1 /*
2 * Copyright (c) 2019 Metempsy Technology LSC
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 #ifndef __ARCH_ARM_SELF_DEBUG_HH__
39 #define __ARCH_ARM_SELF_DEBUG_HH__
40
41
42 #include "arch/arm/faults.hh"
43 #include "arch/arm/miscregs.hh"
44 #include "arch/arm/system.hh"
45 #include "arch/arm/types.hh"
46 #include "arch/arm/utility.hh"
47 #include "arch/generic/tlb.hh"
48 #include "cpu/thread_context.hh"
49
50 class ThreadContext;
51
52 namespace ArmISA
53 {
54
55 class SelfDebug;
56
57 class BrkPoint
58 {
59 private:
60 MiscRegIndex ctrlRegIndex;
61 MiscRegIndex valRegIndex;
62 SelfDebug * conf;
63 bool isCntxtAware;
64 bool VMID16enabled;
65 Addr activePc;
66 bool enable;
67 int maxAddrSize;
68 bool onUse;
69
70 public:
71 friend class SelfDebug;
72
73 BrkPoint(MiscRegIndex ctrl_index, MiscRegIndex val_index,
74 SelfDebug* _conf, bool ctx_aw, bool lva,
75 bool vmid16, bool aarch32):
76 ctrlRegIndex(ctrl_index), valRegIndex(val_index),
77 conf(_conf), isCntxtAware(ctx_aw),
78 VMID16enabled(vmid16), activePc(0x0), enable(false)
79 {
80 maxAddrSize = lva ? 52: 48 ;
81 maxAddrSize = aarch32 ? 31 : maxAddrSize;
82 onUse = false;
83 }
84
85 bool testLinkedBk(ThreadContext *tc, Addr vaddr, ExceptionLevel el);
86 bool test(ThreadContext *tc, Addr pc, ExceptionLevel el, DBGBCR ctr,
87 bool from_link);
88
89 protected:
90 inline Addr
91 getAddrfromReg(ThreadContext *tc) const
92 {
93 return bits(tc->readMiscReg(valRegIndex), maxAddrSize, 2);
94 }
95
96 inline RegVal
97 getContextfromReg(ThreadContext *tc, bool ctxid1) const
98 {
99 if (ctxid1)
100 return bits(tc->readMiscReg(valRegIndex), 31, 0);
101 else
102 return bits(tc->readMiscReg(valRegIndex), 63, 32);
103 }
104
105
106 inline uint32_t getVMIDfromReg(ThreadContext *tc);
107
108 public:
109 bool testAddrMatch(ThreadContext *tc, Addr pc, uint8_t bas);
110 bool testAddrMissMatch(ThreadContext *tc, Addr pc, uint8_t bas);
111 bool testContextMatch(ThreadContext *tc, bool ctx1, bool low_ctx);
112 bool testContextMatch(ThreadContext *tc, bool ctx1);
113 bool testVMIDMatch(ThreadContext *tc);
114
115 const DBGBCR
116 getControlReg(ThreadContext *tc)
117 {
118 return tc->readMiscReg(ctrlRegIndex);
119 }
120
121 bool isEnabled(ThreadContext* tc, ExceptionLevel el,
122 uint8_t hmc, uint8_t ssc, uint8_t pmc);
123
124 bool
125 isActive(Addr vaddr)
126 {
127 if (vaddr == activePc) {
128 activePc = 0x0;
129 return false;
130 } else {
131 activePc = vaddr;
132 return true;
133 }
134 }
135
136 inline void
137 updateControl(DBGBCR val)
138 {
139 enable = val.e == 0x1;
140 }
141 };
142
143 class WatchPoint
144 {
145 private:
146 MiscRegIndex ctrlRegIndex;
147 MiscRegIndex valRegIndex;
148 SelfDebug * conf;
149 bool enable;
150 int maxAddrSize;
151
152 public:
153 friend class SelfDebug;
154
155 WatchPoint(MiscRegIndex ctrl_index, MiscRegIndex val_index,
156 SelfDebug* _conf, bool lva, bool aarch32) :
157 ctrlRegIndex(ctrl_index),
158 valRegIndex(val_index), conf(_conf), enable(false)
159 {
160 maxAddrSize = lva ? 52: 48 ;
161 maxAddrSize = aarch32 ? 31 : maxAddrSize;
162 }
163
164 bool compareAddress(ThreadContext *tc, Addr in_addr,
165 uint8_t bas, uint8_t mask, unsigned size);
166
167 inline Addr
168 getAddrfromReg(ThreadContext *tc)
169 {
170 return bits(tc->readMiscReg(valRegIndex), maxAddrSize, 0);
171
172 }
173
174 inline bool
175 isDoubleAligned(Addr addr)
176 {
177 return addr & 0x4;
178 }
179
180 inline void
181 updateControl(DBGWCR val)
182 {
183 enable = val.e == 0x1;
184 }
185
186 bool isEnabled(ThreadContext* tc, ExceptionLevel el, bool hmc,
187 uint8_t ssc, uint8_t pac);
188 bool test(ThreadContext *tc, Addr addr, ExceptionLevel el, bool& wrt,
189 bool atomic, unsigned size);
190 };
191
192 class SoftwareStep
193 {
194 private:
195 static const uint8_t INACTIVE_STATE = 0;
196 static const uint8_t ACTIVE_PENDING_STATE = 1;
197 static const uint8_t ACTIVE_NOT_PENDING_STATE = 2;
198
199 bool bSS;
200 int stateSS;
201 SelfDebug *conf;
202 bool steppedLdx;
203 bool prevSteppedLdx;
204 bool cpsrD;
205
206 public:
207 SoftwareStep(SelfDebug *s)
208 : bSS(false), stateSS(INACTIVE_STATE),
209 conf(s), steppedLdx(false)
210 {}
211
212 bool debugExceptionReturnSS(ThreadContext *tc, CPSR spsr,
213 ExceptionLevel dest, bool aarch32);
214 bool advanceSS(ThreadContext *tc);
215
216 inline void
217 setCPSRD(bool val)
218 {
219 cpsrD = val;
220 }
221
222 inline void
223 setEnableSS(bool val)
224 {
225 bSS = val;
226 }
227
228 void
229 setLdx()
230 {
231 prevSteppedLdx = steppedLdx;
232 steppedLdx = true;
233 }
234
235 void
236 clearLdx()
237 {
238 prevSteppedLdx = steppedLdx;
239 steppedLdx = false;
240 }
241
242 bool
243 getLdx() const
244 {
245 return prevSteppedLdx;
246 }
247 };
248
249 class VectorCatch
250 {
251 private:
252 bool vcmatch;
253 SelfDebug *conf;
254 std::vector<Fault *> vectorTypes();
255
256 public:
257 VectorCatch(bool _vcmatch, SelfDebug* s) : vcmatch(_vcmatch), conf(s)
258 {}
259
260 bool addressMatching(ThreadContext *tc, Addr addr, ExceptionLevel el);
261 bool exceptionTrapping(ThreadContext *tc, ExceptionLevel el,
262 ArmFault* fault);
263
264 bool isVCMatch() const { return vcmatch; }
265
266 private:
267 Addr
268 getVectorBase(ThreadContext *tc, bool monitor)
269 {
270 if (monitor) {
271 return tc->readMiscReg(MISCREG_MVBAR) & ~0x1F;
272 }
273 SCTLR sctlr = tc->readMiscReg(MISCREG_SCTLR_EL1);
274 if (sctlr.v) {
275 return (Addr) 0xFFFF0000;
276 } else {
277 Addr vbar = tc->readMiscReg(MISCREG_VBAR) & ~0x1F;
278 return vbar;
279 }
280 }
281
282 };
283
284 class SelfDebug
285 {
286 private:
287 std::vector<BrkPoint> arBrkPoints;
288 std::vector<WatchPoint> arWatchPoints;
289 SoftwareStep * softStep;
290 VectorCatch * vcExcpt;
291
292 bool initialized;
293 bool enableTdeTge; // MDCR_EL2.TDE || HCR_EL2.TGE
294
295 // THIS is MDSCR_EL1.MDE in aarch64 and DBGDSCRext.MDBGen in aarch32
296 bool enableFlag;
297
298 bool bSDD; // MDCR_EL3.SDD
299 bool bKDE; // MDSCR_EL1.KDE
300 bool oslk; // OS lock flag
301
302 bool aarch32; // updates with stage1 aarch64/32
303 bool to32;
304
305 public:
306 SelfDebug()
307 : initialized(false), enableTdeTge(false),
308 enableFlag(false), bSDD(false), bKDE(false), oslk(false)
309 {
310 softStep = new SoftwareStep(this);
311 }
312
313 ~SelfDebug()
314 {
315 delete softStep;
316 delete vcExcpt;
317 }
318
319 Fault testDebug(ThreadContext *tc, const RequestPtr &req,
320 BaseTLB::Mode mode);
321
322 protected:
323 Fault testBreakPoints(ThreadContext *tc, Addr vaddr);
324 Fault testWatchPoints(ThreadContext *tc, Addr vaddr, bool write,
325 bool atomic, unsigned size, bool cm);
326
327 Fault triggerException(ThreadContext * tc, Addr vaddr);
328 Fault triggerWatchpointException(ThreadContext *tc, Addr vaddr,
329 bool write, bool cm);
330 public:
331 Fault testVectorCatch(ThreadContext *tc, Addr addr, ArmFault* flt);
332
333 inline BrkPoint*
334 getBrkPoint(uint8_t index)
335 {
336 return &arBrkPoints[index];
337 }
338
339 static inline bool
340 securityStateMatch(ThreadContext *tc, uint8_t ssc, bool hmc)
341 {
342 switch (ssc) {
343 case 0x0: return true;
344 case 0x1: return !isSecure(tc);
345 case 0x2: return isSecure(tc);
346 case 0x3:
347 {
348 bool b = hmc? true: isSecure(tc);
349 return b;
350 }
351 default: panic("Unreachable value");
352 }
353 return false;
354 }
355
356 bool isDebugEnabledForEL64(ThreadContext *tc, ExceptionLevel el,
357 bool secure, bool mask);
358 bool isDebugEnabledForEL32(ThreadContext *tc, ExceptionLevel el,
359 bool secure, bool mask);
360
361 void
362 activateDebug()
363 {
364 for (auto &p: arBrkPoints){
365 p.onUse = false;
366 }
367 }
368
369 inline bool
370 isDebugEnabled(ThreadContext *tc)
371 {
372 CPSR cpsr = tc->readMiscReg(MISCREG_CPSR);
373 ExceptionLevel el = (ExceptionLevel) currEL(tc);
374 if (aarch32) {
375 return isDebugEnabledForEL32(tc, el, isSecure(tc),
376 (bool)cpsr.d == 1);
377 } else {
378 return isDebugEnabledForEL64(tc, el, isSecure(tc),
379 (bool)cpsr.d == 1 );
380 }
381 }
382
383 inline void
384 setbSDD(RegVal val)
385 {
386 bSDD = bits(val, 16);
387 }
388
389 inline void
390 setMDSCRvals(RegVal val)
391 {
392 enableFlag = bits(val, 15);
393 bKDE = bits(val, 13);
394 softStep->setEnableSS((bool)bits(val, 0));
395 }
396
397 inline void
398 setMDBGen(RegVal val)
399 {
400 enableFlag = bits(val, 15);
401 }
402
403 inline void
404 setenableTDETGE(HCR hcr, HDCR mdcr)
405 {
406 enableTdeTge = (mdcr.tde == 0x1 || hcr.tge == 0x1);
407 }
408
409 inline void
410 updateOSLock(RegVal val)
411 {
412 oslk = bool(bits(val, 0));
413 }
414
415 inline void
416 updateDBGBCR(int index, DBGBCR val)
417 {
418 arBrkPoints[index].updateControl(val);
419 }
420
421 inline void
422 updateDBGWCR(int index, DBGWCR val)
423 {
424 arWatchPoints[index].updateControl(val);
425 }
426
427 inline void
428 setDebugMask(bool mask)
429 {
430 softStep->setCPSRD(mask);
431 }
432
433 inline bool
434 isAArch32() const
435 {
436 return aarch32;
437 }
438
439 inline void
440 setAArch32(ThreadContext *tc)
441 {
442 ExceptionLevel from_el = (ExceptionLevel) currEL(tc);
443 if (from_el == EL0)
444 aarch32 = ELIs32(tc, EL0) && ELIs32(tc, EL1);
445 else
446 aarch32 = ELIs32(tc, from_el);
447 return;
448 }
449
450 SoftwareStep *
451 getSstep()
452 {
453 return softStep;
454 }
455
456 VectorCatch*
457 getVectorCatch(ThreadContext *tc)
458 {
459 if (!initialized)
460 init(tc);
461 return vcExcpt;
462 }
463
464 bool
465 targetAArch32(ThreadContext *tc)
466 {
467 ExceptionLevel ELd = debugTargetFrom(tc, isSecure(tc));
468 return ELIs32(tc, ELd) && aarch32;
469 }
470
471 void init(ThreadContext *tc);
472 };
473
474 }
475 #endif