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