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