gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gic_v3_redistributor.cc
Go to the documentation of this file.
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 
44 
45 #include "arch/arm/utility.hh"
46 #include "debug/GIC.hh"
50 
51 const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
52  SGI_base + 0x0420);
53 
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 
80 void
82 {
85 
87 }
88 
89 uint64_t
90 Gicv3Redistributor::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) {
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
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 
384 void
385 Gicv3Redistributor::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 
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 
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_ICFGR0: // SGI Configuration Register
583  // WI
584  return;
585  case GICR_ICFGR1: { // PPI Configuration Register
586  int first_intid = Gicv3::SGI_MAX;
587 
588  for (int i = 0, int_id = first_intid; i < 8 * size;
589  i = i + 2, int_id++) {
590  if (!distributor->DS && !is_secure_access) {
591  // RAZ/WI for non-secure accesses for secure interrupts
592  if (getIntGroup(int_id) != Gicv3::G1NS) {
593  continue;
594  }
595  }
596 
597  irqConfig[int_id] = data & (0x2 << i) ?
600  DPRINTF(GIC, "Gicv3Redistributor::write(): "
601  "int_id %d (PPI) config %d\n",
602  int_id, irqConfig[int_id]);
603  }
604 
605  break;
606  }
607 
608  case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
609  if (distributor->DS) {
610  // RAZ/WI if secutiry disabled
611  } else {
612  for (int int_id = 0; int_id < 8 * size; int_id++) {
613  if (!is_secure_access) {
614  // RAZ/WI for non-secure accesses
615  continue;
616  }
617 
618  irqGrpmod[int_id] = data & (1 << int_id);
619  }
620  }
621 
622  break;
623  }
624 
625  case GICR_NSACR: { // Non-secure Access Control Register
626  if (distributor->DS) {
627  // RAZ/WI
628  } else {
629  if (!is_secure_access) {
630  // RAZ/WI
631  } else {
632  for (int i = 0, int_id = 0; i < 8 * size;
633  i = i + 2, int_id++) {
634  irqNsacr[int_id] = (data >> i) & 0x3;
635  }
636  }
637  }
638 
639  break;
640  }
641 
642  case GICR_SETLPIR: // Set LPI Pending Register
643  setClrLPI(data, true);
644  break;
645 
646  case GICR_CLRLPIR: // Clear LPI Pending Register
647  setClrLPI(data, false);
648  break;
649 
650  case GICR_PROPBASER: { // Redistributor Properties Base Address Register
651  // OuterCache, bits [58:56]
652  // 000 Memory type defined in InnerCache field
653  // Physical_Address, bits [51:12]
654  // Bits [51:12] of the physical address containing the LPI
655  // Configuration table
656  // Shareability, bits [11:10]
657  // 00 Non-shareable
658  // InnerCache, bits [9:7]
659  // 000 Device-nGnRnE
660  // IDbits, bits [4:0]
661  // limited by GICD_TYPER.IDbits (= 0xf)
662  lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
663  lpiIDBits = data & 0x1f;
664 
665  // 0xf here matches the value of GICD_TYPER.IDbits.
666  // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
667  // value
668  if (lpiIDBits > 0xf) {
669  lpiIDBits = 0xf;
670  }
671 
672  break;
673  }
674 
675  // Redistributor LPI Pending Table Base Address Register
676  case GICR_PENDBASER:
677  // PTZ, bit [62]
678  // Pending Table Zero
679  // OuterCache, bits [58:56]
680  // 000 Memory type defined in InnerCache field
681  // Physical_Address, bits [51:16]
682  // Bits [51:16] of the physical address containing the LPI Pending
683  // table
684  // Shareability, bits [11:10]
685  // 00 Non-shareable
686  // InnerCache, bits [9:7]
687  // 000 Device-nGnRnE
688  lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
689  break;
690 
691  case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
692  // Do nothing: no caching supported
693  break;
694  }
695 
696  case GICR_INVALLR: { // Redistributor Invalidate All Register
697  // Do nothing: no caching supported
698  break;
699  }
700 
701  default:
702  panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
703  break;
704  }
705 }
706 
707 void
709 {
710  assert((int_id >= Gicv3::SGI_MAX) &&
711  (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
712  irqPending[int_id] = true;
713  DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
714  "int_id %d (PPI) pending bit set\n", int_id);
716 }
717 
718 void
719 Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
720 {
721  assert(int_id < Gicv3::SGI_MAX);
722  Gicv3::GroupId int_group = getIntGroup(int_id);
723 
724  bool forward = false;
725 
726  if (ns) {
727  // Non-Secure EL1 and EL2 access
728  int nsaccess = irqNsacr[int_id];
729  if (int_group == Gicv3::G0S) {
730 
731  forward = distributor->DS || (nsaccess >= 1);
732 
733  } else if (int_group == Gicv3::G1S) {
734  forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
735  nsaccess == 2);
736  } else {
737  // G1NS
738  forward = group == Gicv3::G1NS;
739  }
740  } else {
741  // Secure EL1 and EL3 access
742  forward = (group == int_group) ||
743  (group == Gicv3::G1S && int_group == Gicv3::G0S &&
744  distributor->DS);
745  }
746 
747  if (!forward) return;
748 
749  irqPending[int_id] = true;
750  DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
751  "int_id %d (SGI) pending bit set\n", int_id);
753 }
754 
756 Gicv3Redistributor::intStatus(uint32_t int_id) const
757 {
758  assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
759 
760  if (irqPending[int_id]) {
761  if (irqActive[int_id]) {
763  }
764 
765  return Gicv3::INT_PENDING;
766  } else if (irqActive[int_id]) {
767  return Gicv3::INT_ACTIVE;
768  } else {
769  return Gicv3::INT_INACTIVE;
770  }
771 }
772 
773 void
775 {
776  distributor->update();
777 }
778 
779 /*
780  * Recalculate the highest priority pending interrupt after a
781  * change to redistributor state.
782  */
783 void
785 {
786  for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
787  Gicv3::GroupId int_group = getIntGroup(int_id);
788  bool group_enabled = distributor->groupEnabled(int_group);
789 
790  if (irqPending[int_id] && irqEnabled[int_id] &&
791  !irqActive[int_id] && group_enabled) {
792  if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
793  /*
794  * Multiple pending ints with same priority.
795  * Implementation choice which one to signal.
796  * Our implementation selects the one with the lower id.
797  */
798  (irqPriority[int_id] == cpuInterface->hppi.prio &&
799  int_id < cpuInterface->hppi.intid)) {
800  cpuInterface->hppi.intid = int_id;
801  cpuInterface->hppi.prio = irqPriority[int_id];
802  cpuInterface->hppi.group = int_group;
803  }
804  }
805  }
806 
807  // Check LPIs
808  if (EnableLPIs) {
809 
810  const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
811  const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
812 
813  uint8_t lpi_pending_table[largest_lpi_id / 8];
814  uint8_t lpi_config_table[number_lpis];
815 
817  lpi_pending_table,
818  sizeof(lpi_pending_table));
819 
821  lpi_config_table,
822  sizeof(lpi_config_table));
823 
824  for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
825  lpi_id++) {
826  uint32_t lpi_pending_entry_byte = lpi_id / 8;
827  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
828  bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
829  1 << lpi_pending_entry_bit_position;
830  uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
831 
832  LPIConfigurationTableEntry config_entry =
833  lpi_config_table[lpi_configuration_entry_index];
834 
835  bool lpi_is_enable = config_entry.enable;
836 
837  // LPIs are always Non-secure Group 1 interrupts,
838  // in a system where two Security states are enabled.
839  Gicv3::GroupId lpi_group = Gicv3::G1NS;
840  bool group_enabled = distributor->groupEnabled(lpi_group);
841 
842  if (lpi_is_pending && lpi_is_enable && group_enabled) {
843  uint8_t lpi_priority = config_entry.priority << 2;
844 
845  if ((lpi_priority < cpuInterface->hppi.prio) ||
846  (lpi_priority == cpuInterface->hppi.prio &&
847  lpi_id < cpuInterface->hppi.intid)) {
848  cpuInterface->hppi.intid = lpi_id;
849  cpuInterface->hppi.prio = lpi_priority;
850  cpuInterface->hppi.group = lpi_group;
851  }
852  }
853  }
854  }
855 
856  cpuInterface->update();
857 }
858 
859 uint8_t
861 {
862  Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
863 
864  uint8_t lpi_pending_entry;
865  memProxy->readBlob(lpi_pending_entry_ptr,
866  &lpi_pending_entry,
867  sizeof(lpi_pending_entry));
868 
869  return lpi_pending_entry;
870 }
871 
872 void
873 Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
874 {
875  Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
876 
877  memProxy->writeBlob(lpi_pending_entry_ptr,
878  &lpi_pending_entry,
879  sizeof(lpi_pending_entry));
880 }
881 
882 bool
884 {
885  // Fetch the LPI pending entry from memory
886  uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
887 
888  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
889  bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
890 
891  return is_set;
892 }
893 
894 void
896 {
897  if (!EnableLPIs) {
898  // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
899  // GICR_CTLR.EnableLPIs == 0.
900  return;
901  }
902 
903  uint32_t lpi_id = data & 0xffffffff;
904  uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
905 
906  if (lpi_id > largest_lpi_id) {
907  // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
908  // pINTID value specifies an unimplemented LPI.
909  return;
910  }
911 
912  // Fetch the LPI pending entry from memory
913  uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
914 
915  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
916  bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
917 
918  if (set) {
919  if (is_set) {
920  // Writes to GICR_SETLPIR have not effect if the pINTID field
921  // corresponds to an LPI that is already pending.
922  return;
923  }
924 
925  lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
926  } else {
927  if (!is_set) {
928  // Writes to GICR_SETLPIR have not effect if the pINTID field
929  // corresponds to an LPI that is not pending.
930  return;
931  }
932 
933  lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
934 
935  // Remove the pending state from the cpu interface
936  cpuInterface->resetHppi(lpi_id);
937  }
938 
939  writeEntryLPI(lpi_id, lpi_pending_entry);
940 
942 }
943 
946 {
947  assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
948 
949  if (distributor->DS) {
950  if (irqGroup[int_id] == 0) {
951  return Gicv3::G0S;
952  } else {
953  return Gicv3::G1NS;
954  }
955  } else {
956  if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
957  return Gicv3::G0S;
958  } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
959  return Gicv3::G1NS;
960  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
961  return Gicv3::G1S;
962  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
963  return Gicv3::G1NS;
964  }
965  }
966 
967  M5_UNREACHABLE;
968 }
969 
970 void
972 {
973  irqPending[int_id] = false;
974  irqActive[int_id] = true;
975 }
976 
977 void
979 {
980  irqActive[int_id] = false;
981 }
982 
983 uint32_t
985 {
987  uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
988  /*
989  * Aff3 = MPIDR[39:32]
990  * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
991  * Aff2 = MPIDR[23:16]
992  * Aff1 = MPIDR[15:8]
993  * Aff0 = MPIDR[7:0]
994  * affinity = Aff3.Aff2.Aff1.Aff0
995  */
996  uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
997  return affinity;
998 }
999 
1000 bool
1002 {
1003  if (peInLowPowerState) {
1004  return false;
1005  }
1006 
1007  if (!distributor->groupEnabled(group)) {
1008  return false;
1009  }
1010 
1011  if ((group == Gicv3::G1S) && DPG1S) {
1012  return false;
1013  }
1014 
1015  if ((group == Gicv3::G1NS) && DPG1NS) {
1016  return false;
1017  }
1018 
1019  if ((group == Gicv3::G0S) && DPG0) {
1020  return false;
1021  }
1022 
1023  return true;
1024 }
1025 
1026 void
1028 {
1045 }
1046 
1047 void
1049 {
1066 }
uint8_t readEntryLPI(uint32_t intid)
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
void deactivateIRQ(uint32_t int_id)
#define DPRINTF(x,...)
Definition: trace.hh:229
static const uint32_t GICR_CTLR_DPG0
static const int PPI_MAX
Definition: gic_v3.hh:80
Definition: gic_v3.hh:54
Bitfield< 7 > i
bool isPendingLPI(uint32_t intid)
static const AddrRange GICR_IPRIORITYR
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:406
ip6_addr_t addr
Definition: inet.hh:335
Gicv3CPUInterface * cpuInterface
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::vector< Gicv3::IntTriggerType > irqConfig
std::vector< uint8_t > irqPriority
Definition: cprintf.cc:42
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
void resetHppi(uint32_t intid)
std::vector< bool > irqEnabled
ThreadContext is the external interface to all thread state for anything outside of the CPU...
RegVal getMPIDR(ArmSystem *arm_sys, ThreadContext *tc)
This helper function is returing the value of MPIDR_EL1.
Definition: utility.cc:253
ThreadContext * getThreadContext(ContextID tid) const
Definition: system.hh:194
static const int SGI_MAX
Definition: gic_v3.hh:78
std::vector< bool > irqPending
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition: system.hh:218
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:72
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:645
Bitfield< 0 > ns
void sendPPInt(uint32_t int_id)
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:664
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void writeEntryLPI(uint32_t intid, uint8_t lpi_entry)
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:189
std::vector< bool > irqActive
std::vector< uint8_t > irqGroup
void activateIRQ(uint32_t int_id)
static const uint32_t GICR_WAKER_ChildrenAsleep
void setClrLPI(uint64_t data, bool set)
unsigned numContexts() const
Definition: system.hh:206
GroupId
Definition: gic_v3.hh:91
Gicv3::IntStatus intStatus(uint32_t int_id) const
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:667
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Gicv3CPUInterface * getCPUInterface(int cpu_id) const
Definition: gic_v3.hh:136
Gicv3Distributor * distributor
std::vector< uint8_t > irqGrpmod
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:179
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
static const uint32_t SMALLEST_LPI_ID
IntStatus
Definition: gic_v3.hh:83
static const uint32_t GICR_CTLR_DPG1S
std::ostream CheckpointOut
Definition: serialize.hh:68
TranslatingPortProxy Object Declaration for FS.
Bitfield< 27, 24 > gic
std::vector< uint8_t > irqNsacr
bool groupEnabled(Gicv3::GroupId group) const
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:297
static const uint32_t GICR_WAKER_ProcessorSleep
uint32_t getAffinity() const
Gicv3::GroupId getIntGroup(int int_id) const
T bits(T val, int first, int last)
Extract the bitfield from position &#39;first&#39; to &#39;last&#39; (inclusive) from &#39;val&#39; and right justify it...
Definition: bitfield.hh:72
static const uint32_t GICR_CTLR_DPG1NS
ArmSystem * getSystem() const
Definition: base_gic.hh:106
const char data[]
void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
uint64_t read(Addr addr, size_t size, bool is_secure_access)
void disable()
Definition: trace.cc:102
Gicv3Redistributor(Gicv3 *gic, uint32_t cpu_id)
Gicv3Distributor * getDistributor() const
Definition: gic_v3.hh:143

Generated on Fri Feb 28 2020 16:27:00 for gem5 by doxygen 1.8.13