gem5  v22.1.0.0
gic_v3_redistributor.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019-2022 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 "base/compiler.hh"
45 #include "debug/GIC.hh"
48 
49 namespace gem5
50 {
51 
52 using namespace ArmISA;
53 
54 const AddrRange Gicv3Redistributor::GICR_IPRIORITYR(SGI_base + 0x0400,
55  SGI_base + 0x0420);
56 
58  : gic(gic),
59  distributor(nullptr),
60  cpuInterface(nullptr),
61  cpuId(cpu_id),
62  memProxy(nullptr),
63  peInLowPowerState(true),
64  irqGroup(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
65  irqEnabled(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
66  irqPending(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
67  irqPendingIspendr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
68  irqActive(Gicv3::SGI_MAX + Gicv3::PPI_MAX, false),
69  irqPriority(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
70  irqConfig(Gicv3::SGI_MAX + Gicv3::PPI_MAX, Gicv3::INT_EDGE_TRIGGERED),
71  irqGrpmod(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
72  irqNsacr(Gicv3::SGI_MAX + Gicv3::PPI_MAX, 0),
73  DPG1S(false),
74  DPG1NS(false),
75  DPG0(false),
76  EnableLPIs(false),
77  lpiConfigurationTablePtr(0),
78  lpiIDBits(0),
79  lpiPendingTablePtr(0),
80  addrRangeSize(gic->params().gicv4 ? 0x40000 : 0x20000)
81 {
82 }
83 
84 void
86 {
89 
91 }
92 
93 uint64_t
94 Gicv3Redistributor::read(Addr addr, size_t size, bool is_secure_access)
95 {
96  if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
97  uint64_t value = 0;
98  int first_intid = addr - GICR_IPRIORITYR.start();
99 
100  for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
101  uint8_t prio = irqPriority[int_id];
102 
103  if (!distributor->DS && !is_secure_access) {
104  if (getIntGroup(int_id) != Gicv3::G1NS) {
105  // RAZ/WI for non-secure accesses for secure interrupts
106  continue;
107  } else {
108  // NS view
109  prio = (prio << 1) & 0xff;
110  }
111  }
112 
113  value |= prio << (i * 8);
114  }
115 
116  return value;
117  }
118 
119  switch (addr) {
120  case GICR_CTLR: { // Control Register
121  uint64_t value = 0;
122 
123  if (DPG1S) {
124  value |= GICR_CTLR_DPG1S;
125  }
126 
127  if (DPG1NS) {
128  value |= GICR_CTLR_DPG1NS;
129  }
130 
131  if (DPG0) {
132  value |= GICR_CTLR_DPG0;
133  }
134 
135  if (EnableLPIs) {
136  value |= GICR_CTLR_ENABLE_LPIS;
137  }
138 
139  return value;
140  }
141 
142  case GICR_IIDR: // Implementer Identification Register
143  //return 0x43b; // r0p0 GIC-500
144  return 0;
145 
146  case GICR_TYPER: { // Type Register
147  /*
148  * Affinity_Value [63:32] == X
149  * (The identity of the PE associated with this Redistributor)
150  * CommonLPIAff [25:24] == 01
151  * (All Redistributors with the same Aff3 value must share an
152  * LPI Configuration table)
153  * Processor_Number [23:8] == X
154  * (A unique identifier for the PE)
155  * DPGS [5] == 1
156  * (GICR_CTLR.DPG* bits are supported)
157  * Last [4] == X
158  * (This Redistributor is the highest-numbered Redistributor in
159  * a series of contiguous Redistributor pages)
160  * DirectLPI [3] == 1
161  * (direct injection of LPIs supported)
162  * VLPIS [1] == 0
163  * (virtual LPIs not supported)
164  * PLPIS [0] == 1
165  * (physical LPIs supported)
166  */
167  uint64_t affinity = getAffinity();
168  int last = cpuId == (gic->getSystem()->threads.size() - 1);
169  return (affinity << 32) | (1 << 24) | (cpuId << 8) |
170  (1 << 5) | (last << 4) | (1 << 3) | (1 << 0);
171  }
172 
173  case GICR_WAKER: // Wake Register
174  if (!distributor->DS && !is_secure_access) {
175  // RAZ/WI for non-secure accesses
176  return 0;
177  }
178 
179  if (peInLowPowerState) {
181  } else {
182  return 0;
183  }
184 
185  case GICR_PIDR0: { // Peripheral ID0 Register
186  return 0x92; // Part number, bits[7:0]
187  }
188 
189  case GICR_PIDR1: { // Peripheral ID1 Register
190  uint8_t des_0 = 0xB; // JEP106 identification code, bits[3:0]
191  uint8_t part_1 = 0x4; // Part number, bits[11:8]
192  return (des_0 << 4) | (part_1 << 0);
193  }
194 
195  case GICR_PIDR2: { // Peripheral ID2 Register
196  return gic->getDistributor()->gicdPidr2;
197  }
198 
199  case GICR_PIDR3: // Peripheral ID3 Register
200  return 0x0; // Implementation defined
201 
202  case GICR_PIDR4: { // Peripheral ID4 Register
203  uint8_t size = 0x4; // 64 KB software visible page
204  uint8_t des_2 = 0x4; // ARM implementation
205  return (size << 4) | (des_2 << 0);
206  }
207 
208  case GICR_PIDR5: // Peripheral ID5 Register
209  case GICR_PIDR6: // Peripheral ID6 Register
210  case GICR_PIDR7: // Peripheral ID7 Register
211  return 0; // RES0
212 
213  case GICR_IGROUPR0: { // Interrupt Group Register 0
214  uint64_t value = 0;
215 
216  if (!distributor->DS && !is_secure_access) {
217  // RAZ/WI for non-secure accesses
218  return 0;
219  }
220 
221  for (int int_id = 0; int_id < 8 * size; int_id++) {
222  value |= (irqGroup[int_id] << int_id);
223  }
224 
225  return value;
226  }
227 
228  case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
229  case GICR_ICENABLER0: { // Interrupt Clear-Enable Register 0
230  uint64_t value = 0;
231 
232  for (int int_id = 0; int_id < 8 * size; int_id++) {
233  if (!distributor->DS && !is_secure_access) {
234  // RAZ/WI for non-secure accesses for secure interrupts
235  if (getIntGroup(int_id) != Gicv3::G1NS) {
236  continue;
237  }
238  }
239 
240  if (irqEnabled[int_id]) {
241  value |= (1 << int_id);
242  }
243  }
244 
245  return value;
246  }
247 
248  case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
249  case GICR_ICPENDR0: { // Interrupt Clear-Pending Register 0
250  uint64_t value = 0;
251 
252  for (int int_id = 0; int_id < 8 * size; int_id++) {
253  if (!distributor->DS && !is_secure_access) {
254  // RAZ/WI for non-secure accesses for secure interrupts
255  if (getIntGroup(int_id) != Gicv3::G1NS) {
256  continue;
257  }
258  }
259 
260  value |= (irqPending[int_id] << int_id);
261  }
262 
263  return value;
264  }
265 
266  case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
267  case GICR_ICACTIVER0: { // Interrupt Clear-Active Register 0
268  uint64_t value = 0;
269 
270  for (int int_id = 0; int_id < 8 * size; int_id++) {
271  if (!distributor->DS && !is_secure_access) {
272  // RAZ/WI for non-secure accesses for secure interrupts
273  if (getIntGroup(int_id) != Gicv3::G1NS) {
274  continue;
275  }
276  }
277 
278  value |= irqActive[int_id] << int_id;
279  }
280 
281  return value;
282  }
283 
284  case GICR_ICFGR0: // SGI Configuration Register
285  case GICR_ICFGR1: { // PPI Configuration Register
286  uint64_t value = 0;
287  uint32_t first_int_id = addr == GICR_ICFGR0 ? 0 : Gicv3::SGI_MAX;
288 
289  for (int i = 0, int_id = first_int_id; i < 32;
290  i = i + 2, int_id++) {
291  if (!distributor->DS && !is_secure_access) {
292  // RAZ/WI for non-secure accesses for secure interrupts
293  if (getIntGroup(int_id) != Gicv3::G1NS) {
294  continue;
295  }
296  }
297 
298  if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
299  value |= (0x2) << i;
300  }
301  }
302 
303  return value;
304  }
305 
306  case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
307  uint64_t value = 0;
308 
309  if (distributor->DS) {
310  value = 0;
311  } else {
312  if (!is_secure_access) {
313  // RAZ/WI for non-secure accesses
314  value = 0;
315  } else {
316  for (int int_id = 0; int_id < 8 * size; int_id++) {
317  value |= irqGrpmod[int_id] << int_id;
318  }
319  }
320  }
321 
322  return value;
323  }
324 
325  case GICR_NSACR: { // Non-secure Access Control Register
326  uint64_t value = 0;
327 
328  if (distributor->DS) {
329  // RAZ/WI
330  value = 0;
331  } else {
332  if (!is_secure_access) {
333  // RAZ/WI
334  value = 0;
335  } else {
336  for (int i = 0, int_id = 0; i < 8 * size;
337  i = i + 2, int_id++) {
338  value |= irqNsacr[int_id] << i;
339  }
340  }
341  }
342 
343  return value;
344  }
345 
346  case GICR_PROPBASER: // Redistributor Properties Base Address Register
347  // OuterCache, bits [58:56]
348  // 000 Memory type defined in InnerCache field
349  // Physical_Address, bits [51:12]
350  // Bits [51:12] of the physical address containing the LPI
351  // Configuration table
352  // Shareability, bits [11:10]
353  // 00 Non-shareable
354  // InnerCache, bits [9:7]
355  // 000 Device-nGnRnE
356  // IDbits, bits [4:0]
357  // limited by GICD_TYPER.IDbits
359 
360  // Redistributor LPI Pending Table Base Address Register
361  case GICR_PENDBASER:
362  // PTZ, bit [62]
363  // Pending Table Zero
364  // OuterCache, bits [58:56]
365  // 000 Memory type defined in InnerCache field
366  // Physical_Address, bits [51:16]
367  // Bits [51:16] of the physical address containing the LPI Pending
368  // table
369  // Shareability, bits [11:10]
370  // 00 Non-shareable
371  // InnerCache, bits [9:7]
372  // 000 Device-nGnRnE
373  return lpiPendingTablePtr;
374 
375  // Redistributor Synchronize Register
376  case GICR_SYNCR:
377  return 0;
378 
379  default:
380  panic("Gicv3Redistributor::read(): invalid offset %#x\n", addr);
381  break;
382  }
383 }
384 
385 void
386 Gicv3Redistributor::write(Addr addr, uint64_t data, size_t size,
387  bool is_secure_access)
388 {
389  if (GICR_IPRIORITYR.contains(addr)) { // Interrupt Priority Registers
390  int first_intid = addr - GICR_IPRIORITYR.start();
391 
392  for (int i = 0, int_id = first_intid; i < size; i++, int_id++) {
393  uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
394 
395  if (!distributor->DS && !is_secure_access) {
396  if (getIntGroup(int_id) != Gicv3::G1NS) {
397  // RAZ/WI for non-secure accesses for secure interrupts
398  continue;
399  } else {
400  // NS view
401  prio = 0x80 | (prio >> 1);
402  }
403  }
404 
405  irqPriority[int_id] = prio;
406  DPRINTF(GIC, "Gicv3Redistributor::write(): "
407  "int_id %d priority %d\n", int_id, irqPriority[int_id]);
408  }
409 
410  return;
411  }
412 
413  switch (addr) {
414  case GICR_CTLR: {
415  // GICR_TYPER.LPIS is 0 so EnableLPIs is RES0
416  EnableLPIs = data & GICR_CTLR_ENABLE_LPIS;
420  break;
421  }
422 
423  case GICR_WAKER: // Wake Register
424  {
425  if (!distributor->DS && !is_secure_access) {
426  // RAZ/WI for non-secure accesses
427  return;
428  }
429 
430  bool pe_was_low_power = peInLowPowerState;
432  if (!pe_was_low_power && peInLowPowerState) {
433  DPRINTF(GIC, "Gicv3Redistributor::write(): "
434  "PE entering in low power state\n");
436  } else if (pe_was_low_power && !peInLowPowerState) {
437  DPRINTF(GIC, "Gicv3Redistributor::write(): powering up PE\n");
440  }
441  break;
442  }
443 
444  case GICR_IGROUPR0: // Interrupt Group Register 0
445  if (!distributor->DS && !is_secure_access) {
446  // RAZ/WI for non-secure accesses
447  return;
448  }
449 
450  for (int int_id = 0; int_id < 8 * size; int_id++) {
451  irqGroup[int_id] = data & (1 << int_id) ? 1 : 0;
452  DPRINTF(GIC, "Gicv3Redistributor::write(): "
453  "int_id %d group %d\n", int_id, irqGroup[int_id]);
454  }
455 
456  break;
457 
458  case GICR_ISENABLER0: // Interrupt Set-Enable Register 0
459  for (int int_id = 0; int_id < 8 * size; int_id++) {
460  if (!distributor->DS && !is_secure_access) {
461  // RAZ/WI for non-secure accesses for secure interrupts
462  if (getIntGroup(int_id) != Gicv3::G1NS) {
463  continue;
464  }
465  }
466 
467  bool enable = data & (1 << int_id) ? 1 : 0;
468 
469  if (enable) {
470  irqEnabled[int_id] = true;
471  }
472 
473  DPRINTF(GIC, "Gicv3Redistributor::write(): "
474  "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
475  }
476 
477  break;
478 
479  case GICR_ICENABLER0: // Interrupt Clear-Enable Register 0
480  for (int int_id = 0; int_id < 8 * size; int_id++) {
481  if (!distributor->DS && !is_secure_access) {
482  // RAZ/WI for non-secure accesses for secure interrupts
483  if (getIntGroup(int_id) != Gicv3::G1NS) {
484  continue;
485  }
486  }
487 
488  bool disable = data & (1 << int_id) ? 1 : 0;
489 
490  if (disable) {
491  irqEnabled[int_id] = false;
492  }
493 
494  DPRINTF(GIC, "Gicv3Redistributor::write(): "
495  "int_id %d enable %i\n", int_id, irqEnabled[int_id]);
496  }
497 
498  break;
499 
500  case GICR_ISPENDR0: // Interrupt Set-Pending Register 0
501  for (int int_id = 0; int_id < 8 * size; int_id++) {
502  if (!distributor->DS && !is_secure_access) {
503  // RAZ/WI for non-secure accesses for secure interrupts
504  if (getIntGroup(int_id) != Gicv3::G1NS) {
505  continue;
506  }
507  }
508 
509  bool pending = data & (1 << int_id) ? 1 : 0;
510 
511  if (pending) {
512  DPRINTF(GIC, "Gicv3Redistributor::write() "
513  "(GICR_ISPENDR0): int_id %d (PPI) "
514  "pending bit set\n", int_id);
515  irqPending[int_id] = true;
516  irqPendingIspendr[int_id] = true;
517  }
518  }
519 
521  break;
522 
523  case GICR_ICPENDR0:// Interrupt Clear-Pending Register 0
524  for (int int_id = 0; int_id < 8 * size; int_id++) {
525  if (!distributor->DS && !is_secure_access) {
526  // RAZ/WI for non-secure accesses for secure interrupts
527  if (getIntGroup(int_id) != Gicv3::G1NS) {
528  continue;
529  }
530  }
531 
532  bool clear = data & (1 << int_id) ? 1 : 0;
533 
534  if (clear && treatAsEdgeTriggered(int_id)) {
535  irqPending[int_id] = false;
536  }
537  }
538 
539  break;
540 
541  case GICR_ISACTIVER0: // Interrupt Set-Active Register 0
542  for (int int_id = 0; int_id < 8 * size; int_id++) {
543  if (!distributor->DS && !is_secure_access) {
544  // RAZ/WI for non-secure accesses for secure interrupts
545  if (getIntGroup(int_id) != Gicv3::G1NS) {
546  continue;
547  }
548  }
549 
550  bool activate = data & (1 << int_id) ? 1 : 0;
551 
552  if (activate) {
553  if (!irqActive[int_id]) {
554  DPRINTF(GIC, "Gicv3Redistributor::write(): "
555  "int_id %d active set\n", int_id);
556  }
557 
558  irqActive[int_id] = true;
559  }
560  }
561 
562  break;
563 
564  case GICR_ICACTIVER0: // Interrupt Clear-Active Register 0
565  for (int int_id = 0; int_id < 8 * size; int_id++) {
566  if (!distributor->DS && !is_secure_access) {
567  // RAZ/WI for non-secure accesses for secure interrupts
568  if (getIntGroup(int_id) != Gicv3::G1NS) {
569  continue;
570  }
571  }
572 
573  bool clear = data & (1 << int_id) ? 1 : 0;
574 
575  if (clear) {
576  if (irqActive[int_id]) {
577  DPRINTF(GIC, "Gicv3Redistributor::write(): "
578  "int_id %d active cleared\n", int_id);
579  }
580 
581  irqActive[int_id] = false;
582  }
583  }
584 
585  break;
586 
587  case GICR_ICFGR0: // SGI Configuration Register
588  // WI
589  return;
590  case GICR_ICFGR1: { // PPI Configuration Register
591  int first_intid = Gicv3::SGI_MAX;
592 
593  for (int i = 0, int_id = first_intid; i < 8 * size;
594  i = i + 2, int_id++) {
595  if (!distributor->DS && !is_secure_access) {
596  // RAZ/WI for non-secure accesses for secure interrupts
597  if (getIntGroup(int_id) != Gicv3::G1NS) {
598  continue;
599  }
600  }
601 
602  irqConfig[int_id] = data & (0x2 << i) ?
605  DPRINTF(GIC, "Gicv3Redistributor::write(): "
606  "int_id %d (PPI) config %d\n",
607  int_id, irqConfig[int_id]);
608  }
609 
610  break;
611  }
612 
613  case GICR_IGRPMODR0: { // Interrupt Group Modifier Register 0
614  if (distributor->DS) {
615  // RAZ/WI if secutiry disabled
616  } else {
617  for (int int_id = 0; int_id < 8 * size; int_id++) {
618  if (!is_secure_access) {
619  // RAZ/WI for non-secure accesses
620  continue;
621  }
622 
623  irqGrpmod[int_id] = data & (1 << int_id);
624  }
625  }
626 
627  break;
628  }
629 
630  case GICR_NSACR: { // Non-secure Access Control Register
631  if (distributor->DS) {
632  // RAZ/WI
633  } else {
634  if (!is_secure_access) {
635  // RAZ/WI
636  } else {
637  for (int i = 0, int_id = 0; i < 8 * size;
638  i = i + 2, int_id++) {
639  irqNsacr[int_id] = (data >> i) & 0x3;
640  }
641  }
642  }
643 
644  break;
645  }
646 
647  case GICR_SETLPIR: // Set LPI Pending Register
648  setClrLPI(data, true);
649  break;
650 
651  case GICR_CLRLPIR: // Clear LPI Pending Register
652  setClrLPI(data, false);
653  break;
654 
655  case GICR_PROPBASER: { // Redistributor Properties Base Address Register
656  // OuterCache, bits [58:56]
657  // 000 Memory type defined in InnerCache field
658  // Physical_Address, bits [51:12]
659  // Bits [51:12] of the physical address containing the LPI
660  // Configuration table
661  // Shareability, bits [11:10]
662  // 00 Non-shareable
663  // InnerCache, bits [9:7]
664  // 000 Device-nGnRnE
665  // IDbits, bits [4:0]
666  // limited by GICD_TYPER.IDbits (= 0xf)
667  lpiConfigurationTablePtr = data & 0xFFFFFFFFFF000;
668  lpiIDBits = data & 0x1f;
669 
670  // 0xf here matches the value of GICD_TYPER.IDbits.
671  // TODO - make GICD_TYPER.IDbits a parameter instead of a hardcoded
672  // value
673  if (lpiIDBits > 0xf) {
674  lpiIDBits = 0xf;
675  }
676 
677  break;
678  }
679 
680  // Redistributor LPI Pending Table Base Address Register
681  case GICR_PENDBASER:
682  // PTZ, bit [62]
683  // Pending Table Zero
684  // OuterCache, bits [58:56]
685  // 000 Memory type defined in InnerCache field
686  // Physical_Address, bits [51:16]
687  // Bits [51:16] of the physical address containing the LPI Pending
688  // table
689  // Shareability, bits [11:10]
690  // 00 Non-shareable
691  // InnerCache, bits [9:7]
692  // 000 Device-nGnRnE
693  lpiPendingTablePtr = data & 0xFFFFFFFFF0000;
694  break;
695 
696  case GICR_INVLPIR: { // Redistributor Invalidate LPI Register
697  // Do nothing: no caching supported
698  break;
699  }
700 
701  case GICR_INVALLR: { // Redistributor Invalidate All Register
702  // Do nothing: no caching supported
703  break;
704  }
705 
706  default:
707  panic("Gicv3Redistributor::write(): invalid offset %#x\n", addr);
708  break;
709  }
710 }
711 
712 void
714 {
715  assert((int_id >= Gicv3::SGI_MAX) &&
716  (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
717  irqPending[int_id] = true;
718  irqPendingIspendr[int_id] = false;
719  DPRINTF(GIC, "Gicv3Redistributor::sendPPInt(): "
720  "int_id %d (PPI) pending bit set\n", int_id);
722 }
723 
724 void
726 {
727  assert((int_id >= Gicv3::SGI_MAX) &&
728  (int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX));
729 
730  if (isLevelSensitive(int_id)) {
731  irqPending[int_id] = false;
732  }
733 }
734 
735 void
736 Gicv3Redistributor::sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
737 {
738  assert(int_id < Gicv3::SGI_MAX);
739  Gicv3::GroupId int_group = getIntGroup(int_id);
740 
741  bool forward = false;
742 
743  if (ns) {
744  // Non-Secure EL1 and EL2 access
745  int nsaccess = irqNsacr[int_id];
746  if (int_group == Gicv3::G0S) {
747 
748  forward = distributor->DS || (nsaccess >= 1);
749 
750  } else if (int_group == Gicv3::G1S) {
751  forward = ((group == Gicv3::G1S || group == Gicv3::G1NS ) &&
752  nsaccess == 2);
753  } else {
754  // G1NS
755  forward = group == Gicv3::G1NS;
756  }
757  } else {
758  // Secure EL1 and EL3 access
759  forward = (group == int_group) ||
760  (group == Gicv3::G1S && int_group == Gicv3::G0S &&
761  distributor->DS);
762  }
763 
764  if (!forward) return;
765 
766  irqPending[int_id] = true;
767  irqPendingIspendr[int_id] = false;
768  DPRINTF(GIC, "Gicv3ReDistributor::sendSGI(): "
769  "int_id %d (SGI) pending bit set\n", int_id);
771 }
772 
774 Gicv3Redistributor::intStatus(uint32_t int_id) const
775 {
776  assert(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX);
777 
778  if (irqPending[int_id]) {
779  if (irqActive[int_id]) {
781  }
782 
783  return Gicv3::INT_PENDING;
784  } else if (irqActive[int_id]) {
785  return Gicv3::INT_ACTIVE;
786  } else {
787  return Gicv3::INT_INACTIVE;
788  }
789 }
790 
791 void
793 {
794  distributor->update();
795 }
796 
797 /*
798  * Recalculate the highest priority pending interrupt after a
799  * change to redistributor state.
800  */
801 void
803 {
804  if (gic->blockIntUpdate())
805  return;
806 
807  for (int int_id = 0; int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id++) {
808  Gicv3::GroupId int_group = getIntGroup(int_id);
809  bool group_enabled = distributor->groupEnabled(int_group);
810 
811  if (irqPending[int_id] && irqEnabled[int_id] &&
812  !irqActive[int_id] && group_enabled) {
813  if ((irqPriority[int_id] < cpuInterface->hppi.prio) ||
814  /*
815  * Multiple pending ints with same priority.
816  * Implementation choice which one to signal.
817  * Our implementation selects the one with the lower id.
818  */
819  (irqPriority[int_id] == cpuInterface->hppi.prio &&
820  int_id < cpuInterface->hppi.intid)) {
821  cpuInterface->hppi.intid = int_id;
822  cpuInterface->hppi.prio = irqPriority[int_id];
823  cpuInterface->hppi.group = int_group;
824  }
825  }
826  }
827 
828  // Check LPIs
829  if (EnableLPIs) {
830 
831  const uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
832  const uint32_t number_lpis = largest_lpi_id - SMALLEST_LPI_ID + 1;
833 
834  uint8_t lpi_pending_table[largest_lpi_id / 8];
835  uint8_t lpi_config_table[number_lpis];
836 
838  lpi_pending_table,
839  sizeof(lpi_pending_table));
840 
842  lpi_config_table,
843  sizeof(lpi_config_table));
844 
845  for (int lpi_id = SMALLEST_LPI_ID; lpi_id < largest_lpi_id;
846  lpi_id++) {
847  uint32_t lpi_pending_entry_byte = lpi_id / 8;
848  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
849  bool lpi_is_pending = lpi_pending_table[lpi_pending_entry_byte] &
850  1 << lpi_pending_entry_bit_position;
851  uint32_t lpi_configuration_entry_index = lpi_id - SMALLEST_LPI_ID;
852 
853  LPIConfigurationTableEntry config_entry =
854  lpi_config_table[lpi_configuration_entry_index];
855 
856  bool lpi_is_enable = config_entry.enable;
857 
858  // LPIs are always Non-secure Group 1 interrupts,
859  // in a system where two Security states are enabled.
860  Gicv3::GroupId lpi_group = Gicv3::G1NS;
861  bool group_enabled = distributor->groupEnabled(lpi_group);
862 
863  if (lpi_is_pending && lpi_is_enable && group_enabled) {
864  uint8_t lpi_priority = config_entry.priority << 2;
865 
866  if ((lpi_priority < cpuInterface->hppi.prio) ||
867  (lpi_priority == cpuInterface->hppi.prio &&
868  lpi_id < cpuInterface->hppi.intid)) {
869  cpuInterface->hppi.intid = lpi_id;
870  cpuInterface->hppi.prio = lpi_priority;
871  cpuInterface->hppi.group = lpi_group;
872  }
873  }
874  }
875  }
876 
877  if (peInLowPowerState) {
881  }
882  } else {
883  cpuInterface->update();
884  }
885 }
886 
887 uint8_t
889 {
890  Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
891 
892  uint8_t lpi_pending_entry;
893  memProxy->readBlob(lpi_pending_entry_ptr,
894  &lpi_pending_entry,
895  sizeof(lpi_pending_entry));
896 
897  return lpi_pending_entry;
898 }
899 
900 void
901 Gicv3Redistributor::writeEntryLPI(uint32_t lpi_id, uint8_t lpi_pending_entry)
902 {
903  Addr lpi_pending_entry_ptr = lpiPendingTablePtr + (lpi_id / 8);
904 
905  memProxy->writeBlob(lpi_pending_entry_ptr,
906  &lpi_pending_entry,
907  sizeof(lpi_pending_entry));
908 }
909 
910 bool
912 {
913  // Fetch the LPI pending entry from memory
914  uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
915 
916  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
917  bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
918 
919  return is_set;
920 }
921 
922 void
924 {
925  if (!EnableLPIs) {
926  // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
927  // GICR_CTLR.EnableLPIs == 0.
928  return;
929  }
930 
931  uint32_t lpi_id = data & 0xffffffff;
932  uint32_t largest_lpi_id = 1 << (lpiIDBits + 1);
933 
934  if (lpi_id > largest_lpi_id) {
935  // Writes to GICR_SETLPIR or GICR_CLRLPIR have not effect if
936  // pINTID value specifies an unimplemented LPI.
937  return;
938  }
939 
940  // Fetch the LPI pending entry from memory
941  uint8_t lpi_pending_entry = readEntryLPI(lpi_id);
942 
943  uint8_t lpi_pending_entry_bit_position = lpi_id % 8;
944  bool is_set = lpi_pending_entry & (1 << lpi_pending_entry_bit_position);
945 
946  if (set) {
947  if (is_set) {
948  // Writes to GICR_SETLPIR have not effect if the pINTID field
949  // corresponds to an LPI that is already pending.
950  return;
951  }
952 
953  lpi_pending_entry |= 1 << (lpi_pending_entry_bit_position);
954  } else {
955  if (!is_set) {
956  // Writes to GICR_SETLPIR have not effect if the pINTID field
957  // corresponds to an LPI that is not pending.
958  return;
959  }
960 
961  lpi_pending_entry &= ~(1 << (lpi_pending_entry_bit_position));
962 
963  // Remove the pending state from the cpu interface
964  cpuInterface->resetHppi(lpi_id);
965  }
966 
967  writeEntryLPI(lpi_id, lpi_pending_entry);
968 
970 }
971 
974 {
975  assert(int_id < (Gicv3::SGI_MAX + Gicv3::PPI_MAX));
976 
977  if (distributor->DS) {
978  if (irqGroup[int_id] == 0) {
979  return Gicv3::G0S;
980  } else {
981  return Gicv3::G1NS;
982  }
983  } else {
984  if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
985  return Gicv3::G0S;
986  } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
987  return Gicv3::G1NS;
988  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
989  return Gicv3::G1S;
990  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
991  return Gicv3::G1NS;
992  }
993  }
994 
995  GEM5_UNREACHABLE;
996 }
997 
998 void
1000 {
1001  if (treatAsEdgeTriggered(int_id)) {
1002  irqPending[int_id] = false;
1003  }
1004  irqActive[int_id] = true;
1005 }
1006 
1007 void
1009 {
1010  irqActive[int_id] = false;
1011 }
1012 
1013 uint32_t
1015 {
1017  return gem5::ArmISA::getAffinity(gic->getSystem(), tc);
1018 }
1019 
1020 bool
1022 {
1023  if (peInLowPowerState) {
1024  return false;
1025  }
1026 
1027  if (!distributor->groupEnabled(group)) {
1028  return false;
1029  }
1030 
1031  if ((group == Gicv3::G1S) && DPG1S) {
1032  return false;
1033  }
1034 
1035  if ((group == Gicv3::G1NS) && DPG1NS) {
1036  return false;
1037  }
1038 
1039  if ((group == Gicv3::G0S) && DPG0) {
1040  return false;
1041  }
1042 
1043  return true;
1044 }
1045 
1046 void
1048 {
1049  const auto affinity = getAffinity();
1050  // SGI_Base regs
1051  gic->copyRedistRegister(from, to, affinity, GICR_CTLR);
1052  gic->copyRedistRegister(from, to, affinity, GICR_WAKER);
1053 
1055  gic->clearRedistRegister(to, affinity, GICR_ICPENDR0);
1057 
1058  gic->copyRedistRegister(from, to, affinity, GICR_ISENABLER0);
1059  gic->copyRedistRegister(from, to, affinity, GICR_ISPENDR0);
1060  gic->copyRedistRegister(from, to, affinity, GICR_ISACTIVER0);
1061  gic->copyRedistRegister(from, to, affinity, GICR_ICFGR0);
1062  gic->copyRedistRegister(from, to, affinity, GICR_ICFGR1);
1063  gic->copyRedistRegister(from, to, affinity, GICR_IGRPMODR0);
1064  gic->copyRedistRegister(from, to, affinity, GICR_NSACR);
1065 
1066  gic->copyRedistRange(from, to, affinity,
1068 
1069  // RD_Base regs
1070  gic->copyRedistRegister(from, to, affinity, GICR_PROPBASER);
1071  gic->copyRedistRegister(from, to, affinity, GICR_PENDBASER);
1072 }
1073 
1074 void
1076 {
1094 }
1095 
1096 void
1098 {
1116 }
1117 
1118 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
ArmSystem * getSystem() const
Definition: base_gic.hh:114
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
Definition: base_gic.hh:130
void resetHppi(uint32_t intid)
bool havePendingInterrupts(void) const
bool groupEnabled(Gicv3::GroupId group) const
uint8_t readEntryLPI(uint32_t intid)
static const uint32_t GICR_WAKER_ProcessorSleep
void clearPPInt(uint32_t int_id)
bool isPendingLPI(uint32_t intid)
static const uint32_t GICR_CTLR_DPG1S
std::vector< uint8_t > irqGroup
Gicv3Distributor * distributor
std::vector< uint8_t > irqPriority
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
void activateIRQ(uint32_t int_id)
Gicv3Redistributor(Gicv3 *gic, uint32_t cpu_id)
static const uint32_t GICR_WAKER_ChildrenAsleep
std::vector< bool > irqPending
std::vector< uint8_t > irqNsacr
void writeEntryLPI(uint32_t intid, uint8_t lpi_entry)
void sendPPInt(uint32_t int_id)
bool isLevelSensitive(uint32_t int_id) const
Gicv3::GroupId getIntGroup(int int_id) const
void serialize(CheckpointOut &cp) const override
Serialize an object.
void copy(Gicv3Registers *from, Gicv3Registers *to)
void deactivateIRQ(uint32_t int_id)
std::vector< bool > irqEnabled
std::vector< Gicv3::IntTriggerType > irqConfig
static const uint32_t SMALLEST_LPI_ID
static const uint32_t GICR_CTLR_DPG1NS
static const uint32_t GICR_CTLR_DPG0
void sendSGI(uint32_t int_id, Gicv3::GroupId group, bool ns)
bool treatAsEdgeTriggered(uint32_t int_id) const
This helper is used to check if an interrupt should be treated as edge triggered in the following sce...
static const AddrRange GICR_IPRIORITYR
Gicv3::IntStatus intStatus(uint32_t int_id) const
std::vector< uint8_t > irqGrpmod
Gicv3CPUInterface * cpuInterface
uint64_t read(Addr addr, size_t size, bool is_secure_access)
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
void unserialize(CheckpointIn &cp) override
Unserialize an object.
void setClrLPI(uint64_t data, bool set)
std::vector< bool > irqPendingIspendr
static void clearRedistRegister(Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr)
Definition: gic_v3.cc:98
static void copyRedistRange(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr, size_t size)
Definition: gic_v3.cc:105
static void copyRedistRegister(Gicv3Registers *from, Gicv3Registers *to, const ArmISA::Affinity &aff, Addr daddr)
Definition: gic_v3.cc:68
static const int SGI_MAX
Definition: gic_v3.hh:119
Gicv3CPUInterface * getCPUInterface(int cpu_id) const
Definition: gic_v3.hh:178
@ INT_LEVEL_SENSITIVE
Definition: gic_v3.hh:142
@ INT_EDGE_TRIGGERED
Definition: gic_v3.hh:143
@ INT_ACTIVE_PENDING
Definition: gic_v3.hh:129
@ INT_ACTIVE
Definition: gic_v3.hh:128
@ INT_PENDING
Definition: gic_v3.hh:127
@ INT_INACTIVE
Definition: gic_v3.hh:126
static const int PPI_MAX
Definition: gic_v3.hh:121
Gicv3Distributor * getDistributor() const
Definition: gic_v3.hh:185
void writeBlob(Addr addr, const void *p, int size) const
Same as tryWriteBlob, but insists on success.
Definition: port_proxy.hh:192
void readBlob(Addr addr, void *p, int size) const
Higher level interfaces based on the above.
Definition: port_proxy.hh:182
int size() const
Definition: system.hh:213
PortProxy physProxy
Port to physical memory used for writing object files into ram at boot.
Definition: system.hh:326
Threads threads
Definition: system.hh:313
ThreadContext is the external interface to all thread state for anything outside of the CPU.
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:471
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:343
Addr size() const
Get the size of the address range.
Definition: addr_range.hh:326
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:634
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:626
Affinity getAffinity(ArmSystem *arm_sys, ThreadContext *tc)
Retrieves MPIDR_EL1.
Definition: utility.cc:214
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 27, 24 > gic
Definition: misc_types.hh:175
Bitfield< 0 > ns
Definition: misc_types.hh:338
Bitfield< 12, 11 > set
Definition: misc_types.hh:709
Bitfield< 25, 21 > to
Definition: types.hh:96
Bitfield< 3 > addr
Definition: types.hh:84
void disable()
Definition: trace.cc:100
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
std::ostream CheckpointOut
Definition: serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568

Generated on Wed Dec 21 2022 10:22:33 for gem5 by doxygen 1.9.1