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