gic_v3_cpu_interface.cc revision 13740:7bb2759e56ed
1/*
2 * Copyright (c) 2018 Metempsy Technology Consulting
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met: redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer;
9 * redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution;
12 * neither the name of the copyright holders nor the names of its
13 * contributors may be used to endorse or promote products derived from
14 * this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 *
28 * Authors: Jairo Balart
29 */
30
31#include "dev/arm/gic_v3_cpu_interface.hh"
32
33#include "arch/arm/isa.hh"
34#include "debug/GIC.hh"
35#include "dev/arm/gic_v3.hh"
36#include "dev/arm/gic_v3_distributor.hh"
37#include "dev/arm/gic_v3_redistributor.hh"
38
39Gicv3CPUInterface::Gicv3CPUInterface(Gicv3 * gic, uint32_t cpu_id)
40    : BaseISADevice(),
41      gic(gic),
42      redistributor(nullptr),
43      distributor(nullptr),
44      cpuId(cpu_id)
45{
46}
47
48Gicv3CPUInterface::~Gicv3CPUInterface()
49{
50}
51
52void
53Gicv3CPUInterface::init()
54{
55    redistributor = gic->getRedistributor(cpuId);
56    distributor = gic->getDistributor();
57}
58
59void
60Gicv3CPUInterface::initState()
61{
62    reset();
63}
64
65void
66Gicv3CPUInterface::reset()
67{
68    hppi.prio = 0xff;
69}
70
71bool
72Gicv3CPUInterface::getHCREL2FMO()
73{
74    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
75
76    if (hcr.tge && hcr.e2h) {
77        return false;
78    } else if (hcr.tge) {
79        return true;
80    } else {
81        return hcr.fmo;
82    }
83}
84
85bool
86Gicv3CPUInterface::getHCREL2IMO()
87{
88    HCR hcr = isa->readMiscRegNoEffect(MISCREG_HCR_EL2);
89
90    if (hcr.tge && hcr.e2h) {
91        return false;
92    } else if (hcr.tge) {
93        return true;
94    } else {
95        return hcr.imo;
96    }
97}
98
99RegVal
100Gicv3CPUInterface::readMiscReg(int misc_reg)
101{
102    RegVal value = isa->readMiscRegNoEffect(misc_reg);
103    bool hcr_fmo = getHCREL2FMO();
104    bool hcr_imo = getHCREL2IMO();
105
106    switch (misc_reg) {
107      case MISCREG_ICC_AP1R0:
108      case MISCREG_ICC_AP1R0_EL1: {
109          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
110              return isa->readMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1);
111          }
112
113          break;
114      }
115
116      case MISCREG_ICC_AP1R1:
117      case MISCREG_ICC_AP1R1_EL1:
118
119        // only implemented if supporting 6 or more bits of priority
120      case MISCREG_ICC_AP1R2:
121      case MISCREG_ICC_AP1R2_EL1:
122
123        // only implemented if supporting 7 or more bits of priority
124      case MISCREG_ICC_AP1R3:
125      case MISCREG_ICC_AP1R3_EL1:
126        // only implemented if supporting 7 or more bits of priority
127        return 0;
128
129      case MISCREG_ICC_AP0R0:
130      case MISCREG_ICC_AP0R0_EL1: {
131          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
132              return isa->readMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1);
133          }
134
135          break;
136      }
137
138      case MISCREG_ICC_AP0R1:
139      case MISCREG_ICC_AP0R1_EL1:
140
141        // only implemented if supporting 6 or more bits of priority
142      case MISCREG_ICC_AP0R2:
143      case MISCREG_ICC_AP0R2_EL1:
144
145        // only implemented if supporting 7 or more bits of priority
146      case MISCREG_ICC_AP0R3:
147      case MISCREG_ICC_AP0R3_EL1:
148        // only implemented if supporting 7 or more bits of priority
149        return 0;
150
151      case MISCREG_ICC_IGRPEN0:
152      case MISCREG_ICC_IGRPEN0_EL1: {
153          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
154              return readMiscReg(MISCREG_ICV_IGRPEN0_EL1);
155          }
156
157          break;
158      }
159
160      case MISCREG_ICV_IGRPEN0_EL1: {
161          RegVal ich_vmcr_el2 =
162              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
163          value = bits(ich_vmcr_el2, ICH_VMCR_EL2_VENG0_SHIFT);
164          break;
165      }
166
167      case MISCREG_ICC_IGRPEN1:
168      case MISCREG_ICC_IGRPEN1_EL1: {
169          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
170              return readMiscReg(MISCREG_ICV_IGRPEN1_EL1);
171          }
172
173          break;
174      }
175
176      case MISCREG_ICV_IGRPEN1_EL1: {
177          RegVal ich_vmcr_el2 =
178              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
179          value = bits(ich_vmcr_el2, ICH_VMCR_EL2_VENG1_SHIFT);
180          break;
181      }
182
183      case MISCREG_ICC_MGRPEN1:
184      case MISCREG_ICC_IGRPEN1_EL3: {
185          // EnableGrp1S and EnableGrp1NS are aliased with
186          // ICC_IGRPEN1_EL1_S.Enable and ICC_IGRPEN1_EL1_NS.Enable
187          bool enable_grp_1s =
188              isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) &
189              ICC_IGRPEN1_EL1_ENABLE;
190          bool enable_grp_1ns =
191              isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) &
192              ICC_IGRPEN1_EL1_ENABLE;
193          value = 0;
194
195          if (enable_grp_1s) {
196              value |= ICC_IGRPEN1_EL3_ENABLEGRP1S;
197          }
198
199          if (enable_grp_1ns) {
200              value |= ICC_IGRPEN1_EL3_ENABLEGRP1NS;
201          }
202
203          break;
204      }
205
206      case MISCREG_ICC_RPR:
207      case MISCREG_ICC_RPR_EL1: {
208          if ((currEL() == EL1) && !inSecureState() &&
209                  (hcr_imo || hcr_fmo)) {
210              return readMiscReg(MISCREG_ICV_RPR_EL1);
211          }
212
213          uint8_t rprio = highestActivePriority();
214
215          if (haveEL(EL3) && !inSecureState() &&
216                  (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
217              /* NS GIC access and Group 0 is inaccessible to NS */
218              if ((rprio & 0x80) == 0) {
219                  /* NS should not see priorities in the Secure half of the
220                   * range */
221                  rprio = 0;
222              } else if (rprio != 0xff) {
223                  /* Non-idle priority: show the Non-secure view of it */
224                  rprio = (rprio << 1) & 0xff;
225              }
226          }
227
228          value = rprio;
229          break;
230      }
231
232      case MISCREG_ICV_RPR_EL1: {
233          value = virtualHighestActivePriority();
234          break;
235      }
236
237      case MISCREG_ICC_HPPIR0:
238      case MISCREG_ICC_HPPIR0_EL1: {
239          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
240              return readMiscReg(MISCREG_ICV_HPPIR0_EL1);
241          }
242
243          value = getHPPIR0();
244          break;
245      }
246
247      case MISCREG_ICV_HPPIR0_EL1: {
248          value = Gicv3::INTID_SPURIOUS;
249          int lr_idx = getHPPVILR();
250
251          if (lr_idx >= 0) {
252              RegVal lr =
253                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
254              Gicv3::GroupId group =
255                  lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
256
257              if (group == Gicv3::G0S) {
258                  value = bits(lr, 31, 0);
259              }
260          }
261
262          break;
263      }
264
265      case MISCREG_ICC_HPPIR1:
266      case MISCREG_ICC_HPPIR1_EL1: {
267          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
268              return readMiscReg(MISCREG_ICV_HPPIR1_EL1);
269          }
270
271          value = getHPPIR1();
272          break;
273      }
274
275      case MISCREG_ICV_HPPIR1_EL1: {
276          value = Gicv3::INTID_SPURIOUS;
277          int lr_idx = getHPPVILR();
278
279          if (lr_idx >= 0) {
280              RegVal lr =
281                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
282              Gicv3::GroupId group =
283                  lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
284
285              if (group == Gicv3::G1NS) {
286                  value = bits(lr, 31, 0);
287              }
288          }
289
290          break;
291      }
292
293      case MISCREG_ICC_BPR0:
294      case MISCREG_ICC_BPR0_EL1:
295        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
296            return readMiscReg(MISCREG_ICV_BPR0_EL1);
297        }
298
299        M5_FALLTHROUGH;
300
301      case MISCREG_ICC_BPR1:
302      case MISCREG_ICC_BPR1_EL1:
303        if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
304            return readMiscReg(MISCREG_ICV_BPR1_EL1);
305        }
306
307        {
308            Gicv3::GroupId group =
309                misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S;
310
311            if (group == Gicv3::G1S && !inSecureState()) {
312                group = Gicv3::G1NS;
313            }
314
315            if ((group == Gicv3::G1S) &&
316                    !isEL3OrMon() &&
317                    (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S)
318                     & ICC_CTLR_EL1_CBPR)) {
319                group = Gicv3::G0S;
320            }
321
322            bool sat_inc = false;
323
324            if ((group == Gicv3::G1NS) &&
325                    (currEL() < EL3) &&
326                    (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS)
327                     & ICC_CTLR_EL1_CBPR)) {
328                // Reads return BPR0 + 1 saturated to 7, WI
329                group = Gicv3::G0S;
330                sat_inc = true;
331            }
332
333            uint8_t bpr;
334
335            if (group == Gicv3::G0S) {
336                bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1);
337            } else {
338                bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1);
339            }
340
341            if (sat_inc) {
342                bpr++;
343
344                if (bpr > 7) {
345                    bpr = 7;
346                }
347            }
348
349            value = bpr;
350            break;
351        }
352
353      case MISCREG_ICV_BPR0_EL1:
354      case MISCREG_ICV_BPR1_EL1: {
355          Gicv3::GroupId group =
356              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
357          RegVal ich_vmcr_el2 =
358              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
359          bool sat_inc = false;
360
361          if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) {
362              // reads return bpr0 + 1 saturated to 7, writes ignored
363              group = Gicv3::G0S;
364              sat_inc = true;
365          }
366
367          uint8_t vbpr;
368
369          if (group == Gicv3::G0S) {
370              vbpr = bits(ich_vmcr_el2, 23, 21);
371          } else {
372              vbpr = bits(ich_vmcr_el2, 20, 18);
373          }
374
375          if (sat_inc) {
376              vbpr++;
377
378              if (vbpr > 7) {
379                  vbpr = 7;
380              }
381          }
382
383          value = vbpr;
384          break;
385      }
386
387      case MISCREG_ICC_PMR:
388      case MISCREG_ICC_PMR_EL1: // Priority Mask Register
389        if ((currEL() == EL1) && !inSecureState() &&
390                (hcr_imo || hcr_fmo)) {
391            return readMiscReg(MISCREG_ICV_PMR_EL1);
392        }
393
394        if (haveEL(EL3) && !inSecureState() &&
395                (isa->readMiscRegNoEffect(MISCREG_SCR_EL3) & (1U << 2))) {
396            /* NS GIC access and Group 0 is inaccessible to NS */
397            if ((value & 0x80) == 0) {
398                /* NS should not see priorities in the Secure half of the
399                 * range */
400                value = 0;
401            } else if (value != 0xff) {
402                /* Non-idle priority: show the Non-secure view of it */
403                value = (value << 1) & 0xff;
404            }
405        }
406
407        break;
408
409      case MISCREG_ICV_PMR_EL1: { // Priority Mask Register
410          RegVal ich_vmcr_el2 =
411              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
412
413          value = ich_vmcr_el2 >> ICH_VMCR_EL2_VPMR_SHIFT;
414          break;
415      }
416
417      case MISCREG_ICC_IAR0:
418      case MISCREG_ICC_IAR0_EL1: { // Interrupt Acknowledge Register 0
419          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
420              return readMiscReg(MISCREG_ICV_IAR0_EL1);
421          }
422
423          uint32_t int_id;
424
425          if (hppiCanPreempt()) {
426              int_id = getHPPIR0();
427
428              // avoid activation for special interrupts
429              if (int_id < Gicv3::INTID_SECURE) {
430                  activateIRQ(int_id, hppi.group);
431              }
432          } else {
433              int_id = Gicv3::INTID_SPURIOUS;
434          }
435
436          value = int_id;
437          break;
438      }
439
440      case MISCREG_ICV_IAR0_EL1: {
441          int lr_idx = getHPPVILR();
442          uint32_t int_id = Gicv3::INTID_SPURIOUS;
443
444          if (lr_idx >= 0) {
445              RegVal lr =
446                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
447
448              if (!(lr & ICH_LR_EL2_GROUP) && hppviCanPreempt(lr_idx)) {
449                  int_id = value = bits(lr, 31, 0);
450
451                  if (int_id < Gicv3::INTID_SECURE ||
452                          int_id > Gicv3::INTID_SPURIOUS) {
453                      virtualActivateIRQ(lr_idx);
454                  } else {
455                      // Bogus... Pseudocode says:
456                      // - Move from pending to invalid...
457                      // - Return de bogus id...
458                      lr &= ~ICH_LR_EL2_STATE_PENDING_BIT;
459                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
460                              lr);
461                  }
462              }
463          }
464
465          value = int_id;
466          virtualUpdate();
467          break;
468      }
469
470      case MISCREG_ICC_IAR1:
471      case MISCREG_ICC_IAR1_EL1: { // Interrupt Acknowledge Register 1
472          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
473              return readMiscReg(MISCREG_ICV_IAR1_EL1);
474          }
475
476          uint32_t int_id;
477
478          if (hppiCanPreempt()) {
479              int_id = getHPPIR1();
480
481              // avoid activation for special interrupts
482              if (int_id < Gicv3::INTID_SECURE) {
483                  activateIRQ(int_id, hppi.group);
484              }
485
486              // LPIs are not activated and when acked their pending
487              // bit is cleared
488              if (int_id >= Gicv3Redistributor::SMALLEST_LPI_ID)
489              {
490                  redistributor->setClrLPI(int_id, false);
491              }
492
493          } else {
494              int_id = Gicv3::INTID_SPURIOUS;
495          }
496
497          value = int_id;
498          break;
499      }
500
501      case MISCREG_ICV_IAR1_EL1: {
502          int lr_idx = getHPPVILR();
503          uint32_t int_id = Gicv3::INTID_SPURIOUS;
504
505          if (lr_idx >= 0) {
506              RegVal lr =
507                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
508
509              if (lr & ICH_LR_EL2_GROUP && hppviCanPreempt(lr_idx)) {
510                  int_id = value = bits(lr, 31, 0);
511
512                  if (int_id < Gicv3::INTID_SECURE ||
513                          int_id > Gicv3::INTID_SPURIOUS) {
514                      virtualActivateIRQ(lr_idx);
515                  } else {
516                      // Bogus... Pseudocode says:
517                      // - Move from pending to invalid...
518                      // - Return de bogus id...
519                      lr &= ~ICH_LR_EL2_STATE_PENDING_BIT;
520                      isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx,
521                              lr);
522                  }
523              }
524          }
525
526          value = int_id;
527          virtualUpdate();
528          break;
529      }
530
531      case MISCREG_ICC_SRE:
532      case MISCREG_ICC_SRE_EL1: { // System Register Enable Register
533          bool dfb;
534          bool dib;
535
536          if (haveEL(EL3) && !distributor->DS) {
537              // DIB is RO alias of ICC_SRE_EL3.DIB
538              // DFB is RO alias of ICC_SRE_EL3.DFB
539              RegVal icc_sre_el3 =
540                  isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3);
541              dfb = icc_sre_el3 & ICC_SRE_EL3_DFB;
542              dib = icc_sre_el3 & ICC_SRE_EL3_DIB;
543          } else if (haveEL(EL3) && distributor->DS) {
544              // DIB is RW alias of ICC_SRE_EL3.DIB
545              // DFB is RW alias of ICC_SRE_EL3.DFB
546              RegVal icc_sre_el3 =
547                  isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3);
548              dfb = icc_sre_el3 & ICC_SRE_EL3_DFB;
549              dib = icc_sre_el3 & ICC_SRE_EL3_DIB;
550          } else if ((!haveEL(EL3) || distributor->DS) and haveEL(EL2)) {
551              // DIB is RO alias of ICC_SRE_EL2.DIB
552              // DFB is RO alias of ICC_SRE_EL2.DFB
553              RegVal icc_sre_el2 =
554                  isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL2);
555              dfb = icc_sre_el2 & ICC_SRE_EL2_DFB;
556              dib = icc_sre_el2 & ICC_SRE_EL2_DIB;
557          } else {
558              dfb = value & ICC_SRE_EL1_DFB;
559              dib = value & ICC_SRE_EL1_DIB;
560          }
561
562          value = ICC_SRE_EL1_SRE;
563
564          if (dfb) {
565              value |= ICC_SRE_EL1_DFB;
566          }
567
568          if (dib) {
569              value |= ICC_SRE_EL1_DIB;
570          }
571
572          break;
573      }
574
575      case MISCREG_ICC_HSRE:
576      case MISCREG_ICC_SRE_EL2: // System Register Enable Register
577        /*
578         * Enable [3] == 1
579         * (Secure EL1 accesses to Secure ICC_SRE_EL1 do not trap to EL2,
580         * RAO/WI)
581         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
582         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
583         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
584         */
585        value = ICC_SRE_EL2_ENABLE | ICC_SRE_EL2_DIB | ICC_SRE_EL2_DFB |
586            ICC_SRE_EL2_SRE;
587        break;
588
589      case MISCREG_ICC_MSRE:
590      case MISCREG_ICC_SRE_EL3: // System Register Enable Register
591        /*
592         * Enable [3] == 1
593         * (Secure EL1 accesses to Secure ICC_SRE_EL1 do not trap to EL3,
594         * RAO/WI)
595         * DIB [2] == 1 (IRQ bypass not supported, RAO/WI)
596         * DFB [1] == 1 (FIQ bypass not supported, RAO/WI)
597         * SRE [0] == 1 (Only system register interface supported, RAO/WI)
598         */
599        value = ICC_SRE_EL3_ENABLE | ICC_SRE_EL3_DIB | ICC_SRE_EL3_DFB |
600            ICC_SRE_EL3_SRE;
601        break;
602
603      case MISCREG_ICC_CTLR:
604      case MISCREG_ICC_CTLR_EL1: { // Control Register
605          if ((currEL() == EL1) && !inSecureState() &&
606                  (hcr_imo || hcr_fmo)) {
607              return readMiscReg(MISCREG_ICV_CTLR_EL1);
608          }
609
610          // Add value for RO bits
611          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
612          // PRIbits [10:8], number of priority bits implemented, minus one
613          value |= ICC_CTLR_EL1_RSS | ICC_CTLR_EL1_A3V |
614              (1 << 11) | ((PRIORITY_BITS - 1) << 8);
615          break;
616      }
617
618      case MISCREG_ICV_CTLR_EL1: {
619          value = ICC_CTLR_EL1_A3V | (1 << ICC_CTLR_EL1_IDBITS_SHIFT) |
620              (7 << ICC_CTLR_EL1_PRIBITS_SHIFT);
621          RegVal ich_vmcr_el2 =
622              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
623
624          if (ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM) {
625              value |= ICC_CTLR_EL1_EOIMODE;
626          }
627
628          if (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR) {
629              value |= ICC_CTLR_EL1_CBPR;
630          }
631
632          break;
633      }
634
635      case MISCREG_ICC_MCTLR:
636      case MISCREG_ICC_CTLR_EL3: {
637          // Add value for RO bits
638          // RSS [18]
639          // A3V [15]
640          // IDbits [13:11], 001 = 24 bits | 000 = 16 bits
641          // PRIbits [10:8], number of priority bits implemented, minus one
642          value |= ICC_CTLR_EL3_RSS | ICC_CTLR_EL3_A3V | (0 << 11) |
643              ((PRIORITY_BITS - 1) << 8);
644          // Aliased bits...
645          RegVal icc_ctlr_el1_ns =
646              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
647          RegVal icc_ctlr_el1_s =
648              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
649
650          if (icc_ctlr_el1_ns & ICC_CTLR_EL1_EOIMODE) {
651              value |= ICC_CTLR_EL3_EOIMODE_EL1NS;
652          }
653
654          if (icc_ctlr_el1_ns & ICC_CTLR_EL1_CBPR) {
655              value |= ICC_CTLR_EL3_CBPR_EL1NS;
656          }
657
658          if (icc_ctlr_el1_s & ICC_CTLR_EL1_EOIMODE) {
659              value |= ICC_CTLR_EL3_EOIMODE_EL1S;
660          }
661
662          if (icc_ctlr_el1_s & ICC_CTLR_EL1_CBPR) {
663              value |= ICC_CTLR_EL3_CBPR_EL1S;
664          }
665
666          break;
667      }
668
669      case MISCREG_ICH_HCR:
670      case MISCREG_ICH_HCR_EL2:
671        break;
672
673      case MISCREG_ICH_AP0R0:
674      case MISCREG_ICH_AP0R0_EL2:
675        break;
676
677      case MISCREG_ICH_AP1R0:
678      case MISCREG_ICH_AP1R0_EL2:
679        break;
680
681      case MISCREG_ICH_MISR:
682      case MISCREG_ICH_MISR_EL2: {
683          value = 0;
684          // Scan list registers and fill in the U, NP and EOI bits
685          eoiMaintenanceInterruptStatus((uint32_t *) &value);
686          RegVal ich_hcr_el2 =
687              isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
688          RegVal ich_vmcr_el2 =
689              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
690
691          if (ich_hcr_el2 &
692                  (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) {
693              value |= ICH_MISR_EL2_LRENP;
694          }
695
696          if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) &&
697                  (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
698              value |= ICH_MISR_EL2_VGRP0E;
699          }
700
701          if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) &&
702                  !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
703              value |= ICH_MISR_EL2_VGRP0D;
704          }
705
706          if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) &&
707                  (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
708              value |= ICH_MISR_EL2_VGRP1E;
709          }
710
711          if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) &&
712                  !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
713              value |= ICH_MISR_EL2_VGRP1D;
714          }
715
716          break;
717      }
718
719      case MISCREG_ICH_VTR:
720      case MISCREG_ICH_VTR_EL2:
721        /*
722         * PRIbits [31:29]
723         * PREbits [28:26]
724         * IDbits [25:23]
725         * SEIS [22] == 0 (SEI Support)
726         * A3V [21] == 1
727         * (Non-zero values supported for Affinity 3 in SGI genearion)
728         * nV4 [20] == 0
729         * (Support for direct injection of virtual interrupts)
730         * TDS [19] == 0 (Implementation supports ICH_HCR_EL2.TDIR)
731         * ListRegs [4:0]
732         */
733        value = (16 - 1) << 0 |
734            (5 - 1) << 26 |
735            (5 - 1) << 29;
736        value =
737            ((VIRTUAL_NUM_LIST_REGS - 1) << ICH_VTR_EL2_LISTREGS_SHIFT) |
738            // ICH_VTR_EL2_TDS |
739            // ICH_VTR_EL2_NV4 |
740            ICH_VTR_EL2_A3V |
741            (1 << ICH_VTR_EL2_IDBITS_SHIFT) |
742            ((VIRTUAL_PREEMPTION_BITS - 1) << ICH_VTR_EL2_PREBITS_SHIFT) |
743            ((VIRTUAL_PRIORITY_BITS - 1) << ICH_VTR_EL2_PRIBITS_SHIFT);
744        break;
745
746      case MISCREG_ICH_EISR:
747      case MISCREG_ICH_EISR_EL2:
748        value = eoiMaintenanceInterruptStatus(nullptr);
749        break;
750
751      case MISCREG_ICH_ELRSR:
752      case MISCREG_ICH_ELRSR_EL2:
753        value = 0;
754
755        for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
756            RegVal lr =
757                isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
758
759            if ((lr & ICH_LR_EL2_STATE_MASK) == 0 &&
760                    ((lr & ICH_LR_EL2_HW) != 0 ||
761                     (lr & ICH_LR_EL2_EOI) == 0)) {
762                value |= (1 << lr_idx);
763            }
764        }
765
766        break;
767
768      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15:
769        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
770        value = value >> 32;
771        break;
772
773      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15:
774        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
775        value = value & 0xffffffff;
776        break;
777
778      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2:
779        break;
780
781      case MISCREG_ICH_VMCR:
782      case MISCREG_ICH_VMCR_EL2:
783        break;
784
785      default:
786        panic("Gicv3CPUInterface::readMiscReg(): "
787                "unknown register %d (%s)",
788                misc_reg, miscRegName[misc_reg]);
789    }
790
791    DPRINTF(GIC, "Gicv3CPUInterface::readMiscReg(): "
792            "register %s value %#x\n", miscRegName[misc_reg], value);
793    return value;
794}
795
796void
797Gicv3CPUInterface::setMiscReg(int misc_reg, RegVal val)
798{
799    bool do_virtual_update = false;
800    DPRINTF(GIC, "Gicv3CPUInterface::setMiscReg(): "
801            "register %s value %#x\n", miscRegName[misc_reg], val);
802    bool hcr_fmo = getHCREL2FMO();
803    bool hcr_imo = getHCREL2IMO();
804
805    switch (misc_reg) {
806      case MISCREG_ICC_AP1R0:
807      case MISCREG_ICC_AP1R0_EL1:
808        if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
809            return isa->setMiscRegNoEffect(MISCREG_ICV_AP1R0_EL1, val);
810        }
811
812        break;
813
814      case MISCREG_ICC_AP1R1:
815      case MISCREG_ICC_AP1R1_EL1:
816
817        // only implemented if supporting 6 or more bits of priority
818      case MISCREG_ICC_AP1R2:
819      case MISCREG_ICC_AP1R2_EL1:
820
821        // only implemented if supporting 7 or more bits of priority
822      case MISCREG_ICC_AP1R3:
823      case MISCREG_ICC_AP1R3_EL1:
824        // only implemented if supporting 7 or more bits of priority
825        break;
826
827      case MISCREG_ICC_AP0R0:
828      case MISCREG_ICC_AP0R0_EL1:
829        if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
830            return isa->setMiscRegNoEffect(MISCREG_ICV_AP0R0_EL1, val);
831        }
832
833        break;
834
835      case MISCREG_ICC_AP0R1:
836      case MISCREG_ICC_AP0R1_EL1:
837
838        // only implemented if supporting 6 or more bits of priority
839      case MISCREG_ICC_AP0R2:
840      case MISCREG_ICC_AP0R2_EL1:
841
842        // only implemented if supporting 7 or more bits of priority
843      case MISCREG_ICC_AP0R3:
844      case MISCREG_ICC_AP0R3_EL1:
845        // only implemented if supporting 7 or more bits of priority
846        break;
847
848      case MISCREG_ICC_EOIR0:
849      case MISCREG_ICC_EOIR0_EL1: { // End Of Interrupt Register 0
850          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
851              return setMiscReg(MISCREG_ICV_EOIR0_EL1, val);
852          }
853
854          int int_id = val & 0xffffff;
855
856          // avoid activation for special interrupts
857          if (int_id >= Gicv3::INTID_SECURE) {
858              return;
859          }
860
861          Gicv3::GroupId group = Gicv3::G0S;
862
863          if (highestActiveGroup() != group) {
864              return;
865          }
866
867          dropPriority(group);
868
869          if (!isEOISplitMode()) {
870              deactivateIRQ(int_id, group);
871          }
872
873          break;
874      }
875
876      case MISCREG_ICV_EOIR0_EL1: {
877          int int_id = val & 0xffffff;
878
879          // avoid deactivation for special interrupts
880          if (int_id >= Gicv3::INTID_SECURE &&
881                  int_id <= Gicv3::INTID_SPURIOUS) {
882              return;
883          }
884
885          uint8_t drop_prio = virtualDropPriority();
886
887          if (drop_prio == 0xff) {
888              return;
889          }
890
891          int lr_idx = virtualFindActive(int_id);
892
893          if (lr_idx < 0) {
894              // No LR found matching
895              virtualIncrementEOICount();
896          } else {
897              RegVal lr =
898                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
899              Gicv3::GroupId lr_group =
900                  lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
901              uint8_t lr_group_prio = bits(lr, 55, 48) & 0xf8;
902
903              if (lr_group == Gicv3::G0S && lr_group_prio == drop_prio) {
904                  //JAIRO if (!virtualIsEOISplitMode())
905                  {
906                      virtualDeactivateIRQ(lr_idx);
907                  }
908              }
909          }
910
911          virtualUpdate();
912          break;
913      }
914
915      case MISCREG_ICC_EOIR1:
916      case MISCREG_ICC_EOIR1_EL1: { // End Of Interrupt Register 1
917          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
918              return setMiscReg(MISCREG_ICV_EOIR1_EL1, val);
919          }
920
921          int int_id = val & 0xffffff;
922
923          // avoid deactivation for special interrupts
924          if (int_id >= Gicv3::INTID_SECURE) {
925              return;
926          }
927
928          Gicv3::GroupId group =
929              inSecureState() ? Gicv3::G1S : Gicv3::G1NS;
930
931          if (highestActiveGroup() == Gicv3::G0S) {
932              return;
933          }
934
935          if (distributor->DS == 0) {
936              if (highestActiveGroup() == Gicv3::G1S && !inSecureState()) {
937                  return;
938              } else if (highestActiveGroup() == Gicv3::G1NS &&
939                      !(!inSecureState() or (currEL() == EL3))) {
940                  return;
941              }
942          }
943
944          dropPriority(group);
945
946          if (!isEOISplitMode()) {
947              deactivateIRQ(int_id, group);
948          }
949
950          break;
951      }
952
953      case MISCREG_ICV_EOIR1_EL1: {
954          int int_id = val & 0xffffff;
955
956          // avoid deactivation for special interrupts
957          if (int_id >= Gicv3::INTID_SECURE &&
958                  int_id <= Gicv3::INTID_SPURIOUS) {
959              return;
960          }
961
962          uint8_t drop_prio = virtualDropPriority();
963
964          if (drop_prio == 0xff) {
965              return;
966          }
967
968          int lr_idx = virtualFindActive(int_id);
969
970          if (lr_idx < 0) {
971              // No LR found matching
972              virtualIncrementEOICount();
973          } else {
974              RegVal lr =
975                  isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
976              Gicv3::GroupId lr_group =
977                  lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
978              uint8_t lr_group_prio = bits(lr, 55, 48) & 0xf8;
979
980              if (lr_group == Gicv3::G1NS && lr_group_prio == drop_prio) {
981                  if (!virtualIsEOISplitMode()) {
982                      virtualDeactivateIRQ(lr_idx);
983                  }
984              }
985          }
986
987          virtualUpdate();
988          break;
989      }
990
991      case MISCREG_ICC_DIR:
992      case MISCREG_ICC_DIR_EL1: { // Deactivate Interrupt Register
993          if ((currEL() == EL1) && !inSecureState() &&
994                  (hcr_imo || hcr_fmo)) {
995              return setMiscReg(MISCREG_ICV_DIR_EL1, val);
996          }
997
998          int int_id = val & 0xffffff;
999
1000          // avoid deactivation for special interrupts
1001          if (int_id >= Gicv3::INTID_SECURE) {
1002              return;
1003          }
1004
1005          if (!isEOISplitMode()) {
1006              return;
1007          }
1008
1009          /*
1010           * Check whether we're allowed to deactivate.
1011           * These checks are correspond to the spec's pseudocode.
1012           */
1013          Gicv3::GroupId group =
1014              int_id >= 32 ? distributor->getIntGroup(int_id) :
1015              redistributor->getIntGroup(int_id);
1016          bool irq_is_grp0 = group == Gicv3::G0S;
1017          bool single_sec_state = distributor->DS;
1018          bool irq_is_secure = !single_sec_state && (group != Gicv3::G1NS);
1019          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
1020          bool route_fiq_to_el3 = scr_el3.fiq;
1021          bool route_irq_to_el3 = scr_el3.irq;
1022          bool route_fiq_to_el2 = hcr_fmo;
1023          bool route_irq_to_el2 = hcr_imo;
1024
1025          switch (currEL()) {
1026            case EL3:
1027              break;
1028
1029            case EL2:
1030              if (single_sec_state && irq_is_grp0 && !route_fiq_to_el3) {
1031                  break;
1032              }
1033
1034              if (!irq_is_secure && !irq_is_grp0 && !route_irq_to_el3) {
1035                  break;
1036              }
1037
1038              return;
1039
1040            case EL1:
1041              if (!isSecureBelowEL3()) {
1042                  if (single_sec_state && irq_is_grp0 &&
1043                          !route_fiq_to_el3 && !route_fiq_to_el2) {
1044                      break;
1045                  }
1046
1047                  if (!irq_is_secure && !irq_is_grp0 &&
1048                          !route_irq_to_el3 && !route_irq_to_el2) {
1049                      break;
1050                  }
1051              } else {
1052                  if (irq_is_grp0 && !route_fiq_to_el3) {
1053                      break;
1054                  }
1055
1056                  if (!irq_is_grp0 &&
1057                          (!irq_is_secure || !single_sec_state) &&
1058                          !route_irq_to_el3) {
1059                      break;
1060                  }
1061              }
1062
1063              return;
1064
1065            default:
1066              break;
1067          }
1068
1069          deactivateIRQ(int_id, group);
1070          break;
1071      }
1072
1073      case MISCREG_ICV_DIR_EL1: {
1074          int int_id = val & 0xffffff;
1075
1076          // avoid deactivation for special interrupts
1077          if (int_id >= Gicv3::INTID_SECURE &&
1078                  int_id <= Gicv3::INTID_SPURIOUS) {
1079              return;
1080          }
1081
1082          if (!virtualIsEOISplitMode()) {
1083              return;
1084          }
1085
1086          int lr_idx = virtualFindActive(int_id);
1087
1088          if (lr_idx < 0) {
1089              // No LR found matching
1090              virtualIncrementEOICount();
1091          } else {
1092              virtualDeactivateIRQ(lr_idx);
1093          }
1094
1095          virtualUpdate();
1096          break;
1097      }
1098
1099      case MISCREG_ICC_BPR0:
1100      case MISCREG_ICC_BPR0_EL1: // Binary Point Register 0
1101      case MISCREG_ICC_BPR1:
1102      case MISCREG_ICC_BPR1_EL1: { // Binary Point Register 1
1103          if ((currEL() == EL1) && !inSecureState()) {
1104              if (misc_reg == MISCREG_ICC_BPR0_EL1 && hcr_fmo) {
1105                  return setMiscReg(MISCREG_ICV_BPR0_EL1, val);
1106              } else if (misc_reg == MISCREG_ICC_BPR1_EL1 && hcr_imo) {
1107                  return setMiscReg(MISCREG_ICV_BPR1_EL1, val);
1108              }
1109          }
1110
1111          Gicv3::GroupId group =
1112              misc_reg == MISCREG_ICC_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1S;
1113
1114          if (group == Gicv3::G1S && !inSecureState()) {
1115              group = Gicv3::G1NS;
1116          }
1117
1118          if ((group == Gicv3::G1S) &&
1119                  !isEL3OrMon() &&
1120                  (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S) &
1121                   ICC_CTLR_EL1_CBPR)) {
1122              group = Gicv3::G0S;
1123          }
1124
1125          if ((group == Gicv3::G1NS) &&
1126                  (currEL() < EL3) &&
1127                  (isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS) &
1128                   ICC_CTLR_EL1_CBPR)) {
1129              // Reads return BPR0 + 1 saturated to 7, WI
1130              return;
1131          }
1132
1133          uint8_t min_val = (group == Gicv3::G1NS) ?
1134              GIC_MIN_BPR_NS : GIC_MIN_BPR;
1135          val &= 0x7;
1136
1137          if (val < min_val) {
1138              val = min_val;
1139          }
1140
1141          break;
1142      }
1143
1144      case MISCREG_ICV_BPR0_EL1:
1145      case MISCREG_ICV_BPR1_EL1: {
1146          Gicv3::GroupId group =
1147              misc_reg == MISCREG_ICV_BPR0_EL1 ? Gicv3::G0S : Gicv3::G1NS;
1148          RegVal ich_vmcr_el2 =
1149              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1150
1151          if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) {
1152              // reads return bpr0 + 1 saturated to 7, writes ignored
1153              return;
1154          }
1155
1156          uint8_t min_VPBR = 7 - VIRTUAL_PREEMPTION_BITS;
1157
1158          if (group != Gicv3::G0S) {
1159              min_VPBR++;
1160          }
1161
1162          if (val < min_VPBR) {
1163              val = min_VPBR;
1164          }
1165
1166          if (group == Gicv3::G0S) {
1167              ich_vmcr_el2 = insertBits(ich_vmcr_el2,
1168                      ICH_VMCR_EL2_VBPR0_SHIFT + 2, ICH_VMCR_EL2_VBPR0_SHIFT,
1169                      val);
1170          } else {
1171              ich_vmcr_el2 = insertBits(ich_vmcr_el2,
1172                      ICH_VMCR_EL2_VBPR1_SHIFT + 2, ICH_VMCR_EL2_VBPR1_SHIFT,
1173                      val);
1174          }
1175
1176          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1177          do_virtual_update = true;
1178          break;
1179      }
1180
1181      case MISCREG_ICC_CTLR:
1182      case MISCREG_ICC_CTLR_EL1: { // Control Register
1183          if ((currEL() == EL1) && !inSecureState() &&
1184                  (hcr_imo || hcr_fmo)) {
1185              return setMiscReg(MISCREG_ICV_CTLR_EL1, val);
1186          }
1187
1188          /*
1189           * RSS is RO.
1190           * A3V is RO.
1191           * SEIS is RO.
1192           * IDbits is RO.
1193           * PRIbits is RO.
1194           * If EL3 is implemented and GICD_CTLR.DS == 0, then PMHE is RO.
1195           * So, only CBPR[0] and EOIMODE[1] are RW.
1196           * If EL3 is implemented and GICD_CTLR.DS == 0, then CBPR is RO.
1197           */
1198          uint64_t mask;
1199
1200          if (haveEL(EL3) and distributor->DS == 0) {
1201              mask = ICC_CTLR_EL1_EOIMODE;
1202          } else if (haveEL(EL3) and distributor->DS == 1) {
1203              mask = ICC_CTLR_EL1_PMHE | ICC_CTLR_EL1_CBPR |
1204                  ICC_CTLR_EL1_EOIMODE;
1205          } else {
1206              mask = ICC_CTLR_EL1_CBPR | ICC_CTLR_EL1_EOIMODE;
1207          }
1208
1209          RegVal old_val =
1210              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1);
1211          old_val &= ~mask;
1212          val = old_val | (val & mask);
1213          break;
1214      }
1215
1216      case MISCREG_ICV_CTLR_EL1: {
1217          RegVal ich_vmcr_el2 =
1218              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1219          ich_vmcr_el2 = insertBits(ich_vmcr_el2, ICH_VMCR_EL2_VCBPR_SHIFT,
1220                  val & ICC_CTLR_EL1_CBPR ? 1 : 0);
1221          ich_vmcr_el2 = insertBits(ich_vmcr_el2, ICH_VMCR_EL2_VEOIM_SHIFT,
1222                  val & ICC_CTLR_EL1_EOIMODE ? 1 : 0);
1223          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1224          do_virtual_update = true;
1225          break;
1226      }
1227
1228      case MISCREG_ICC_MCTLR:
1229      case MISCREG_ICC_CTLR_EL3: {
1230          RegVal icc_ctlr_el1_s =
1231              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1232          RegVal icc_ctlr_el1_ns =
1233              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
1234
1235          // ICC_CTLR_EL1(NS).EOImode is an alias of
1236          // ICC_CTLR_EL3.EOImode_EL1NS
1237          if (val & ICC_CTLR_EL3_EOIMODE_EL1NS) {
1238              icc_ctlr_el1_ns |= ICC_CTLR_EL1_EOIMODE;
1239          } else {
1240              icc_ctlr_el1_ns &= ~ICC_CTLR_EL1_EOIMODE;
1241          }
1242
1243          // ICC_CTLR_EL1(NS).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1NS
1244          if (val & ICC_CTLR_EL3_CBPR_EL1NS) {
1245              icc_ctlr_el1_ns |= ICC_CTLR_EL1_CBPR;
1246          } else {
1247              icc_ctlr_el1_ns &= ~ICC_CTLR_EL1_CBPR;
1248          }
1249
1250          // ICC_CTLR_EL1(S).EOImode is an alias of ICC_CTLR_EL3.EOImode_EL1S
1251          if (val & ICC_CTLR_EL3_EOIMODE_EL1S) {
1252              icc_ctlr_el1_s |= ICC_CTLR_EL1_EOIMODE;
1253          } else {
1254              icc_ctlr_el1_s &= ~ICC_CTLR_EL1_EOIMODE;
1255          }
1256
1257          // ICC_CTLR_EL1(S).CBPR is an alias of ICC_CTLR_EL3.CBPR_EL1S
1258          if (val & ICC_CTLR_EL3_CBPR_EL1S) {
1259              icc_ctlr_el1_s |= ICC_CTLR_EL1_CBPR;
1260          } else {
1261              icc_ctlr_el1_s &= ~ICC_CTLR_EL1_CBPR;
1262          }
1263
1264          isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S, icc_ctlr_el1_s);
1265          isa->setMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS, icc_ctlr_el1_ns);
1266          // Only ICC_CTLR_EL3_EOIMODE_EL3 is writable
1267          RegVal old_icc_ctlr_el3 =
1268              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3);
1269          old_icc_ctlr_el3 &= ~(ICC_CTLR_EL3_EOIMODE_EL3 | ICC_CTLR_EL3_RM);
1270          val = old_icc_ctlr_el3 |
1271              (val & (ICC_CTLR_EL3_EOIMODE_EL3 | ICC_CTLR_EL3_RM));
1272          break;
1273      }
1274
1275      case MISCREG_ICC_PMR:
1276      case MISCREG_ICC_PMR_EL1: { // Priority Mask Register
1277          if ((currEL() == EL1) && !inSecureState() &&
1278                  (hcr_imo || hcr_fmo)) {
1279              return setMiscReg(MISCREG_ICV_PMR_EL1, val);
1280          }
1281
1282          val &= 0xff;
1283          SCR scr_el3 = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
1284
1285          if (haveEL(EL3) && !inSecureState() && (scr_el3.fiq)) {
1286              /*
1287               * NS access and Group 0 is inaccessible to NS: return the
1288               * NS view of the current priority
1289               */
1290              RegVal old_icc_pmr_el1 =
1291                  isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1);
1292
1293              if (!(old_icc_pmr_el1 & 0x80)) {
1294                  /* Current PMR in the secure range, don't allow NS to
1295                   * change it */
1296                  return;
1297              }
1298
1299              val = (val >> 1) | 0x80;
1300          }
1301
1302          val &= ~0U << (8 - PRIORITY_BITS);
1303          break;
1304      }
1305
1306      case MISCREG_ICV_PMR_EL1: { // Priority Mask Register
1307          RegVal ich_vmcr_el2 =
1308             isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1309          ich_vmcr_el2 = insertBits(
1310              ich_vmcr_el2,
1311              ICH_VMCR_EL2_VPMR_SHIFT + ICH_VMCR_EL2_VPMR_LENGTH - 1,
1312              ICH_VMCR_EL2_VPMR_SHIFT, val);
1313
1314          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1315          virtualUpdate();
1316          return;
1317      }
1318
1319      case MISCREG_ICC_IGRPEN0:
1320      case MISCREG_ICC_IGRPEN0_EL1: { // Interrupt Group 0 Enable Register
1321          if ((currEL() == EL1) && !inSecureState() && hcr_fmo) {
1322              return setMiscReg(MISCREG_ICV_IGRPEN0_EL1, val);
1323          }
1324
1325          break;
1326      }
1327
1328      case MISCREG_ICV_IGRPEN0_EL1: {
1329          bool enable = val & 0x1;
1330          RegVal ich_vmcr_el2 =
1331              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1332          ich_vmcr_el2 = insertBits(ich_vmcr_el2,
1333                  ICH_VMCR_EL2_VENG0_SHIFT, enable);
1334          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1335          virtualUpdate();
1336          return;
1337      }
1338
1339      case MISCREG_ICC_IGRPEN1:
1340      case MISCREG_ICC_IGRPEN1_EL1: { // Interrupt Group 1 Enable Register
1341          if ((currEL() == EL1) && !inSecureState() && hcr_imo) {
1342              return setMiscReg(MISCREG_ICV_IGRPEN1_EL1, val);
1343          }
1344
1345          break;
1346      }
1347
1348      case MISCREG_ICV_IGRPEN1_EL1: {
1349          bool enable = val & 0x1;
1350          RegVal ich_vmcr_el2 =
1351              isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1352          ich_vmcr_el2 = insertBits(ich_vmcr_el2,
1353                  ICH_VMCR_EL2_VENG1_SHIFT, enable);
1354          isa->setMiscRegNoEffect(MISCREG_ICH_VMCR_EL2, ich_vmcr_el2);
1355          virtualUpdate();
1356          return;
1357      }
1358
1359      case MISCREG_ICC_MGRPEN1:
1360      case MISCREG_ICC_IGRPEN1_EL3: {
1361          // EnableGrp1S and EnableGrp1NS are aliased with
1362          // ICC_IGRPEN1_EL1_S.Enable and ICC_IGRPEN1_EL1_NS.Enable
1363          bool enable_grp_1s = val & ICC_IGRPEN1_EL3_ENABLEGRP1S;
1364          bool enable_grp_1ns = val & ICC_IGRPEN1_EL3_ENABLEGRP1NS;
1365          isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S, enable_grp_1s);
1366          isa->setMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS, enable_grp_1ns);
1367          return;
1368      }
1369
1370        // Software Generated Interrupt Group 0 Register
1371      case MISCREG_ICC_SGI0R:
1372      case MISCREG_ICC_SGI0R_EL1:
1373
1374        // Software Generated Interrupt Group 1 Register
1375      case MISCREG_ICC_SGI1R:
1376      case MISCREG_ICC_SGI1R_EL1:
1377
1378        // Alias Software Generated Interrupt Group 1 Register
1379      case MISCREG_ICC_ASGI1R:
1380      case MISCREG_ICC_ASGI1R_EL1: {
1381          bool ns = !inSecureState();
1382          Gicv3::GroupId group;
1383
1384          if (misc_reg == MISCREG_ICC_SGI1R_EL1) {
1385              group = ns ? Gicv3::G1NS : Gicv3::G1S;
1386          } else if (misc_reg == MISCREG_ICC_ASGI1R_EL1) {
1387              group = ns ? Gicv3::G1S : Gicv3::G1NS;
1388          } else {
1389              group = Gicv3::G0S;
1390          }
1391
1392          if (distributor->DS && group == Gicv3::G1S) {
1393              group = Gicv3::G0S;
1394          }
1395
1396          uint8_t aff3 = bits(val, 55, 48);
1397          uint8_t aff2 = bits(val, 39, 32);
1398          uint8_t aff1 = bits(val, 23, 16);;
1399          uint16_t target_list = bits(val, 15, 0);
1400          uint32_t int_id = bits(val, 27, 24);
1401          bool irm = bits(val, 40, 40);
1402          uint8_t rs = bits(val, 47, 44);
1403
1404          for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1405              Gicv3Redistributor * redistributor_i =
1406                  gic->getRedistributor(i);
1407              uint32_t affinity_i = redistributor_i->getAffinity();
1408
1409              if (irm) {
1410                  // Interrupts routed to all PEs in the system,
1411                  // excluding "self"
1412                  if (affinity_i == redistributor->getAffinity()) {
1413                      continue;
1414                  }
1415              } else {
1416                  // Interrupts routed to the PEs specified by
1417                  // Aff3.Aff2.Aff1.<target list>
1418                  if ((affinity_i >> 8) !=
1419                          ((aff3 << 16) | (aff2 << 8) | (aff1 << 0))) {
1420                      continue;
1421                  }
1422
1423                  uint8_t aff0_i = bits(affinity_i, 7, 0);
1424
1425                  if (!(aff0_i >= rs * 16 && aff0_i < (rs + 1) * 16 &&
1426                              ((0x1 << (aff0_i - rs * 16)) & target_list))) {
1427                      continue;
1428                  }
1429              }
1430
1431              redistributor_i->sendSGI(int_id, group, ns);
1432          }
1433
1434          break;
1435      }
1436
1437      case MISCREG_ICC_SRE:
1438      case MISCREG_ICC_SRE_EL1: { // System Register Enable Register EL1
1439          if (!(val & ICC_SRE_EL1_SRE)) {
1440              warn("Gicv3CPUInterface::setMiscReg(): "
1441                      "ICC_SRE_EL*.SRE is RAO/WI, legacy not supported!\n");
1442          }
1443
1444          bool dfb = val & ICC_SRE_EL1_DFB;
1445          bool dib = val & ICC_SRE_EL1_DIB;
1446
1447          if (haveEL(EL3) && !distributor->DS) {
1448              // DIB is RO alias of ICC_SRE_EL3.DIB
1449              // DFB is RO alias of ICC_SRE_EL3.DFB
1450          } else if (haveEL(EL3) && distributor->DS) {
1451              // DIB is RW alias of ICC_SRE_EL3.DIB
1452              // DFB is RW alias of ICC_SRE_EL3.DFB
1453              RegVal icc_sre_el3 =
1454                  isa->readMiscRegNoEffect(MISCREG_ICC_SRE_EL3);
1455              icc_sre_el3 = insertBits(icc_sre_el3, ICC_SRE_EL3_DFB, dfb);
1456              icc_sre_el3 = insertBits(icc_sre_el3, ICC_SRE_EL3_DIB, dib);
1457              isa->setMiscRegNoEffect(MISCREG_ICC_SRE_EL3, icc_sre_el3);
1458          } else if ((!haveEL(EL3) || distributor->DS) and haveEL(EL2)) {
1459              // DIB is RO alias of ICC_SRE_EL2.DIB
1460              // DFB is RO alias of ICC_SRE_EL2.DFB
1461          } else {
1462              isa->setMiscRegNoEffect(misc_reg, val);
1463          }
1464
1465          return;
1466      }
1467
1468      case MISCREG_ICC_HSRE:
1469      case MISCREG_ICC_SRE_EL2: // System Register Enable Register EL2
1470      case MISCREG_ICC_MSRE:
1471      case MISCREG_ICC_SRE_EL3: // System Register Enable Register EL3
1472        if (!(val & (1 << 0))) {
1473            warn("Gicv3CPUInterface::setMiscReg(): "
1474                    "ICC_SRE_EL*.SRE is RAO/WI, legacy not supported!\n");
1475        }
1476
1477        // All bits are RAO/WI
1478        break;
1479
1480      case MISCREG_ICH_HCR:
1481      case MISCREG_ICH_HCR_EL2:
1482        val &= ICH_HCR_EL2_EN | ICH_HCR_EL2_UIE | ICH_HCR_EL2_LRENPIE |
1483            ICH_HCR_EL2_NPIE | ICH_HCR_EL2_VGRP0EIE |
1484            ICH_HCR_EL2_VGRP0DIE | ICH_HCR_EL2_VGRP1EIE |
1485            ICH_HCR_EL2_VGRP1DIE | ICH_HCR_EL2_TC | ICH_HCR_EL2_TALL0 |
1486            ICH_HCR_EL2_TALL1 | ICH_HCR_EL2_TDIR |
1487            ICH_HCR_EL2_EOICOUNT_MASK;
1488        do_virtual_update = true;
1489        break;
1490
1491      case MISCREG_ICH_LRC0 ... MISCREG_ICH_LRC15:
1492        // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 high half part)
1493        {
1494            // Enforce RES0 bits in priority field, 5 of 8 bits used
1495            val = insertBits(val, ICH_LRC_PRIORITY_SHIFT + 2,
1496                    ICH_LRC_PRIORITY_SHIFT, 0);
1497            RegVal old_val = isa->readMiscRegNoEffect(misc_reg);
1498            val = (old_val & 0xffffffff) | (val << 32);
1499            do_virtual_update = true;
1500            break;
1501        }
1502
1503      case MISCREG_ICH_LR0 ... MISCREG_ICH_LR15: {
1504          // AArch32 (maps to AArch64 MISCREG_ICH_LR<n>_EL2 low half part)
1505          RegVal old_val = isa->readMiscRegNoEffect(misc_reg);
1506          val = (old_val & 0xffffffff00000000) | (val & 0xffffffff);
1507          do_virtual_update = true;
1508          break;
1509      }
1510
1511      case MISCREG_ICH_LR0_EL2 ... MISCREG_ICH_LR15_EL2: { // AArch64
1512          // Enforce RES0 bits in priority field, 5 of 8 bits used
1513          val = insertBits(val, ICH_LR_EL2_PRIORITY_SHIFT + 2,
1514                  ICH_LR_EL2_PRIORITY_SHIFT, 0);
1515          do_virtual_update = true;
1516          break;
1517      }
1518
1519      case MISCREG_ICH_VMCR:
1520      case MISCREG_ICH_VMCR_EL2: {
1521          val &= ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1 |
1522              ICH_VMCR_EL2_VCBPR | ICH_VMCR_EL2_VEOIM |
1523              ICH_VMCR_EL2_VBPR1_MASK | ICH_VMCR_EL2_VBPR0_MASK |
1524              ICH_VMCR_EL2_VPMR_MASK;
1525          val |= ICH_VMCR_EL2_VFIQEN; // RES1
1526          // Check VBPRs against minimun allowed value
1527          uint8_t vbpr0 = bits(val, 23, 21);
1528          uint8_t vbpr1 = bits(val, 20, 18);
1529          uint8_t min_vpr0 = 7 - VIRTUAL_PREEMPTION_BITS;
1530          uint8_t min_vpr1 = min_vpr0 + 1;
1531          vbpr0 = vbpr0 < min_vpr0 ? min_vpr0 : vbpr0;
1532          vbpr1 = vbpr1 < min_vpr1 ? min_vpr1 : vbpr1;
1533          val = insertBits(val, ICH_VMCR_EL2_VBPR0_SHIFT + 2,
1534                  ICH_VMCR_EL2_VBPR0_SHIFT, vbpr0);
1535          val = insertBits(val, ICH_VMCR_EL2_VBPR1_SHIFT + 2,
1536                  ICH_VMCR_EL2_VBPR1_SHIFT, vbpr1);
1537          break;
1538      }
1539
1540      case MISCREG_ICH_AP0R0 ... MISCREG_ICH_AP0R3:
1541      case MISCREG_ICH_AP0R0_EL2 ... MISCREG_ICH_AP0R3_EL2:
1542      case MISCREG_ICH_AP1R0 ... MISCREG_ICH_AP1R3:
1543      case MISCREG_ICH_AP1R0_EL2 ... MISCREG_ICH_AP1R3_EL2:
1544        break;
1545
1546      default:
1547        panic("Gicv3CPUInterface::setMiscReg(): "
1548                "unknown register %d (%s)",
1549                misc_reg, miscRegName[misc_reg]);
1550    }
1551
1552    isa->setMiscRegNoEffect(misc_reg, val);
1553
1554    if (do_virtual_update) {
1555        virtualUpdate();
1556    }
1557}
1558
1559int
1560Gicv3CPUInterface::virtualFindActive(uint32_t int_id)
1561{
1562    for (uint32_t lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
1563        RegVal lr =
1564            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1565        uint32_t lr_intid = bits(lr, 31, 0);
1566
1567        if ((lr & ICH_LR_EL2_STATE_ACTIVE_BIT) && lr_intid == int_id) {
1568            return lr_idx;
1569        }
1570    }
1571
1572    return -1;
1573}
1574
1575uint32_t
1576Gicv3CPUInterface::getHPPIR0()
1577{
1578    if (hppi.prio == 0xff) {
1579        return Gicv3::INTID_SPURIOUS;
1580    }
1581
1582    bool irq_is_secure = !distributor->DS && hppi.group != Gicv3::G1NS;
1583
1584    if ((hppi.group != Gicv3::G0S) && isEL3OrMon()) {
1585        /* Indicate to EL3 that there's a Group 1 interrupt for the
1586         * other state pending.
1587         */
1588        return irq_is_secure ? Gicv3::INTID_SECURE : Gicv3::INTID_NONSECURE;
1589    }
1590
1591    if ((hppi.group != Gicv3::G0S)) { // && !isEL3OrMon())
1592        return Gicv3::INTID_SPURIOUS;
1593    }
1594
1595    if (irq_is_secure && !inSecureState()) {
1596        // Secure interrupts not visible in Non-secure
1597        return Gicv3::INTID_SPURIOUS;
1598    }
1599
1600    return hppi.intid;
1601}
1602
1603uint32_t
1604Gicv3CPUInterface::getHPPIR1()
1605{
1606    if (hppi.prio == 0xff) {
1607        return Gicv3::INTID_SPURIOUS;
1608    }
1609
1610    //if ((currEL() == EL3) && ICC_CTLR_EL3_RM)
1611    if ((currEL() == EL3) &&
1612            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) & ICC_CTLR_EL3_RM) {
1613        if (hppi.group == Gicv3::G0S) {
1614            return Gicv3::INTID_SECURE;
1615        } else if (hppi.group == Gicv3::G1NS) {
1616            return Gicv3::INTID_NONSECURE;
1617        }
1618    }
1619
1620    if (hppi.group == Gicv3::G0S) {
1621        return Gicv3::INTID_SPURIOUS;
1622    }
1623
1624    bool irq_is_secure = (distributor->DS == 0) && (hppi.group != Gicv3::G1NS);
1625
1626    if (irq_is_secure) {
1627        if (!inSecureState()) {
1628            // Secure interrupts not visible in Non-secure
1629            return Gicv3::INTID_SPURIOUS;
1630        }
1631    } else if (!isEL3OrMon() && inSecureState()) {
1632        // Group 1 non-secure interrupts not visible in Secure EL1
1633        return Gicv3::INTID_SPURIOUS;
1634    }
1635
1636    return hppi.intid;
1637}
1638
1639void
1640Gicv3CPUInterface::dropPriority(Gicv3::GroupId group)
1641{
1642    int apr_misc_reg;
1643    RegVal apr;
1644    apr_misc_reg = group == Gicv3::G0S ?
1645                   MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1646    apr = isa->readMiscRegNoEffect(apr_misc_reg);
1647
1648    if (apr) {
1649        /* Clear the lowest set bit */
1650        apr &= apr - 1;
1651        isa->setMiscRegNoEffect(apr_misc_reg, apr);
1652    }
1653
1654    update();
1655}
1656
1657uint8_t
1658Gicv3CPUInterface::virtualDropPriority()
1659{
1660    /* Drop the priority of the currently active virtual interrupt
1661     * (favouring group 0 if there is a set active bit at
1662     * the same priority for both group 0 and group 1).
1663     * Return the priority value for the bit we just cleared,
1664     * or 0xff if no bits were set in the AP registers at all.
1665     * Note that though the ich_apr[] are uint64_t only the low
1666     * 32 bits are actually relevant.
1667     */
1668    int apr_max = 1 << (VIRTUAL_PREEMPTION_BITS - 5);
1669
1670    for (int i = 0; i < apr_max; i++) {
1671        RegVal vapr0 = isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i);
1672        RegVal vapr1 = isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
1673
1674        if (!vapr0 && !vapr1) {
1675            continue;
1676        }
1677
1678        int vapr0_count = ctz32(vapr0);
1679        int vapr1_count = ctz32(vapr1);
1680
1681        if (vapr0_count <= vapr1_count) {
1682            /* Clear the lowest set bit */
1683            vapr0 &= vapr0 - 1;
1684            isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0);
1685            return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1);
1686        } else {
1687            /* Clear the lowest set bit */
1688            vapr1 &= vapr1 - 1;
1689            isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1);
1690            return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1);
1691        }
1692    }
1693
1694    return 0xff;
1695}
1696
1697void
1698Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
1699{
1700    // Update active priority registers.
1701    uint32_t prio = hppi.prio & 0xf8;
1702    int apr_bit = prio >> (8 - PRIORITY_BITS);
1703    int reg_bit = apr_bit % 32;
1704    int apr_idx = group == Gicv3::G0S ?
1705                 MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1706    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1707    apr |= (1 << reg_bit);
1708    isa->setMiscRegNoEffect(apr_idx, apr);
1709
1710    // Move interrupt state from pending to active.
1711    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1712        // SGI or PPI, redistributor
1713        redistributor->activateIRQ(int_id);
1714        redistributor->updateAndInformCPUInterface();
1715    } else if (int_id < Gicv3::INTID_SECURE) {
1716        // SPI, distributor
1717        distributor->activateIRQ(int_id);
1718        distributor->updateAndInformCPUInterfaces();
1719    }
1720}
1721
1722void
1723Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx)
1724{
1725    // Update active priority registers.
1726    RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1727            lr_idx);
1728    Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
1729    uint8_t prio = bits(lr, 55, 48) & 0xf8;
1730    int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS);
1731    int reg_no = apr_bit / 32;
1732    int reg_bit = apr_bit % 32;
1733    int apr_idx = group == Gicv3::G0S ?
1734        MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no;
1735    RegVal apr = isa->readMiscRegNoEffect(apr_idx);
1736    apr |= (1 << reg_bit);
1737    isa->setMiscRegNoEffect(apr_idx, apr);
1738    // Move interrupt state from pending to active.
1739    lr &= ~ICH_LR_EL2_STATE_PENDING_BIT;
1740    lr |= ICH_LR_EL2_STATE_ACTIVE_BIT;
1741    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr);
1742}
1743
1744void
1745Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group)
1746{
1747    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1748        // SGI or PPI, redistributor
1749        redistributor->deactivateIRQ(int_id);
1750        redistributor->updateAndInformCPUInterface();
1751    } else if (int_id < Gicv3::INTID_SECURE) {
1752        // SPI, distributor
1753        distributor->deactivateIRQ(int_id);
1754        distributor->updateAndInformCPUInterfaces();
1755    } else {
1756        return;
1757    }
1758}
1759
1760void
1761Gicv3CPUInterface::virtualDeactivateIRQ(int lr_idx)
1762{
1763    RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1764            lr_idx);
1765
1766    if (lr & ICH_LR_EL2_HW) {
1767        // Deactivate the associated physical interrupt
1768        int pintid = bits(lr, 41, 32);
1769
1770        if (pintid < Gicv3::INTID_SECURE) {
1771            Gicv3::GroupId group =
1772                pintid >= 32 ? distributor->getIntGroup(pintid) :
1773                redistributor->getIntGroup(pintid);
1774            deactivateIRQ(pintid, group);
1775        }
1776    }
1777
1778    //  Remove the active bit
1779    lr &= ~ICH_LR_EL2_STATE_ACTIVE_BIT;
1780    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr);
1781}
1782
1783/*
1784 * Return a mask word which clears the subpriority bits from
1785 * a priority value for an interrupt in the specified group.
1786 * This depends on the BPR value. For CBPR0 (S or NS):
1787 *  a BPR of 0 means the group priority bits are [7:1];
1788 *  a BPR of 1 means they are [7:2], and so on down to
1789 *  ...
1790 *  a BPR of 7 meaning no group priority bits at all.
1791 * For CBPR1 NS:
1792 *  a BPR of 0 is impossible (the minimum value is 1)
1793 *  a BPR of 1 means the group priority bits are [7:1];
1794 *  a BPR of 2 means they are [7:2], and so on down to
1795 *  ...
1796 *  a BPR of 7 meaning the group priority is [7].
1797 *
1798 * Which BPR to use depends on the group of the interrupt and
1799 * the current ICC_CTLR.CBPR settings.
1800 *
1801 * This corresponds to the GroupBits() pseudocode from 4.8.2.
1802 */
1803uint32_t
1804Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group)
1805{
1806    if ((group == Gicv3::G1S &&
1807            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S)
1808            & ICC_CTLR_EL1_CBPR) ||
1809            (group == Gicv3::G1NS &&
1810             isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS)
1811             & ICC_CTLR_EL1_CBPR)) {
1812        group = Gicv3::G0S;
1813    }
1814
1815    int bpr;
1816
1817    if (group == Gicv3::G0S) {
1818        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) & 0x7;
1819    } else {
1820        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1) & 0x7;
1821    }
1822
1823    if (group == Gicv3::G1NS) {
1824        assert(bpr > 0);
1825        bpr--;
1826    }
1827
1828    return ~0U << (bpr + 1);
1829}
1830
1831uint32_t
1832Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group)
1833{
1834    RegVal ich_vmcr_el2 =
1835        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1836
1837    if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) {
1838        group = Gicv3::G0S;
1839    }
1840
1841    int bpr;
1842
1843    if (group == Gicv3::G0S) {
1844        bpr = bits(ich_vmcr_el2, 23, 21);
1845    } else {
1846        bpr = bits(ich_vmcr_el2, 20, 18);
1847    }
1848
1849    if (group == Gicv3::G1NS) {
1850        assert(bpr > 0);
1851        bpr--;
1852    }
1853
1854    return ~0U << (bpr + 1);
1855}
1856
1857bool
1858Gicv3CPUInterface::isEOISplitMode()
1859{
1860    if (isEL3OrMon()) {
1861        return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) &
1862               ICC_CTLR_EL3_EOIMODE_EL3;
1863    } else {
1864        return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1) &
1865               ICC_CTLR_EL1_EOIMODE;
1866    }
1867}
1868
1869bool
1870Gicv3CPUInterface::virtualIsEOISplitMode()
1871{
1872    RegVal ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1873    return ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM;
1874}
1875
1876int
1877Gicv3CPUInterface::highestActiveGroup()
1878{
1879    int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1));
1880    int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S));
1881    int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS));
1882
1883    if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) {
1884        return Gicv3::G1NS;
1885    }
1886
1887    if (gq_ctz < g0_ctz) {
1888        return Gicv3::G1S;
1889    }
1890
1891    if (g0_ctz < 32) {
1892        return Gicv3::G0S;
1893    }
1894
1895    return -1;
1896}
1897
1898void
1899Gicv3CPUInterface::update()
1900{
1901    bool signal_IRQ = false;
1902    bool signal_FIQ = false;
1903
1904    if (hppi.group == Gicv3::G1S && !haveEL(EL3)) {
1905        /*
1906         * Secure enabled GIC sending a G1S IRQ to a secure disabled
1907         * CPU -> send G0 IRQ
1908         */
1909        hppi.group = Gicv3::G0S;
1910    }
1911
1912    if (hppiCanPreempt()) {
1913        ArmISA::InterruptTypes int_type = intSignalType(hppi.group);
1914        DPRINTF(GIC, "Gicv3CPUInterface::update(): "
1915                "posting int as %d!\n", int_type);
1916        int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true;
1917    }
1918
1919    if (signal_IRQ) {
1920        gic->postInt(cpuId, ArmISA::INT_IRQ);
1921    } else {
1922        gic->deassertInt(cpuId, ArmISA::INT_IRQ);
1923    }
1924
1925    if (signal_FIQ) {
1926        gic->postInt(cpuId, ArmISA::INT_FIQ);
1927    } else {
1928        gic->deassertInt(cpuId, ArmISA::INT_FIQ);
1929    }
1930}
1931
1932void
1933Gicv3CPUInterface::virtualUpdate()
1934{
1935    bool signal_IRQ = false;
1936    bool signal_FIQ = false;
1937    int lr_idx = getHPPVILR();
1938
1939    if (lr_idx >= 0) {
1940        RegVal ich_lr_el2 =
1941            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1942
1943        if (hppviCanPreempt(lr_idx)) {
1944            if (ich_lr_el2 & ICH_LR_EL2_GROUP) {
1945                signal_IRQ = true;
1946            } else {
1947                signal_FIQ = true;
1948            }
1949        }
1950    }
1951
1952    RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1953
1954    if (ich_hcr_el2 & ICH_HCR_EL2_EN) {
1955        if (maintenanceInterruptStatus()) {
1956            redistributor->sendPPInt(25);
1957        }
1958    }
1959
1960    if (signal_IRQ) {
1961        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
1962                "posting int as %d!\n", ArmISA::INT_VIRT_IRQ);
1963        gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ);
1964    } else {
1965        gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ);
1966    }
1967
1968    if (signal_FIQ) {
1969        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
1970                "posting int as %d!\n", ArmISA::INT_VIRT_FIQ);
1971        gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ);
1972    } else {
1973        gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ);
1974    }
1975}
1976
1977// Returns the intex of the LR with the HPPI
1978int
1979Gicv3CPUInterface::getHPPVILR()
1980{
1981    int idx = -1;
1982    RegVal ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1983
1984    if (!(ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) {
1985        // VG0 and VG1 disabled...
1986        return idx;
1987    }
1988
1989    uint8_t highest_prio = 0xff;
1990
1991    for (int i = 0; i < 16; i++) {
1992        RegVal ich_lri_el2 =
1993            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i);
1994        uint8_t state = bits(ich_lri_el2, 63, 62);
1995
1996        if (state != Gicv3::INT_PENDING) {
1997            continue;
1998        }
1999
2000        if (ich_lri_el2 & ICH_LR_EL2_GROUP) {
2001            // VG1
2002            if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2003                continue;
2004            }
2005        } else {
2006            // VG0
2007            if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
2008                continue;
2009            }
2010        }
2011
2012        uint8_t prio = bits(ich_lri_el2, 55, 48);
2013
2014        if (prio < highest_prio) {
2015            highest_prio = prio;
2016            idx = i;
2017        }
2018    }
2019
2020    return idx;
2021}
2022
2023bool
2024Gicv3CPUInterface::hppviCanPreempt(int lr_idx)
2025{
2026    RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2027
2028    if (!(isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2) & ICH_HCR_EL2_EN)) {
2029        // virtual interface is disabled
2030        return false;
2031    }
2032
2033    uint8_t prio = bits(lr, 55, 48);
2034    uint8_t vpmr =
2035        bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24);
2036
2037    if (prio >= vpmr) {
2038        // prioriry masked
2039        return false;
2040    }
2041
2042    uint8_t rprio = virtualHighestActivePriority();
2043
2044    if (rprio == 0xff) {
2045        return true;
2046    }
2047
2048    Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
2049    uint32_t prio_mask = virtualGroupPriorityMask(group);
2050
2051    if ((prio & prio_mask) < (rprio & prio_mask)) {
2052        return true;
2053    }
2054
2055    return false;
2056}
2057
2058uint8_t
2059Gicv3CPUInterface::virtualHighestActivePriority()
2060{
2061    uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5);
2062
2063    for (int i = 0; i < num_aprs; i++) {
2064        RegVal vapr =
2065            isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) |
2066            isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
2067
2068        if (!vapr) {
2069            continue;
2070        }
2071
2072        return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1);
2073    }
2074
2075    // no active interrups, return idle priority
2076    return 0xff;
2077}
2078
2079void
2080Gicv3CPUInterface::virtualIncrementEOICount()
2081{
2082    // Increment the EOICOUNT field in ICH_HCR_EL2
2083    RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2084    uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27);
2085    EOI_cout++;
2086    ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout);
2087    isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2);
2088}
2089
2090/*
2091 * Should we signal the interrupt as IRQ or FIQ?
2092 * see spec section 4.6.2
2093 */
2094ArmISA::InterruptTypes
2095Gicv3CPUInterface::intSignalType(Gicv3::GroupId group)
2096{
2097    bool is_fiq = false;
2098
2099    switch (group) {
2100      case Gicv3::G0S:
2101        is_fiq = true;
2102        break;
2103
2104      case Gicv3::G1S:
2105        is_fiq = (distributor->DS == 0) &&
2106            (!inSecureState() || ((currEL() == EL3) && isAA64()));
2107        break;
2108
2109      case Gicv3::G1NS:
2110        is_fiq = (distributor->DS == 0) && inSecureState();
2111        break;
2112
2113      default:
2114        panic("Gicv3CPUInterface::intSignalType(): invalid group!");
2115    }
2116
2117    if (is_fiq) {
2118        return ArmISA::INT_FIQ;
2119    } else {
2120        return ArmISA::INT_IRQ;
2121    }
2122}
2123
2124bool
2125Gicv3CPUInterface::hppiCanPreempt()
2126{
2127    if (hppi.prio == 0xff) {
2128        // there is no pending interrupt
2129        return false;
2130    }
2131
2132    if (!groupEnabled(hppi.group)) {
2133        // group disabled at CPU interface
2134        return false;
2135    }
2136
2137    if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) {
2138        // priority masked
2139        return false;
2140    }
2141
2142    uint8_t rprio = highestActivePriority();
2143
2144    if (rprio == 0xff) {
2145        return true;
2146    }
2147
2148    uint32_t prio_mask = groupPriorityMask(hppi.group);
2149
2150    if ((hppi.prio & prio_mask) < (rprio & prio_mask)) {
2151        return true;
2152    }
2153
2154    return false;
2155}
2156
2157uint8_t
2158Gicv3CPUInterface::highestActivePriority()
2159{
2160    uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) |
2161                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) |
2162                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S);
2163
2164    if (apr) {
2165        return ctz32(apr) << (GIC_MIN_BPR + 1);
2166    }
2167
2168    // no active interrups, return idle priority
2169    return 0xff;
2170}
2171
2172bool
2173Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group)
2174{
2175    switch (group) {
2176      case Gicv3::G0S:
2177        return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1) &
2178            ICC_IGRPEN0_EL1_ENABLE;
2179
2180      case Gicv3::G1S:
2181        //if (distributor->DS)
2182        //{
2183        //    return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) &
2184        //           ICC_IGRPEN1_EL1_ENABLE;
2185        //}
2186        //else
2187        //{
2188        return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) &
2189            ICC_IGRPEN1_EL1_ENABLE;
2190
2191        //}
2192
2193      case Gicv3::G1NS:
2194        return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) &
2195            ICC_IGRPEN1_EL1_ENABLE;
2196
2197      default:
2198        panic("Gicv3CPUInterface::groupEnable(): invalid group!\n");
2199    }
2200}
2201
2202bool
2203Gicv3CPUInterface::inSecureState()
2204{
2205    if (!gic->getSystem()->haveSecurity()) {
2206        return false;
2207    }
2208
2209    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2210    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR);
2211    return ArmISA::inSecureState(scr, cpsr);
2212}
2213
2214int
2215Gicv3CPUInterface::currEL()
2216{
2217    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2218    bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2219
2220    if (is_64) {
2221        return (ExceptionLevel)(uint8_t) cpsr.el;
2222    } else {
2223        switch (cpsr.mode) {
2224          case MODE_USER:
2225            return 0;
2226
2227          case MODE_HYP:
2228            return 2;
2229
2230          case MODE_MON:
2231            return 3;
2232
2233          default:
2234            return 1;
2235        }
2236    }
2237}
2238
2239bool
2240Gicv3CPUInterface::haveEL(ExceptionLevel el)
2241{
2242    switch (el) {
2243      case EL0:
2244      case EL1:
2245        return true;
2246
2247      case EL2:
2248        return gic->getSystem()->haveVirtualization();
2249
2250      case EL3:
2251        return gic->getSystem()->haveSecurity();
2252
2253      default:
2254        warn("Unimplemented Exception Level\n");
2255        return false;
2256    }
2257}
2258
2259bool
2260Gicv3CPUInterface::isSecureBelowEL3()
2261{
2262    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
2263    return haveEL(EL3) && scr.ns == 0;
2264}
2265
2266bool
2267Gicv3CPUInterface::isAA64()
2268{
2269    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2270    return opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2271}
2272
2273bool
2274Gicv3CPUInterface::isEL3OrMon()
2275{
2276    if (haveEL(EL3)) {
2277        CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2278        bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2279
2280        if (is_64 && (cpsr.el == EL3)) {
2281            return true;
2282        } else if (!is_64 && (cpsr.mode == MODE_MON)) {
2283            return true;
2284        }
2285    }
2286
2287    return false;
2288}
2289
2290uint32_t
2291Gicv3CPUInterface::eoiMaintenanceInterruptStatus(uint32_t * misr)
2292{
2293    /* Return a set of bits indicating the EOI maintenance interrupt status
2294     * for each list register. The EOI maintenance interrupt status is
2295     * 1 if LR.State == 0 && LR.HW == 0 && LR.EOI == 1
2296     * (see the GICv3 spec for the ICH_EISR_EL2 register).
2297     * If misr is not NULL then we should also collect the information
2298     * about the MISR.EOI, MISR.NP and MISR.U bits.
2299     */
2300    uint32_t value = 0;
2301    int valid_count = 0;
2302    bool seen_pending = false;
2303
2304    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2305        RegVal lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
2306
2307        if ((lr & (ICH_LR_EL2_STATE_MASK | ICH_LR_EL2_HW | ICH_LR_EL2_EOI)) ==
2308                ICH_LR_EL2_EOI) {
2309            value |= (1 << lr_idx);
2310        }
2311
2312        if ((lr & ICH_LR_EL2_STATE_MASK)) {
2313            valid_count++;
2314        }
2315
2316        if (bits(lr, ICH_LR_EL2_STATE_SHIFT + ICH_LR_EL2_STATE_LENGTH,
2317                 ICH_LR_EL2_STATE_SHIFT) == ICH_LR_EL2_STATE_PENDING) {
2318            seen_pending = true;
2319        }
2320    }
2321
2322    if (misr) {
2323        RegVal ich_hcr_el2 =
2324            isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2325
2326        if (valid_count < 2 && (ich_hcr_el2 & ICH_HCR_EL2_UIE)) {
2327            *misr |= ICH_MISR_EL2_U;
2328        }
2329
2330        if (!seen_pending && (ich_hcr_el2 & ICH_HCR_EL2_NPIE)) {
2331            *misr |= ICH_MISR_EL2_NP;
2332        }
2333
2334        if (value) {
2335            *misr |= ICH_MISR_EL2_EOI;
2336        }
2337    }
2338
2339    return value;
2340}
2341
2342uint32_t
2343Gicv3CPUInterface::maintenanceInterruptStatus()
2344{
2345    /* Return a set of bits indicating the maintenance interrupt status
2346     * (as seen in the ICH_MISR_EL2 register).
2347     */
2348    uint32_t value = 0;
2349    /* Scan list registers and fill in the U, NP and EOI bits */
2350    eoiMaintenanceInterruptStatus(&value);
2351    RegVal ich_hcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2352    RegVal ich_vmcr_el2 = isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2353
2354    if (ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) {
2355        value |= ICH_MISR_EL2_LRENP;
2356    }
2357
2358    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) &&
2359            (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
2360        value |= ICH_MISR_EL2_VGRP0E;
2361    }
2362
2363    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) &&
2364            !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2365        value |= ICH_MISR_EL2_VGRP0D;
2366    }
2367
2368    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) &&
2369            (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2370        value |= ICH_MISR_EL2_VGRP1E;
2371    }
2372
2373    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) &&
2374            !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2375        value |= ICH_MISR_EL2_VGRP1D;
2376    }
2377
2378    return value;
2379}
2380
2381void
2382Gicv3CPUInterface::serialize(CheckpointOut & cp) const
2383{
2384    SERIALIZE_SCALAR(hppi.intid);
2385    SERIALIZE_SCALAR(hppi.prio);
2386    SERIALIZE_ENUM(hppi.group);
2387}
2388
2389void
2390Gicv3CPUInterface::unserialize(CheckpointIn & cp)
2391{
2392    UNSERIALIZE_SCALAR(hppi.intid);
2393    UNSERIALIZE_SCALAR(hppi.prio);
2394    UNSERIALIZE_ENUM(hppi.group);
2395}
2396