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