gic_v3_redistributor.cc revision 14258
1/*
2 * Copyright (c) 2019 ARM Limited
3 * All rights reserved
4 *
5 * The license below extends only to copyright in the software and shall
6 * not be construed as granting a license to any other intellectual
7 * property including but not limited to intellectual property relating
8 * to a hardware implementation of the functionality of the software
9 * licensed hereunder.  You may use the software subject to the license
10 * terms below provided that you ensure that this notice is replicated
11 * unmodified and in its entirety in all distributions of the software,
12 * modified or unmodified, in source code or in binary form.
13 *
14 * Copyright (c) 2018 Metempsy Technology Consulting
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions are
19 * met: redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer;
21 * redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution;
24 * neither the name of the copyright holders nor the names of its
25 * contributors may be used to endorse or promote products derived from
26 * this software without specific prior written permission.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
29 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
30 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
31 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
32 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
33 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
34 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
35 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
36 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
37 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
38 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
39 *
40 * Authors: Jairo Balart
41 */
42
43#include "dev/arm/gic_v3_redistributor.hh"
44
45#include "arch/arm/utility.hh"
46#include "debug/GIC.hh"
47#include "dev/arm/gic_v3_cpu_interface.hh"
48#include "dev/arm/gic_v3_distributor.hh"
49#include "mem/fs_translating_port_proxy.hh"
50
51const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
52                                                    SGI_base + 0x041f);
53
54Gicv3Redistributor::Gicv3Redistributor(Gicv3 * gic, uint32_t cpu_id)
55    : gic(gic),
56      distributor(nullptr),
57      cpuInterface(nullptr),
58      cpuId(cpu_id),
59      memProxy(nullptr),
60      peInLowPowerState(true),
61      irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
62      irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
63      irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
64      irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
65      irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
66      irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX, Gicv3::INT_EDGE_TRIGGERED),
67      irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
68      irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
69      DPG1S(false),
70      DPG1NS(false),
71      DPG0(false),
72      EnableLPIs(false),
73      lpiConfigurationTablePtr(0),
74      lpiIDBits(0),
75      lpiPendingTablePtr(0),
76      addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
77{
78}
79
80void
81Gicv3Redistributor::init()
82{
83    distributor = gic->getDistributor();
84    cpuInterface = gic->getCPUInterface(cpuId);
85
86    memProxy = &gic->getSystem()->physProxy;
87}
88
89uint64_t
90Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
91{
92    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
93        uint64_t value = 0;
94        int first_intid = addr - GICR_IPRIORITYR.start();
95
96        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
97            uint8_t prio = irqPriority[int_id];
98
99            if (!distributor->DS && !is_secure_access) {
100                if (getIntGroup(int_id) != Gicv3::G1NS) {
101                    // RAZ/WI for non-secure accesses for secure interrupts
102                    continue;
103                } else {
104                    // NS view
105                    prio = (prio << 1) & 0xff;
106                }
107            }
108
109            value |= prio << (i * 8);
110        }
111
112        return value;
113    }
114
115    switch (addr) {
116      case GICR_CTLR: { // Control Register
117          uint64_t value = 0;
118
119          if (DPG1S) {
120              value |= GICR_CTLR_DPG1S;
121          }
122
123          if (DPG1NS) {
124              value |= GICR_CTLR_DPG1NS;
125          }
126
127          if (DPG0) {
128              value |= GICR_CTLR_DPG0;
129          }
130
131          if (EnableLPIs) {
132              value |= GICR_CTLR_ENABLE_LPIS;
133          }
134
135          return value;
136      }
137
138      case GICR_IIDR: // Implementer Identification Register
139        //return 0x43b; // r0p0 GIC-500
140        return 0;
141
142      case GICR_TYPER: { // Type Register
143          /*
144           * Affinity_Value   [63:32] == X
145           * (The identity of the PE associated with this Redistributor)
146           * CommonLPIAff     [25:24] == 01
147           * (All Redistributors with the same Aff3 value must share an
148           * LPI Configuration table)
149           * Processor_Number [23:8]  == X
150           * (A unique identifier for the PE)
151           * DPGS             [5]     == 1
152           * (GICR_CTLR.DPG* bits are supported)
153           * Last             [4]     == X
154           * (This Redistributor is the highest-numbered Redistributor in
155           * a series of contiguous Redistributor pages)
156           * DirectLPI        [3]     == 1
157           * (direct injection of LPIs supported)
158           * VLPIS            [1]     == 0
159           * (virtual LPIs not supported)
160           * PLPIS            [0]     == 1
161           * (physical LPIs supported)
162           */
163          uint64_t affinity = getAffinity();
164          int last = cpuId == (gic->getSystem()->numContexts() - 1);
165          return (affinity << 32) | (1 << 24) | (cpuId << 8) |
166              (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
167      }
168
169      case GICR_WAKER: // Wake Register
170        if (!distributor->DS && !is_secure_access) {
171            // RAZ/WI for non-secure accesses
172            return 0;
173        }
174
175        if (peInLowPowerState) {
176            return GICR_WAKER_ChildrenAsleep | GICR_WAKER_ProcessorSleep;
177        } else {
178            return 0;
179        }
180
181      case GICR_PIDR0: { // Peripheral ID0 Register
182          return 0x92; // Part number, bits[7:0]
183      }
184
185      case GICR_PIDR1: { // Peripheral ID1 Register
186          uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
187          uint8_t part_1 = 0x4; // Part number, bits[11:8]
188          return (des_0 << 4) | (part_1 << 0);
189      }
190
191      case GICR_PIDR2: { // Peripheral ID2 Register
192          uint8_t arch_rev = 0x3; // 0x3 GICv3
193          uint8_t jedec = 0x1; // JEP code
194          uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
195          return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
196      }
197
198      case GICR_PIDR3: // Peripheral ID3 Register
199        return 0x0; // Implementation defined
200
201      case GICR_PIDR4: { // Peripheral ID4 Register
202          uint8_t size = 0x4; // 64 KB software visible page
203          uint8_t des_2 = 0x4; // ARM implementation
204          return (size << 4) | (des_2 << 0);
205      }
206
207      case GICR_PIDR5: // Peripheral ID5 Register
208      case GICR_PIDR6: // Peripheral ID6 Register
209      case GICR_PIDR7: // Peripheral ID7 Register
210        return 0; // RES0
211
212      case GICR_IGROUPR0: { // Interrupt Group Register 0
213          uint64_t value = 0;
214
215          if (!distributor->DS && !is_secure_access) {
216              // RAZ/WI for non-secure accesses
217              return 0;
218          }
219
220          for (int int_id = 0; int_id < 8 * size; int_id++) {
221              value |= (irqGroup[int_id] << int_id);
222          }
223
224          return value;
225      }
226
227      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
228      case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
229          uint64_t value = 0;
230
231          for (int int_id = 0; int_id < 8 * size; int_id++) {
232              if (!distributor->DS && !is_secure_access) {
233                  // RAZ/WI for non-secure accesses for secure interrupts
234                  if (getIntGroup(int_id) != Gicv3::G1NS) {
235                      continue;
236                  }
237              }
238
239              if (irqEnabled[int_id]) {
240                  value |= (1 << int_id);
241              }
242          }
243
244          return value;
245      }
246
247      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
248      case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
249          uint64_t value = 0;
250
251          for (int int_id = 0; int_id < 8 * size; int_id++) {
252              if (!distributor->DS && !is_secure_access) {
253                  // RAZ/WI for non-secure accesses for secure interrupts
254                  if (getIntGroup(int_id) != Gicv3::G1NS) {
255                      continue;
256                  }
257              }
258
259              value |= (irqPending[int_id] << int_id);
260          }
261
262          return value;
263      }
264
265      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
266      case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
267          uint64_t value = 0;
268
269          for (int int_id = 0; int_id < 8 * size; int_id++) {
270              if (!distributor->DS && !is_secure_access) {
271                  // RAZ/WI for non-secure accesses for secure interrupts
272                  if (getIntGroup(int_id) != Gicv3::G1NS) {
273                      continue;
274                  }
275              }
276
277              value |=  irqActive[int_id] << int_id;
278          }
279
280          return value;
281      }
282
283      case GICR_ICFGR0: // SGI Configuration Register
284      case GICR_ICFGR1: { // PPI Configuration Register
285          uint64_t value = 0;
286          uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
287
288          for (int i = 0, int_id = first_int_id; i < 32;
289               i = i + 2, int_id++) {
290              if (!distributor->DS && !is_secure_access) {
291                  // RAZ/WI for non-secure accesses for secure interrupts
292                  if (getIntGroup(int_id) != Gicv3::G1NS) {
293                      continue;
294                  }
295              }
296
297              if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
298                  value |= (0x2) << i;
299              }
300          }
301
302          return value;
303      }
304
305      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
306          uint64_t value = 0;
307
308          if (distributor->DS) {
309              value = 0;
310          } else {
311              if (!is_secure_access) {
312                  // RAZ/WI for non-secure accesses
313                  value = 0;
314              } else {
315                  for (int int_id = 0; int_id < 8 * size; int_id++) {
316                      value |= irqGrpmod[int_id] << int_id;
317                  }
318              }
319          }
320
321          return value;
322      }
323
324      case GICR_NSACR: { // Non-secure Access Control Register
325          uint64_t value = 0;
326
327          if (distributor->DS) {
328              // RAZ/WI
329              value = 0;
330          } else {
331              if (!is_secure_access) {
332                  // RAZ/WI
333                  value = 0;
334              } else {
335                  for (int i = 0, int_id = 0; i < 8 * size;
336                       i = i + 2, int_id++) {
337                      value |= irqNsacr[int_id] << i;
338                  }
339              }
340          }
341
342          return value;
343      }
344
345      case GICR_PROPBASER: // Redistributor Properties Base Address Register
346        // OuterCache, bits [58:56]
347        //   000 Memory type defined in InnerCache field
348        // Physical_Address, bits [51:12]
349        //   Bits [51:12] of the physical address containing the LPI
350        //   Configuration table
351        // Shareability, bits [11:10]
352        //   00 Non-shareable
353        // InnerCache, bits [9:7]
354        //   000 Device-nGnRnE
355        // IDbits, bits [4:0]
356        //   limited by GICD_TYPER.IDbits
357        return lpiConfigurationTablePtr | lpiIDBits;
358
359      // Redistributor LPI Pending Table Base Address Register
360      case GICR_PENDBASER:
361        // PTZ, bit [62]
362        //   Pending Table Zero
363        // OuterCache, bits [58:56]
364        //   000 Memory type defined in InnerCache field
365        // Physical_Address, bits [51:16]
366        //   Bits [51:16] of the physical address containing the LPI Pending
367        //   table
368        // Shareability, bits [11:10]
369        //   00 Non-shareable
370        // InnerCache, bits [9:7]
371        //   000 Device-nGnRnE
372        return lpiPendingTablePtr;
373
374      // Redistributor Synchronize Register
375      case GICR_SYNCR:
376        return 0;
377
378      default:
379        panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
380        break;
381    }
382}
383
384void
385Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
386                          bool is_secure_access)
387{
388    if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
389        int first_intid = addr - GICR_IPRIORITYR.start();
390
391        for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
392            uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
393
394            if (!distributor->DS && !is_secure_access) {
395                if (getIntGroup(int_id) != Gicv3::G1NS) {
396                    // RAZ/WI for non-secure accesses for secure interrupts
397                    continue;
398                } else {
399                    // NS view
400                    prio = 0x80 | (prio >> 1);
401                }
402            }
403
404            irqPriority[int_id] = prio;
405            DPRINTF(GIC, "Gicv3Redistributor::write(): "
406                    "int_id %d priority %d\n", int_id, irqPriority[int_id]);
407        }
408
409        return;
410    }
411
412    switch (addr) {
413      case GICR_CTLR: {
414          // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
415          EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
416          DPG1S = data & GICR_CTLR_DPG1S;
417          DPG1NS = data & GICR_CTLR_DPG1NS;
418          DPG0 = data & GICR_CTLR_DPG0;
419          break;
420      }
421
422      case GICR_WAKER: // Wake Register
423        if (!distributor->DS && !is_secure_access) {
424            // RAZ/WI for non-secure accesses
425            return;
426        }
427
428        if (not peInLowPowerState and
429            (data & GICR_WAKER_ProcessorSleep)) {
430            DPRINTF(GIC, "Gicv3Redistributor::write(): "
431                    "PE entering in low power state\n");
432        } else if (peInLowPowerState and
433                   not(data & GICR_WAKER_ProcessorSleep)) {
434            DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
435        }
436
437        peInLowPowerState = data & GICR_WAKER_ProcessorSleep;
438        break;
439
440      case GICR_IGROUPR0: // Interrupt Group Register 0
441        if (!distributor->DS && !is_secure_access) {
442            // RAZ/WI for non-secure accesses
443            return;
444        }
445
446        for (int int_id = 0; int_id < 8 * size; int_id++) {
447            irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
448            DPRINTF(GIC, "Gicv3Redistributor::write(): "
449                    "int_id %d group %d\n", int_id, irqGroup[int_id]);
450        }
451
452        break;
453
454      case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
455        for (int int_id = 0; int_id < 8 * size; int_id++) {
456            if (!distributor->DS && !is_secure_access) {
457                // RAZ/WI for non-secure accesses for secure interrupts
458                if (getIntGroup(int_id) != Gicv3::G1NS) {
459                    continue;
460                }
461            }
462
463            bool enable = data & (1 << int_id) ? 1 : 0;
464
465            if (enable) {
466                irqEnabled[int_id] = true;
467            }
468
469            DPRINTF(GIC, "Gicv3Redistributor::write(): "
470                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
471        }
472
473        break;
474
475      case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
476        for (int int_id = 0; int_id < 8 * size; int_id++) {
477            if (!distributor->DS && !is_secure_access) {
478                // RAZ/WI for non-secure accesses for secure interrupts
479                if (getIntGroup(int_id) != Gicv3::G1NS) {
480                    continue;
481                }
482            }
483
484            bool disable = data & (1 << int_id) ? 1 : 0;
485
486            if (disable) {
487                irqEnabled[int_id] = false;
488            }
489
490            DPRINTF(GIC, "Gicv3Redistributor::write(): "
491                    "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
492        }
493
494        break;
495
496      case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
497        for (int int_id = 0; int_id < 8 * size; int_id++) {
498            if (!distributor->DS && !is_secure_access) {
499                // RAZ/WI for non-secure accesses for secure interrupts
500                if (getIntGroup(int_id) != Gicv3::G1NS) {
501                    continue;
502                }
503            }
504
505            bool pending = data & (1 << int_id) ? 1 : 0;
506
507            if (pending) {
508                DPRINTF(GIC, "Gicv3Redistributor::write() "
509                        "(GICR_ISPENDR0): int_id %d (PPI) "
510                        "pending bit set\n", int_id);
511                irqPending[int_id] = true;
512            }
513        }
514
515        updateDistributor();
516        break;
517
518      case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
519        for (int int_id = 0; int_id < 8 * size; int_id++) {
520            if (!distributor->DS && !is_secure_access) {
521                // RAZ/WI for non-secure accesses for secure interrupts
522                if (getIntGroup(int_id) != Gicv3::G1NS) {
523                    continue;
524                }
525            }
526
527            bool clear = data & (1 << int_id) ? 1 : 0;
528
529            if (clear) {
530                irqPending[int_id] = false;
531            }
532        }
533
534        break;
535
536      case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
537        for (int int_id = 0; int_id < 8 * size; int_id++) {
538            if (!distributor->DS && !is_secure_access) {
539                // RAZ/WI for non-secure accesses for secure interrupts
540                if (getIntGroup(int_id) != Gicv3::G1NS) {
541                    continue;
542                }
543            }
544
545            bool activate = data & (1 << int_id) ? 1 : 0;
546
547            if (activate) {
548                if (!irqActive[int_id]) {
549                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
550                            "int_id %d active set\n", int_id);
551                }
552
553                irqActive[int_id] = true;
554            }
555        }
556
557        break;
558
559      case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
560        for (int int_id = 0; int_id < 8 * size; int_id++) {
561            if (!distributor->DS && !is_secure_access) {
562                // RAZ/WI for non-secure accesses for secure interrupts
563                if (getIntGroup(int_id) != Gicv3::G1NS) {
564                    continue;
565                }
566            }
567
568            bool clear = data & (1 << int_id) ? 1 : 0;
569
570            if (clear) {
571                if (irqActive[int_id]) {
572                    DPRINTF(GIC, "Gicv3Redistributor::write(): "
573                            "int_id %d active cleared\n", int_id);
574                }
575
576                irqActive[int_id] = false;
577            }
578        }
579
580        break;
581
582      case GICR_ICFGR1: { // PPI Configuration Register
583          int first_intid = Gicv3::SGI_MAX;
584
585          for (int i = 0, int_id = first_intid; i < 8 * size;
586               i = i + 2, int_id++) {
587              if (!distributor->DS && !is_secure_access) {
588                  // RAZ/WI for non-secure accesses for secure interrupts
589                  if (getIntGroup(int_id) != Gicv3::G1NS) {
590                      continue;
591                  }
592              }
593
594              irqConfig[int_id] = data & (0x2 << i) ?
595                                  Gicv3::INT_EDGE_TRIGGERED :
596                                  Gicv3::INT_LEVEL_SENSITIVE;
597              DPRINTF(GIC, "Gicv3Redistributor::write(): "
598                      "int_id %d (PPI) config %d\n",
599                      int_id, irqConfig[int_id]);
600          }
601
602          break;
603      }
604
605      case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
606          if (distributor->DS) {
607              // RAZ/WI if secutiry disabled
608          } else {
609              for (int int_id = 0; int_id < 8 * size; int_id++) {
610                  if (!is_secure_access) {
611                      // RAZ/WI for non-secure accesses
612                      continue;
613                  }
614
615                  irqGrpmod[int_id] = data & (1 << int_id);
616              }
617          }
618
619          break;
620      }
621
622      case GICR_NSACR: { // Non-secure Access Control Register
623          if (distributor->DS) {
624              // RAZ/WI
625          } else {
626              if (!is_secure_access) {
627                  // RAZ/WI
628              } else {
629                  for (int i = 0, int_id = 0; i < 8 * size;
630                       i = i + 2, int_id++) {
631                      irqNsacr[int_id] = (data >> i) & 0x3;
632                  }
633              }
634          }
635
636          break;
637      }
638
639      case GICR_SETLPIR: // Set LPI Pending Register
640        setClrLPI(data, true);
641        break;
642
643      case GICR_CLRLPIR: // Clear LPI Pending Register
644        setClrLPI(data, false);
645        break;
646
647      case GICR_PROPBASER: { // Redistributor Properties Base Address Register
648          // OuterCache, bits [58:56]
649          //   000 Memory type defined in InnerCache field
650          // Physical_Address, bits [51:12]
651          //   Bits [51:12] of the physical address containing the LPI
652          //   Configuration table
653          // Shareability, bits [11:10]
654          //   00 Non-shareable
655          // InnerCache, bits [9:7]
656          //   000 Device-nGnRnE
657          // IDbits, bits [4:0]
658          //   limited by GICD_TYPER.IDbits (= 0xf)
659          lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
660          lpiIDBits = data & 0x1f;
661
662          // 0xf here matches the value of GICD_TYPER.IDbits.
663          // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
664          // value
665          if (lpiIDBits > 0xf) {
666              lpiIDBits = 0xf;
667          }
668
669          break;
670      }
671
672      // Redistributor LPI Pending Table Base Address Register
673      case GICR_PENDBASER:
674        // PTZ, bit [62]
675        //   Pending Table Zero
676        // OuterCache, bits [58:56]
677        //   000 Memory type defined in InnerCache field
678        // Physical_Address, bits [51:16]
679        //   Bits [51:16] of the physical address containing the LPI Pending
680        //   table
681        // Shareability, bits [11:10]
682        //   00 Non-shareable
683        // InnerCache, bits [9:7]
684        //   000 Device-nGnRnE
685        lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
686        break;
687
688      case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
689          // Do nothing: no caching supported
690          break;
691      }
692
693      case GICR_INVALLR: { // Redistributor Invalidate All Register
694          // Do nothing: no caching supported
695          break;
696      }
697
698      default:
699        panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
700        break;
701    }
702}
703
704void
705Gicv3Redistributor::sendPPInt(uint32_t int_id)
706{
707    assert((int_id >= Gicv3::SGI_MAX) &&
708           (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
709    irqPending[int_id] = true;
710    DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
711            "int_id %d (PPI) pending bit set\n", int_id);
712    updateDistributor();
713}
714
715void
716Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
717{
718    assert(int_id < Gicv3::SGI_MAX);
719    Gicv3::GroupId int_group = getIntGroup(int_id);
720
721    bool forward = false;
722
723    if (ns) {
724        // Non-Secure EL1 and EL2 access
725        int nsaccess = irqNsacr[int_id];
726        if (int_group == Gicv3::G0S) {
727
728            forward = distributor->DS || (nsaccess >= 1);
729
730        } else if (int_group == Gicv3::G1S) {
731            forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
732                      nsaccess == 2);
733        } else {
734            // G1NS
735            forward = group == Gicv3::G1NS;
736        }
737    } else {
738        // Secure EL1 and EL3 access
739        forward = (group == int_group) ||
740            (group == Gicv3::G1S && int_group == Gicv3::G0S &&
741            distributor->DS);
742    }
743
744    if (!forward) return;
745
746    irqPending[int_id] = true;
747    DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
748            "int_id %d (SGI) pending bit set\n", int_id);
749    updateDistributor();
750}
751
752Gicv3::IntStatus
753Gicv3Redistributor::intStatus(uint32_t int_id) const
754{
755    assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
756
757    if (irqPending[int_id]) {
758        if (irqActive[int_id]) {
759            return Gicv3::INT_ACTIVE_PENDING;
760        }
761
762        return Gicv3::INT_PENDING;
763    } else if (irqActive[int_id]) {
764        return Gicv3::INT_ACTIVE;
765    } else {
766        return Gicv3::INT_INACTIVE;
767    }
768}
769
770void
771Gicv3Redistributor::updateDistributor()
772{
773    distributor->update();
774}
775
776/*
777 * Recalculate the highest priority pending interrupt after a
778 * change to redistributor state.
779 */
780void
781Gicv3Redistributor::update()
782{
783    for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
784        Gicv3::GroupId int_group = getIntGroup(int_id);
785        bool group_enabled = distributor->groupEnabled(int_group);
786
787        if (irqPending[int_id] && irqEnabled[int_id] &&
788                !irqActive[int_id] && group_enabled) {
789            if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
790                /*
791                 * Multiple pending ints with same priority.
792                 * Implementation choice which one to signal.
793                 * Our implementation selects the one with the lower id.
794                 */
795                (irqPriority[int_id] == cpuInterface->hppi.prio &&
796                 int_id < cpuInterface->hppi.intid)) {
797                cpuInterface->hppi.intid = int_id;
798                cpuInterface->hppi.prio = irqPriority[int_id];
799                cpuInterface->hppi.group = int_group;
800            }
801        }
802    }
803
804    // Check LPIs
805    if (EnableLPIs) {
806
807        const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
808        const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
809
810        uint8_t lpi_pending_table[largest_lpi_id / 8];
811        uint8_t lpi_config_table[number_lpis];
812
813        memProxy->readBlob(lpiPendingTablePtr,
814                           lpi_pending_table,
815                           sizeof(lpi_pending_table));
816
817        memProxy->readBlob(lpiConfigurationTablePtr,
818                           lpi_config_table,
819                           sizeof(lpi_config_table));
820
821        for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
822             lpi_id++) {
823            uint32_t lpi_pending_entry_byte = lpi_id / 8;
824            uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
825            bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
826                                  1 << lpi_pending_entry_bit_position;
827            uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
828
829            LPIConfigurationTableEntry config_entry =
830                lpi_config_table[lpi_configuration_entry_index];
831
832            bool lpi_is_enable = config_entry.enable;
833
834            // LPIs are always Non-secure Group 1 interrupts,
835            // in a system where two Security states are enabled.
836            Gicv3::GroupId lpi_group = Gicv3::G1NS;
837            bool group_enabled = distributor->groupEnabled(lpi_group);
838
839            if (lpi_is_pending && lpi_is_enable && group_enabled) {
840                uint8_t lpi_priority = config_entry.priority << 2;
841
842                if ((lpi_priority < cpuInterface->hppi.prio) ||
843                    (lpi_priority == cpuInterface->hppi.prio &&
844                     lpi_id < cpuInterface->hppi.intid)) {
845                    cpuInterface->hppi.intid = lpi_id;
846                    cpuInterface->hppi.prio = lpi_priority;
847                    cpuInterface->hppi.group = lpi_group;
848                }
849            }
850        }
851    }
852
853    cpuInterface->update();
854}
855
856uint8_t
857Gicv3Redistributor::readEntryLPI(uint32_t lpi_id)
858{
859    Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
860
861    uint8_t lpi_pending_entry;
862    memProxy->readBlob(lpi_pending_entry_ptr,
863                       &lpi_pending_entry,
864                       sizeof(lpi_pending_entry));
865
866    return lpi_pending_entry;
867}
868
869void
870Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
871{
872    Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
873
874    memProxy->writeBlob(lpi_pending_entry_ptr,
875                        &lpi_pending_entry,
876                        sizeof(lpi_pending_entry));
877}
878
879bool
880Gicv3Redistributor::isPendingLPI(uint32_t lpi_id)
881{
882    // Fetch the LPI pending entry from memory
883    uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
884
885    uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
886    bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
887
888    return is_set;
889}
890
891void
892Gicv3Redistributor::setClrLPI(uint64_t data, bool set)
893{
894    if (!EnableLPIs) {
895        // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
896        // GICR_CTLR.EnableLPIs == 0.
897        return;
898    }
899
900    uint32_t lpi_id = data & 0xffffffff;
901    uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
902
903    if (lpi_id > largest_lpi_id) {
904        // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
905        // pINTID value specifies an unimplemented LPI.
906        return;
907    }
908
909    // Fetch the LPI pending entry from memory
910    uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
911
912    uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
913    bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
914
915    if (set) {
916        if (is_set) {
917            // Writes to GICR_SETLPIR have not effect if the pINTID field
918            // corresponds to an LPI that is already pending.
919            return;
920        }
921
922        lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
923    } else {
924        if (!is_set) {
925            // Writes to GICR_SETLPIR have not effect if the pINTID field
926            // corresponds to an LPI that is not pending.
927            return;
928        }
929
930        lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
931    }
932
933    writeEntryLPI(lpi_id, lpi_pending_entry);
934
935    updateDistributor();
936}
937
938Gicv3::GroupId
939Gicv3Redistributor::getIntGroup(int int_id) const
940{
941    assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
942
943    if (distributor->DS) {
944        if (irqGroup[int_id] == 0) {
945            return Gicv3::G0S;
946        } else {
947            return Gicv3::G1NS;
948        }
949    } else {
950        if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
951            return Gicv3::G0S;
952        } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
953            return Gicv3::G1NS;
954        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
955            return Gicv3::G1S;
956        } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
957            return Gicv3::G1NS;
958        }
959    }
960
961    M5_UNREACHABLE;
962}
963
964void
965Gicv3Redistributor::activateIRQ(uint32_t int_id)
966{
967    irqPending[int_id] = false;
968    irqActive[int_id] = true;
969}
970
971void
972Gicv3Redistributor::deactivateIRQ(uint32_t int_id)
973{
974    irqActive[int_id] = false;
975}
976
977uint32_t
978Gicv3Redistributor::getAffinity() const
979{
980    ThreadContext * tc = gic->getSystem()->getThreadContext(cpuId);
981    uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
982    /*
983     * Aff3 = MPIDR[39:32]
984     * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
985     * Aff2 = MPIDR[23:16]
986     * Aff1 = MPIDR[15:8]
987     * Aff0 = MPIDR[7:0]
988     * affinity = Aff3.Aff2.Aff1.Aff0
989     */
990    uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
991    return affinity;
992}
993
994bool
995Gicv3Redistributor::canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
996{
997    if (peInLowPowerState) {
998        return false;
999    }
1000
1001    if (!distributor->groupEnabled(group)) {
1002        return false;
1003    }
1004
1005    if ((group == Gicv3::G1S) && DPG1S) {
1006        return false;
1007    }
1008
1009    if ((group == Gicv3::G1NS) && DPG1NS) {
1010        return false;
1011    }
1012
1013    if ((group == Gicv3::G0S) && DPG0) {
1014        return false;
1015    }
1016
1017    return true;
1018}
1019
1020void
1021Gicv3Redistributor::serialize(CheckpointOut & cp) const
1022{
1023    SERIALIZE_SCALAR(peInLowPowerState);
1024    SERIALIZE_CONTAINER(irqGroup);
1025    SERIALIZE_CONTAINER(irqEnabled);
1026    SERIALIZE_CONTAINER(irqPending);
1027    SERIALIZE_CONTAINER(irqActive);
1028    SERIALIZE_CONTAINER(irqPriority);
1029    SERIALIZE_CONTAINER(irqConfig);
1030    SERIALIZE_CONTAINER(irqGrpmod);
1031    SERIALIZE_CONTAINER(irqNsacr);
1032    SERIALIZE_SCALAR(DPG1S);
1033    SERIALIZE_SCALAR(DPG1NS);
1034    SERIALIZE_SCALAR(DPG0);
1035    SERIALIZE_SCALAR(EnableLPIs);
1036    SERIALIZE_SCALAR(lpiConfigurationTablePtr);
1037    SERIALIZE_SCALAR(lpiIDBits);
1038    SERIALIZE_SCALAR(lpiPendingTablePtr);
1039}
1040
1041void
1042Gicv3Redistributor::unserialize(CheckpointIn & cp)
1043{
1044    UNSERIALIZE_SCALAR(peInLowPowerState);
1045    UNSERIALIZE_CONTAINER(irqGroup);
1046    UNSERIALIZE_CONTAINER(irqEnabled);
1047    UNSERIALIZE_CONTAINER(irqPending);
1048    UNSERIALIZE_CONTAINER(irqActive);
1049    UNSERIALIZE_CONTAINER(irqPriority);
1050    UNSERIALIZE_CONTAINER(irqConfig);
1051    UNSERIALIZE_CONTAINER(irqGrpmod);
1052    UNSERIALIZE_CONTAINER(irqNsacr);
1053    UNSERIALIZE_SCALAR(DPG1S);
1054    UNSERIALIZE_SCALAR(DPG1NS);
1055    UNSERIALIZE_SCALAR(DPG0);
1056    UNSERIALIZE_SCALAR(EnableLPIs);
1057    UNSERIALIZE_SCALAR(lpiConfigurationTablePtr);
1058    UNSERIALIZE_SCALAR(lpiIDBits);
1059    UNSERIALIZE_SCALAR(lpiPendingTablePtr);
1060}
1061