gem5  v20.0.0.2
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 
42 
43 #include "arch/arm/utility.hh"
44 #include "debug/GIC.hh"
47 
48 const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
49  SGI_base + 0x0420);
50 
52  : gic(gic),
53  distributor(nullptr),
54  cpuInterface(nullptr),
55  cpuId(cpu_id),
56  memProxy(nullptr),
57  peInLowPowerState(true),
58  irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
59  irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
60  irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
61  irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
62  irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
63  irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX, Gicv3::INT_EDGE_TRIGGERED),
64  irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
65  irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
66  DPG1S(false),
67  DPG1NS(false),
68  DPG0(false),
69  EnableLPIs(false),
70  lpiConfigurationTablePtr(0),
71  lpiIDBits(0),
72  lpiPendingTablePtr(0),
73  addrRangeSize(gic->params()->gicv4 ? 0x40000 : 0x20000)
74 {
75 }
76 
77 void
79 {
82 
84 }
85 
86 uint64_t
87 Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
88 {
89  if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
90  uint64_t value = 0;
91  int first_intid = addr - GICR_IPRIORITYR.start();
92 
93  for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
94  uint8_t prio = irqPriority[int_id];
95 
96  if (!distributor->DS && !is_secure_access) {
97  if (getIntGroup(int_id) != Gicv3::G1NS) {
98  // RAZ/WI for non-secure accesses for secure interrupts
99  continue;
100  } else {
101  // NS view
102  prio = (prio << 1) & 0xff;
103  }
104  }
105 
106  value |= prio << (i * 8);
107  }
108 
109  return value;
110  }
111 
112  switch (addr) {
113  case GICR_CTLR: { // Control Register
114  uint64_t value = 0;
115 
116  if (DPG1S) {
117  value |= GICR_CTLR_DPG1S;
118  }
119 
120  if (DPG1NS) {
121  value |= GICR_CTLR_DPG1NS;
122  }
123 
124  if (DPG0) {
125  value |= GICR_CTLR_DPG0;
126  }
127 
128  if (EnableLPIs) {
129  value |= GICR_CTLR_ENABLE_LPIS;
130  }
131 
132  return value;
133  }
134 
135  case GICR_IIDR: // Implementer Identification Register
136  //return 0x43b; // r0p0 GIC-500
137  return 0;
138 
139  case GICR_TYPER: { // Type Register
140  /*
141  * Affinity_Value [63:32] == X
142  * (The identity of the PE associated with this Redistributor)
143  * CommonLPIAff [25:24] == 01
144  * (All Redistributors with the same Aff3 value must share an
145  * LPI Configuration table)
146  * Processor_Number [23:8] == X
147  * (A unique identifier for the PE)
148  * DPGS [5] == 1
149  * (GICR_CTLR.DPG* bits are supported)
150  * Last [4] == X
151  * (This Redistributor is the highest-numbered Redistributor in
152  * a series of contiguous Redistributor pages)
153  * DirectLPI [3] == 1
154  * (direct injection of LPIs supported)
155  * VLPIS [1] == 0
156  * (virtual LPIs not supported)
157  * PLPIS [0] == 1
158  * (physical LPIs supported)
159  */
160  uint64_t affinity = getAffinity();
161  int last = cpuId == (gic->getSystem()->numContexts() - 1);
162  return (affinity << 32) | (1 << 24) | (cpuId << 8) |
163  (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
164  }
165 
166  case GICR_WAKER: // Wake Register
167  if (!distributor->DS && !is_secure_access) {
168  // RAZ/WI for non-secure accesses
169  return 0;
170  }
171 
172  if (peInLowPowerState) {
174  } else {
175  return 0;
176  }
177 
178  case GICR_PIDR0: { // Peripheral ID0 Register
179  return 0x92; // Part number, bits[7:0]
180  }
181 
182  case GICR_PIDR1: { // Peripheral ID1 Register
183  uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
184  uint8_t part_1 = 0x4; // Part number, bits[11:8]
185  return (des_0 << 4) | (part_1 << 0);
186  }
187 
188  case GICR_PIDR2: { // Peripheral ID2 Register
189  uint8_t arch_rev = 0x3; // 0x3 GICv3
190  uint8_t jedec = 0x1; // JEP code
191  uint8_t des_1 = 0x3; // JEP106 identification code, bits[6:4]
192  return (arch_rev << 4) | (jedec << 3) | (des_1 << 0);
193  }
194 
195  case GICR_PIDR3: // Peripheral ID3 Register
196  return 0x0; // Implementation defined
197 
198  case GICR_PIDR4: { // Peripheral ID4 Register
199  uint8_t size = 0x4; // 64 KB software visible page
200  uint8_t des_2 = 0x4; // ARM implementation
201  return (size << 4) | (des_2 << 0);
202  }
203 
204  case GICR_PIDR5: // Peripheral ID5 Register
205  case GICR_PIDR6: // Peripheral ID6 Register
206  case GICR_PIDR7: // Peripheral ID7 Register
207  return 0; // RES0
208 
209  case GICR_IGROUPR0: { // Interrupt Group Register 0
210  uint64_t value = 0;
211 
212  if (!distributor->DS && !is_secure_access) {
213  // RAZ/WI for non-secure accesses
214  return 0;
215  }
216 
217  for (int int_id = 0; int_id < 8 * size; int_id++) {
218  value |= (irqGroup[int_id] << int_id);
219  }
220 
221  return value;
222  }
223 
224  case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
225  case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
226  uint64_t value = 0;
227 
228  for (int int_id = 0; int_id < 8 * size; int_id++) {
229  if (!distributor->DS && !is_secure_access) {
230  // RAZ/WI for non-secure accesses for secure interrupts
231  if (getIntGroup(int_id) != Gicv3::G1NS) {
232  continue;
233  }
234  }
235 
236  if (irqEnabled[int_id]) {
237  value |= (1 << int_id);
238  }
239  }
240 
241  return value;
242  }
243 
244  case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
245  case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
246  uint64_t value = 0;
247 
248  for (int int_id = 0; int_id < 8 * size; int_id++) {
249  if (!distributor->DS && !is_secure_access) {
250  // RAZ/WI for non-secure accesses for secure interrupts
251  if (getIntGroup(int_id) != Gicv3::G1NS) {
252  continue;
253  }
254  }
255 
256  value |= (irqPending[int_id] << int_id);
257  }
258 
259  return value;
260  }
261 
262  case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
263  case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
264  uint64_t value = 0;
265 
266  for (int int_id = 0; int_id < 8 * size; int_id++) {
267  if (!distributor->DS && !is_secure_access) {
268  // RAZ/WI for non-secure accesses for secure interrupts
269  if (getIntGroup(int_id) != Gicv3::G1NS) {
270  continue;
271  }
272  }
273 
274  value |= irqActive[int_id] << int_id;
275  }
276 
277  return value;
278  }
279 
280  case GICR_ICFGR0: // SGI Configuration Register
281  case GICR_ICFGR1: { // PPI Configuration Register
282  uint64_t value = 0;
283  uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
284 
285  for (int i = 0, int_id = first_int_id; i < 32;
286  i = i + 2, int_id++) {
287  if (!distributor->DS && !is_secure_access) {
288  // RAZ/WI for non-secure accesses for secure interrupts
289  if (getIntGroup(int_id) != Gicv3::G1NS) {
290  continue;
291  }
292  }
293 
294  if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
295  value |= (0x2) << i;
296  }
297  }
298 
299  return value;
300  }
301 
302  case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
303  uint64_t value = 0;
304 
305  if (distributor->DS) {
306  value = 0;
307  } else {
308  if (!is_secure_access) {
309  // RAZ/WI for non-secure accesses
310  value = 0;
311  } else {
312  for (int int_id = 0; int_id < 8 * size; int_id++) {
313  value |= irqGrpmod[int_id] << int_id;
314  }
315  }
316  }
317 
318  return value;
319  }
320 
321  case GICR_NSACR: { // Non-secure Access Control Register
322  uint64_t value = 0;
323 
324  if (distributor->DS) {
325  // RAZ/WI
326  value = 0;
327  } else {
328  if (!is_secure_access) {
329  // RAZ/WI
330  value = 0;
331  } else {
332  for (int i = 0, int_id = 0; i < 8 * size;
333  i = i + 2, int_id++) {
334  value |= irqNsacr[int_id] << i;
335  }
336  }
337  }
338 
339  return value;
340  }
341 
342  case GICR_PROPBASER: // Redistributor Properties Base Address Register
343  // OuterCache, bits [58:56]
344  // 000 Memory type defined in InnerCache field
345  // Physical_Address, bits [51:12]
346  // Bits [51:12] of the physical address containing the LPI
347  // Configuration table
348  // Shareability, bits [11:10]
349  // 00 Non-shareable
350  // InnerCache, bits [9:7]
351  // 000 Device-nGnRnE
352  // IDbits, bits [4:0]
353  // limited by GICD_TYPER.IDbits
355 
356  // Redistributor LPI Pending Table Base Address Register
357  case GICR_PENDBASER:
358  // PTZ, bit [62]
359  // Pending Table Zero
360  // OuterCache, bits [58:56]
361  // 000 Memory type defined in InnerCache field
362  // Physical_Address, bits [51:16]
363  // Bits [51:16] of the physical address containing the LPI Pending
364  // table
365  // Shareability, bits [11:10]
366  // 00 Non-shareable
367  // InnerCache, bits [9:7]
368  // 000 Device-nGnRnE
369  return lpiPendingTablePtr;
370 
371  // Redistributor Synchronize Register
372  case GICR_SYNCR:
373  return 0;
374 
375  default:
376  panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
377  break;
378  }
379 }
380 
381 void
382 Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
383  bool is_secure_access)
384 {
385  if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
386  int first_intid = addr - GICR_IPRIORITYR.start();
387 
388  for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
389  uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
390 
391  if (!distributor->DS && !is_secure_access) {
392  if (getIntGroup(int_id) != Gicv3::G1NS) {
393  // RAZ/WI for non-secure accesses for secure interrupts
394  continue;
395  } else {
396  // NS view
397  prio = 0x80 | (prio >> 1);
398  }
399  }
400 
401  irqPriority[int_id] = prio;
402  DPRINTF(GIC, "Gicv3Redistributor::write(): "
403  "int_id %d priority %d\n", int_id, irqPriority[int_id]);
404  }
405 
406  return;
407  }
408 
409  switch (addr) {
410  case GICR_CTLR: {
411  // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
412  EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
413  DPG1S = data & GICR_CTLR_DPG1S;
414  DPG1NS = data & GICR_CTLR_DPG1NS;
415  DPG0 = data & GICR_CTLR_DPG0;
416  break;
417  }
418 
419  case GICR_WAKER: // Wake Register
420  {
421  if (!distributor->DS && !is_secure_access) {
422  // RAZ/WI for non-secure accesses
423  return;
424  }
425 
426  bool pe_was_low_power = peInLowPowerState;
428  if (!pe_was_low_power && peInLowPowerState) {
429  DPRINTF(GIC, "Gicv3Redistributor::write(): "
430  "PE entering in low power state\n");
432  } else if (pe_was_low_power && !peInLowPowerState) {
433  DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
436  }
437  break;
438  }
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  if (peInLowPowerState) {
860  }
861  } else {
862  cpuInterface->update();
863  }
864 }
865 
866 uint8_t
868 {
869  Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
870 
871  uint8_t lpi_pending_entry;
872  memProxy->readBlob(lpi_pending_entry_ptr,
873  &lpi_pending_entry,
874  sizeof(lpi_pending_entry));
875 
876  return lpi_pending_entry;
877 }
878 
879 void
880 Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
881 {
882  Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
883 
884  memProxy->writeBlob(lpi_pending_entry_ptr,
885  &lpi_pending_entry,
886  sizeof(lpi_pending_entry));
887 }
888 
889 bool
891 {
892  // Fetch the LPI pending entry from memory
893  uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
894 
895  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
896  bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
897 
898  return is_set;
899 }
900 
901 void
903 {
904  if (!EnableLPIs) {
905  // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
906  // GICR_CTLR.EnableLPIs == 0.
907  return;
908  }
909 
910  uint32_t lpi_id = data & 0xffffffff;
911  uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
912 
913  if (lpi_id > largest_lpi_id) {
914  // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
915  // pINTID value specifies an unimplemented LPI.
916  return;
917  }
918 
919  // Fetch the LPI pending entry from memory
920  uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
921 
922  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
923  bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
924 
925  if (set) {
926  if (is_set) {
927  // Writes to GICR_SETLPIR have not effect if the pINTID field
928  // corresponds to an LPI that is already pending.
929  return;
930  }
931 
932  lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
933  } else {
934  if (!is_set) {
935  // Writes to GICR_SETLPIR have not effect if the pINTID field
936  // corresponds to an LPI that is not pending.
937  return;
938  }
939 
940  lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
941 
942  // Remove the pending state from the cpu interface
943  cpuInterface->resetHppi(lpi_id);
944  }
945 
946  writeEntryLPI(lpi_id, lpi_pending_entry);
947 
949 }
950 
953 {
954  assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
955 
956  if (distributor->DS) {
957  if (irqGroup[int_id] == 0) {
958  return Gicv3::G0S;
959  } else {
960  return Gicv3::G1NS;
961  }
962  } else {
963  if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
964  return Gicv3::G0S;
965  } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
966  return Gicv3::G1NS;
967  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
968  return Gicv3::G1S;
969  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
970  return Gicv3::G1NS;
971  }
972  }
973 
974  M5_UNREACHABLE;
975 }
976 
977 void
979 {
980  irqPending[int_id] = false;
981  irqActive[int_id] = true;
982 }
983 
984 void
986 {
987  irqActive[int_id] = false;
988 }
989 
990 uint32_t
992 {
994  uint64_t mpidr = getMPIDR(gic->getSystem(), tc);
995  /*
996  * Aff3 = MPIDR[39:32]
997  * (Note getMPIDR() returns uint32_t so Aff3 is always 0...)
998  * Aff2 = MPIDR[23:16]
999  * Aff1 = MPIDR[15:8]
1000  * Aff0 = MPIDR[7:0]
1001  * affinity = Aff3.Aff2.Aff1.Aff0
1002  */
1003  uint64_t affinity = ((mpidr & 0xff00000000) >> 8) | (mpidr & (0xffffff));
1004  return affinity;
1005 }
1006 
1007 bool
1009 {
1010  if (peInLowPowerState) {
1011  return false;
1012  }
1013 
1014  if (!distributor->groupEnabled(group)) {
1015  return false;
1016  }
1017 
1018  if ((group == Gicv3::G1S) && DPG1S) {
1019  return false;
1020  }
1021 
1022  if ((group == Gicv3::G1NS) && DPG1NS) {
1023  return false;
1024  }
1025 
1026  if ((group == Gicv3::G0S) && DPG0) {
1027  return false;
1028  }
1029 
1030  return true;
1031 }
1032 
1033 void
1035 {
1052 }
1053 
1054 void
1056 {
1073 }
uint8_t readEntryLPI(uint32_t intid)
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:163
void deactivateIRQ(uint32_t int_id)
#define DPRINTF(x,...)
Definition: trace.hh:222
static const uint32_t GICR_CTLR_DPG0
static const int PPI_MAX
Definition: gic_v3.hh:78
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:829
Definition: gic_v3.hh:52
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:402
ip6_addr_t addr
Definition: inet.hh:330
Gicv3CPUInterface * cpuInterface
void serialize(CheckpointOut &cp) const override
Serialize an object.
std::vector< Gicv3::IntTriggerType > irqConfig
std::vector< uint8_t > irqPriority
Definition: cprintf.cc:40
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 returning the value of MPIDR_EL1.
Definition: utility.cc:232
ThreadContext * getThreadContext(ContextID tid) const
Definition: system.hh:186
static const int SGI_MAX
Definition: gic_v3.hh:76
std::vector< bool > irqPending
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition: system.hh:210
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:68
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:770
Bitfield< 0 > ns
void sendPPInt(uint32_t int_id)
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:187
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:198
GroupId
Definition: gic_v3.hh:89
Gicv3::IntStatus intStatus(uint32_t int_id) const
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:140
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:177
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:763
static const uint32_t SMALLEST_LPI_ID
IntStatus
Definition: gic_v3.hh:81
static const uint32_t GICR_CTLR_DPG1S
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:821
std::ostream CheckpointOut
Definition: serialize.hh:63
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:293
bool havePendingInterrupts(void) const
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:71
static const uint32_t GICR_CTLR_DPG1NS
ArmSystem * getSystem() const
Definition: base_gic.hh:104
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:98
Gicv3Redistributor(Gicv3 *gic, uint32_t cpu_id)
Gicv3Distributor * getDistributor() const
Definition: gic_v3.hh:143

Generated on Mon Jun 8 2020 15:45:09 for gem5 by doxygen 1.8.13