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