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