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