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