gic_v3_cpu_interface.cc revision 13531
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
99ArmISA::MiscReg
100Gicv3CPUInterface::readMiscReg(int misc_reg)
101{
102    ArmISA::MiscReg 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              ArmISA::MiscReg 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              ArmISA::MiscReg 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          ArmISA::MiscReg 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              ArmISA::MiscReg 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              ArmISA::MiscReg 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              ArmISA::MiscReg 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              ArmISA::MiscReg 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              ArmISA::MiscReg 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          ArmISA::MiscReg 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          ArmISA::MiscReg icc_ctlr_el1_ns =
616              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS);
617          ArmISA::MiscReg 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          ArmISA::MiscReg ich_hcr_el2 =
657              isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
658          ArmISA::MiscReg 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            ArmISA::MiscReg 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, ArmISA::MiscReg 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              ArmISA::MiscReg 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              ArmISA::MiscReg 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          ArmISA::MiscReg 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          ArmISA::MiscReg 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          ArmISA::MiscReg 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          ArmISA::MiscReg icc_ctlr_el1_s =
1201              isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S);
1202          ArmISA::MiscReg 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          ArmISA::MiscReg 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              ArmISA::MiscReg 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          ArmISA::MiscReg 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          ArmISA::MiscReg 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              ArmISA::MiscReg 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            ArmISA::MiscReg 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          ArmISA::MiscReg 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        ArmISA::MiscReg 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    ArmISA::MiscReg 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        ArmISA::MiscReg vapr0 =
1629            isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i);
1630        ArmISA::MiscReg vapr1 =
1631            isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
1632
1633        if (!vapr0 && !vapr1) {
1634            continue;
1635        }
1636
1637        int vapr0_count = ctz32(vapr0);
1638        int vapr1_count = ctz32(vapr1);
1639
1640        if (vapr0_count <= vapr1_count) {
1641            /* Clear the lowest set bit */
1642            vapr0 &= vapr0 - 1;
1643            isa->setMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i, vapr0);
1644            return (vapr0_count + i * 32) << (GIC_MIN_VBPR + 1);
1645        } else {
1646            /* Clear the lowest set bit */
1647            vapr1 &= vapr1 - 1;
1648            isa->setMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i, vapr1);
1649            return (vapr1_count + i * 32) << (GIC_MIN_VBPR + 1);
1650        }
1651    }
1652
1653    return 0xff;
1654}
1655
1656void
1657Gicv3CPUInterface::activateIRQ(uint32_t int_id, Gicv3::GroupId group)
1658{
1659    // Update active priority registers.
1660    uint32_t prio = hppi.prio & 0xf8;
1661    int apr_bit = prio >> (8 - PRIORITY_BITS);
1662    int reg_bit = apr_bit % 32;
1663    int apr_idx = group == Gicv3::G0S ?
1664                 MISCREG_ICC_AP0R0_EL1 : MISCREG_ICC_AP1R0_EL1;
1665    ArmISA::MiscReg apr = isa->readMiscRegNoEffect(apr_idx);
1666    apr |= (1 << reg_bit);
1667    isa->setMiscRegNoEffect(apr_idx, apr);
1668
1669    // Move interrupt state from pending to active.
1670    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1671        // SGI or PPI, redistributor
1672        redistributor->activateIRQ(int_id);
1673        redistributor->updateAndInformCPUInterface();
1674    } else if (int_id < Gicv3::INTID_SECURE) {
1675        // SPI, distributor
1676        distributor->activateIRQ(int_id);
1677        distributor->updateAndInformCPUInterfaces();
1678    }
1679}
1680
1681void
1682Gicv3CPUInterface::virtualActivateIRQ(uint32_t lr_idx)
1683{
1684    // Update active priority registers.
1685    ArmISA::MiscReg lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1686            lr_idx);
1687    Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
1688    uint8_t prio = bits(lr, 55, 48) & 0xf8;
1689    int apr_bit = prio >> (8 - VIRTUAL_PREEMPTION_BITS);
1690    int reg_no = apr_bit / 32;
1691    int reg_bit = apr_bit % 32;
1692    int apr_idx = group == Gicv3::G0S ?
1693        MISCREG_ICH_AP0R0_EL2 + reg_no : MISCREG_ICH_AP1R0_EL2 + reg_no;
1694    ArmISA::MiscReg apr = isa->readMiscRegNoEffect(apr_idx);
1695    apr |= (1 << reg_bit);
1696    isa->setMiscRegNoEffect(apr_idx, apr);
1697    // Move interrupt state from pending to active.
1698    lr &= ~ICH_LR_EL2_STATE_PENDING_BIT;
1699    lr |= ICH_LR_EL2_STATE_ACTIVE_BIT;
1700    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr);
1701}
1702
1703void
1704Gicv3CPUInterface::deactivateIRQ(uint32_t int_id, Gicv3::GroupId group)
1705{
1706    if (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX) {
1707        // SGI or PPI, redistributor
1708        redistributor->deactivateIRQ(int_id);
1709        redistributor->updateAndInformCPUInterface();
1710    } else if (int_id < Gicv3::INTID_SECURE) {
1711        // SPI, distributor
1712        distributor->deactivateIRQ(int_id);
1713        distributor->updateAndInformCPUInterfaces();
1714    } else {
1715        return;
1716    }
1717}
1718
1719void
1720Gicv3CPUInterface::virtualDeactivateIRQ(int lr_idx)
1721{
1722    ArmISA::MiscReg lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1723            lr_idx);
1724
1725    if (lr & ICH_LR_EL2_HW) {
1726        // Deactivate the associated physical interrupt
1727        int pintid = bits(lr, 41, 32);
1728
1729        if (pintid < Gicv3::INTID_SECURE) {
1730            Gicv3::GroupId group =
1731                pintid >= 32 ? distributor->getIntGroup(pintid) :
1732                redistributor->getIntGroup(pintid);
1733            deactivateIRQ(pintid, group);
1734        }
1735    }
1736
1737    //  Remove the active bit
1738    lr &= ~ICH_LR_EL2_STATE_ACTIVE_BIT;
1739    isa->setMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx, lr);
1740}
1741
1742/*
1743 * Return a mask word which clears the subpriority bits from
1744 * a priority value for an interrupt in the specified group.
1745 * This depends on the BPR value. For CBPR0 (S or NS):
1746 *  a BPR of 0 means the group priority bits are [7:1];
1747 *  a BPR of 1 means they are [7:2], and so on down to
1748 *  ...
1749 *  a BPR of 7 meaning no group priority bits at all.
1750 * For CBPR1 NS:
1751 *  a BPR of 0 is impossible (the minimum value is 1)
1752 *  a BPR of 1 means the group priority bits are [7:1];
1753 *  a BPR of 2 means they are [7:2], and so on down to
1754 *  ...
1755 *  a BPR of 7 meaning the group priority is [7].
1756 *
1757 * Which BPR to use depends on the group of the interrupt and
1758 * the current ICC_CTLR.CBPR settings.
1759 *
1760 * This corresponds to the GroupBits() pseudocode from 4.8.2.
1761 */
1762uint32_t
1763Gicv3CPUInterface::groupPriorityMask(Gicv3::GroupId group)
1764{
1765    if ((group == Gicv3::G1S &&
1766            isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_S)
1767            & ICC_CTLR_EL1_CBPR) ||
1768            (group == Gicv3::G1NS &&
1769             isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1_NS)
1770             & ICC_CTLR_EL1_CBPR)) {
1771        group = Gicv3::G0S;
1772    }
1773
1774    int bpr;
1775
1776    if (group == Gicv3::G0S) {
1777        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR0_EL1) & 0x7;
1778    } else {
1779        bpr = isa->readMiscRegNoEffect(MISCREG_ICC_BPR1_EL1) & 0x7;
1780    }
1781
1782    if (group == Gicv3::G1NS) {
1783        assert(bpr > 0);
1784        bpr--;
1785    }
1786
1787    return ~0U << (bpr + 1);
1788}
1789
1790uint32_t
1791Gicv3CPUInterface::virtualGroupPriorityMask(Gicv3::GroupId group)
1792{
1793    ArmISA::MiscReg ich_vmcr_el2 =
1794        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1795
1796    if (group == Gicv3::G1NS && (ich_vmcr_el2 & ICH_VMCR_EL2_VCBPR)) {
1797        group = Gicv3::G0S;
1798    }
1799
1800    int bpr;
1801
1802    if (group == Gicv3::G0S) {
1803        bpr = bits(ich_vmcr_el2, 23, 21);
1804    } else {
1805        bpr = bits(ich_vmcr_el2, 20, 18);
1806    }
1807
1808    if (group == Gicv3::G1NS) {
1809        assert(bpr > 0);
1810        bpr--;
1811    }
1812
1813    return ~0U << (bpr + 1);
1814}
1815
1816bool
1817Gicv3CPUInterface::isEOISplitMode()
1818{
1819    if (isEL3OrMon()) {
1820        return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL3) &
1821               ICC_CTLR_EL3_EOIMODE_EL3;
1822    } else {
1823        return isa->readMiscRegNoEffect(MISCREG_ICC_CTLR_EL1) &
1824               ICC_CTLR_EL1_EOIMODE;
1825    }
1826}
1827
1828bool
1829Gicv3CPUInterface::virtualIsEOISplitMode()
1830{
1831    ArmISA::MiscReg ich_vmcr_el2 =
1832        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1833    return ich_vmcr_el2 & ICH_VMCR_EL2_VEOIM;
1834}
1835
1836int
1837Gicv3CPUInterface::highestActiveGroup()
1838{
1839    int g0_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1));
1840    int gq_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S));
1841    int g1nz_ctz = ctz32(isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS));
1842
1843    if (g1nz_ctz < g0_ctz && g1nz_ctz < gq_ctz) {
1844        return Gicv3::G1NS;
1845    }
1846
1847    if (gq_ctz < g0_ctz) {
1848        return Gicv3::G1S;
1849    }
1850
1851    if (g0_ctz < 32) {
1852        return Gicv3::G0S;
1853    }
1854
1855    return -1;
1856}
1857
1858void
1859Gicv3CPUInterface::update()
1860{
1861    bool signal_IRQ = false;
1862    bool signal_FIQ = false;
1863
1864    if (hppi.group == Gicv3::G1S && !haveEL(EL3)) {
1865        /*
1866         * Secure enabled GIC sending a G1S IRQ to a secure disabled
1867         * CPU -> send G0 IRQ
1868         */
1869        hppi.group = Gicv3::G0S;
1870    }
1871
1872    if (hppiCanPreempt()) {
1873        ArmISA::InterruptTypes int_type = intSignalType(hppi.group);
1874        DPRINTF(GIC, "Gicv3CPUInterface::update(): "
1875                "posting int as %d!\n", int_type);
1876        int_type == ArmISA::INT_IRQ ? signal_IRQ = true : signal_FIQ = true;
1877    }
1878
1879    if (signal_IRQ) {
1880        gic->postInt(cpuId, ArmISA::INT_IRQ);
1881    } else {
1882        gic->deassertInt(cpuId, ArmISA::INT_IRQ);
1883    }
1884
1885    if (signal_FIQ) {
1886        gic->postInt(cpuId, ArmISA::INT_FIQ);
1887    } else {
1888        gic->deassertInt(cpuId, ArmISA::INT_FIQ);
1889    }
1890}
1891
1892void
1893Gicv3CPUInterface::virtualUpdate()
1894{
1895    bool signal_IRQ = false;
1896    bool signal_FIQ = false;
1897    int lr_idx = getHPPVILR();
1898
1899    if (lr_idx >= 0) {
1900        ArmISA::MiscReg ich_lr_el2 =
1901            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + lr_idx);
1902
1903        if (hppviCanPreempt(lr_idx)) {
1904            if (ich_lr_el2 & ICH_LR_EL2_GROUP) {
1905                signal_IRQ = true;
1906            } else {
1907                signal_FIQ = true;
1908            }
1909        }
1910    }
1911
1912    ArmISA::MiscReg ich_hcr_el2 =
1913        isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
1914
1915    if (ich_hcr_el2 & ICH_HCR_EL2_EN) {
1916        if (maintenanceInterruptStatus()) {
1917            redistributor->sendPPInt(25);
1918        }
1919    }
1920
1921    if (signal_IRQ) {
1922        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
1923                "posting int as %d!\n", ArmISA::INT_VIRT_IRQ);
1924        gic->postInt(cpuId, ArmISA::INT_VIRT_IRQ);
1925    } else {
1926        gic->deassertInt(cpuId, ArmISA::INT_VIRT_IRQ);
1927    }
1928
1929    if (signal_FIQ) {
1930        DPRINTF(GIC, "Gicv3CPUInterface::virtualUpdate(): "
1931                "posting int as %d!\n", ArmISA::INT_VIRT_FIQ);
1932        gic->postInt(cpuId, ArmISA::INT_VIRT_FIQ);
1933    } else {
1934        gic->deassertInt(cpuId, ArmISA::INT_VIRT_FIQ);
1935    }
1936}
1937
1938// Returns the intex of the LR with the HPPI
1939int
1940Gicv3CPUInterface::getHPPVILR()
1941{
1942    int idx = -1;
1943    ArmISA::MiscReg ich_vmcr_el2 =
1944        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
1945
1946    if (!(ich_vmcr_el2 & (ICH_VMCR_EL2_VENG0 | ICH_VMCR_EL2_VENG1))) {
1947        // VG0 and VG1 disabled...
1948        return idx;
1949    }
1950
1951    uint8_t highest_prio = 0xff;
1952
1953    for (int i = 0; i < 16; i++) {
1954        ArmISA::MiscReg ich_lri_el2 =
1955            isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 + i);
1956        uint8_t state = bits(ich_lri_el2, 63, 62);
1957
1958        if (state != Gicv3::INT_PENDING) {
1959            continue;
1960        }
1961
1962        if (ich_lri_el2 & ICH_LR_EL2_GROUP) {
1963            // VG1
1964            if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
1965                continue;
1966            }
1967        } else {
1968            // VG0
1969            if (!(ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
1970                continue;
1971            }
1972        }
1973
1974        uint8_t prio = bits(ich_lri_el2, 55, 48);
1975
1976        if (prio < highest_prio) {
1977            highest_prio = prio;
1978            idx = i;
1979        }
1980    }
1981
1982    return idx;
1983}
1984
1985bool
1986Gicv3CPUInterface::hppviCanPreempt(int lr_idx)
1987{
1988    ArmISA::MiscReg lr = isa->readMiscRegNoEffect(MISCREG_ICH_LR0_EL2 +
1989            lr_idx);
1990
1991    if (!(isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2) & ICH_HCR_EL2_EN)) {
1992        // virtual interface is disabled
1993        return false;
1994    }
1995
1996    uint8_t prio = bits(lr, 55, 48);
1997    uint8_t vpmr =
1998        bits(isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2), 31, 24);
1999
2000    if (prio >= vpmr) {
2001        // prioriry masked
2002        return false;
2003    }
2004
2005    uint8_t rprio = virtualHighestActivePriority();
2006
2007    if (rprio == 0xff) {
2008        return true;
2009    }
2010
2011    Gicv3::GroupId group = lr & ICH_LR_EL2_GROUP ? Gicv3::G1NS : Gicv3::G0S;
2012    uint32_t prio_mask = virtualGroupPriorityMask(group);
2013
2014    if ((prio & prio_mask) < (rprio & prio_mask)) {
2015        return true;
2016    }
2017
2018    return false;
2019}
2020
2021uint8_t
2022Gicv3CPUInterface::virtualHighestActivePriority()
2023{
2024    uint8_t num_aprs = 1 << (VIRTUAL_PRIORITY_BITS - 5);
2025
2026    for (int i = 0; i < num_aprs; i++) {
2027        ArmISA::MiscReg vapr =
2028            isa->readMiscRegNoEffect(MISCREG_ICH_AP0R0_EL2 + i) |
2029            isa->readMiscRegNoEffect(MISCREG_ICH_AP1R0_EL2 + i);
2030
2031        if (!vapr) {
2032            continue;
2033        }
2034
2035        return (i * 32 + ctz32(vapr)) << (GIC_MIN_VBPR + 1);
2036    }
2037
2038    // no active interrups, return idle priority
2039    return 0xff;
2040}
2041
2042void
2043Gicv3CPUInterface::virtualIncrementEOICount()
2044{
2045    // Increment the EOICOUNT field in ICH_HCR_EL2
2046    ArmISA::MiscReg ich_hcr_el2 =
2047        isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2048    uint32_t EOI_cout = bits(ich_hcr_el2, 31, 27);
2049    EOI_cout++;
2050    ich_hcr_el2 = insertBits(ich_hcr_el2, 31, 27, EOI_cout);
2051    isa->setMiscRegNoEffect(MISCREG_ICH_HCR_EL2, ich_hcr_el2);
2052}
2053
2054/*
2055 * Should we signal the interrupt as IRQ or FIQ?
2056 * see spec section 4.6.2
2057 */
2058ArmISA::InterruptTypes
2059Gicv3CPUInterface::intSignalType(Gicv3::GroupId group)
2060{
2061    bool is_fiq = false;
2062
2063    switch (group) {
2064      case Gicv3::G0S:
2065        is_fiq = true;
2066        break;
2067
2068      case Gicv3::G1S:
2069        is_fiq = (distributor->DS == 0) &&
2070            (!inSecureState() || ((currEL() == EL3) && isAA64()));
2071        break;
2072
2073      case Gicv3::G1NS:
2074        is_fiq = (distributor->DS == 0) && inSecureState();
2075        break;
2076
2077      default:
2078        panic("Gicv3CPUInterface::intSignalType(): invalid group!");
2079    }
2080
2081    if (is_fiq) {
2082        return ArmISA::INT_FIQ;
2083    } else {
2084        return ArmISA::INT_IRQ;
2085    }
2086}
2087
2088bool
2089Gicv3CPUInterface::hppiCanPreempt()
2090{
2091    if (hppi.prio == 0xff) {
2092        // there is no pending interrupt
2093        return false;
2094    }
2095
2096    if (!groupEnabled(hppi.group)) {
2097        // group disabled at CPU interface
2098        return false;
2099    }
2100
2101    if (hppi.prio >= isa->readMiscRegNoEffect(MISCREG_ICC_PMR_EL1)) {
2102        // priority masked
2103        return false;
2104    }
2105
2106    uint8_t rprio = highestActivePriority();
2107
2108    if (rprio == 0xff) {
2109        return true;
2110    }
2111
2112    uint32_t prio_mask = groupPriorityMask(hppi.group);
2113
2114    if ((hppi.prio & prio_mask) < (rprio & prio_mask)) {
2115        return true;
2116    }
2117
2118    return false;
2119}
2120
2121uint8_t
2122Gicv3CPUInterface::highestActivePriority()
2123{
2124    uint32_t apr = isa->readMiscRegNoEffect(MISCREG_ICC_AP0R0_EL1) |
2125                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_NS) |
2126                   isa->readMiscRegNoEffect(MISCREG_ICC_AP1R0_EL1_S);
2127
2128    if (apr) {
2129        return ctz32(apr) << (GIC_MIN_BPR + 1);
2130    }
2131
2132    // no active interrups, return idle priority
2133    return 0xff;
2134}
2135
2136bool
2137Gicv3CPUInterface::groupEnabled(Gicv3::GroupId group)
2138{
2139    switch (group) {
2140      case Gicv3::G0S:
2141        return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN0_EL1) &
2142            ICC_IGRPEN0_EL1_ENABLE;
2143
2144      case Gicv3::G1S:
2145        //if (distributor->DS)
2146        //{
2147        //    return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) &
2148        //           ICC_IGRPEN1_EL1_ENABLE;
2149        //}
2150        //else
2151        //{
2152        return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_S) &
2153            ICC_IGRPEN1_EL1_ENABLE;
2154
2155        //}
2156
2157      case Gicv3::G1NS:
2158        return isa->readMiscRegNoEffect(MISCREG_ICC_IGRPEN1_EL1_NS) &
2159            ICC_IGRPEN1_EL1_ENABLE;
2160
2161      default:
2162        panic("Gicv3CPUInterface::groupEnable(): invalid group!\n");
2163    }
2164}
2165
2166bool
2167Gicv3CPUInterface::inSecureState()
2168{
2169    if (!gic->getSystem()->haveSecurity()) {
2170        return false;
2171    }
2172
2173    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2174    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR);
2175    return ArmISA::inSecureState(scr, cpsr);
2176}
2177
2178int
2179Gicv3CPUInterface::currEL()
2180{
2181    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2182    bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2183
2184    if (is_64) {
2185        return (ExceptionLevel)(uint8_t) cpsr.el;
2186    } else {
2187        switch (cpsr.mode) {
2188          case MODE_USER:
2189            return 0;
2190
2191          case MODE_HYP:
2192            return 2;
2193
2194          case MODE_MON:
2195            return 3;
2196
2197          default:
2198            return 1;
2199        }
2200    }
2201}
2202
2203bool
2204Gicv3CPUInterface::haveEL(ExceptionLevel el)
2205{
2206    switch (el) {
2207      case EL0:
2208      case EL1:
2209        return true;
2210
2211      case EL2:
2212        return gic->getSystem()->haveVirtualization();
2213
2214      case EL3:
2215        return gic->getSystem()->haveSecurity();
2216
2217      default:
2218        warn("Unimplemented Exception Level\n");
2219        return false;
2220    }
2221}
2222
2223bool
2224Gicv3CPUInterface::isSecureBelowEL3()
2225{
2226    SCR scr = isa->readMiscRegNoEffect(MISCREG_SCR_EL3);
2227    return haveEL(EL3) && scr.ns == 0;
2228}
2229
2230bool
2231Gicv3CPUInterface::isAA64()
2232{
2233    CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2234    return opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2235}
2236
2237bool
2238Gicv3CPUInterface::isEL3OrMon()
2239{
2240    if (haveEL(EL3)) {
2241        CPSR cpsr = isa->readMiscRegNoEffect(MISCREG_CPSR);
2242        bool is_64 = opModeIs64((OperatingMode)(uint8_t) cpsr.mode);
2243
2244        if (is_64 && (cpsr.el == EL3)) {
2245            return true;
2246        } else if (!is_64 && (cpsr.mode == MODE_MON)) {
2247            return true;
2248        }
2249    }
2250
2251    return false;
2252}
2253
2254uint32_t
2255Gicv3CPUInterface::eoiMaintenanceInterruptStatus(uint32_t * misr)
2256{
2257    /* Return a set of bits indicating the EOI maintenance interrupt status
2258     * for each list register. The EOI maintenance interrupt status is
2259     * 1 if LR.State == 0 && LR.HW == 0 && LR.EOI == 1
2260     * (see the GICv3 spec for the ICH_EISR_EL2 register).
2261     * If misr is not NULL then we should also collect the information
2262     * about the MISR.EOI, MISR.NP and MISR.U bits.
2263     */
2264    uint32_t value = 0;
2265    int valid_count = 0;
2266    bool seen_pending = false;
2267
2268    for (int lr_idx = 0; lr_idx < VIRTUAL_NUM_LIST_REGS; lr_idx++) {
2269        ArmISA::MiscReg lr =
2270            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        ArmISA::MiscReg 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    ArmISA::MiscReg ich_hcr_el2 =
2317        isa->readMiscRegNoEffect(MISCREG_ICH_HCR_EL2);
2318    ArmISA::MiscReg ich_vmcr_el2 =
2319        isa->readMiscRegNoEffect(MISCREG_ICH_VMCR_EL2);
2320
2321    if (ich_hcr_el2 & (ICH_HCR_EL2_LRENPIE | ICH_HCR_EL2_EOICOUNT_MASK)) {
2322        value |= ICH_MISR_EL2_LRENP;
2323    }
2324
2325    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0EIE) &&
2326            (ich_vmcr_el2 & ICH_VMCR_EL2_VENG0)) {
2327        value |= ICH_MISR_EL2_VGRP0E;
2328    }
2329
2330    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP0DIE) &&
2331            !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2332        value |= ICH_MISR_EL2_VGRP0D;
2333    }
2334
2335    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1EIE) &&
2336            (ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2337        value |= ICH_MISR_EL2_VGRP1E;
2338    }
2339
2340    if ((ich_hcr_el2 & ICH_HCR_EL2_VGRP1DIE) &&
2341            !(ich_vmcr_el2 & ICH_VMCR_EL2_VENG1)) {
2342        value |= ICH_MISR_EL2_VGRP1D;
2343    }
2344
2345    return value;
2346}
2347
2348void
2349Gicv3CPUInterface::serialize(CheckpointOut & cp) const
2350{
2351    SERIALIZE_SCALAR(hppi.intid);
2352    SERIALIZE_SCALAR(hppi.prio);
2353    SERIALIZE_ENUM(hppi.group);
2354}
2355
2356void
2357Gicv3CPUInterface::unserialize(CheckpointIn & cp)
2358{
2359    UNSERIALIZE_SCALAR(hppi.intid);
2360    UNSERIALIZE_SCALAR(hppi.prio);
2361    UNSERIALIZE_ENUM(hppi.group);
2362}
2363