gem5  v19.0.0.0
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
gic_v3_distributor.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 <algorithm>
46 
47 #include "base/intmath.hh"
48 #include "debug/GIC.hh"
49 #include "dev/arm/gic_v3.hh"
52 
53 const AddrRange Gicv3Distributor::GICD_IGROUPR (0x0080, 0x0100);
54 const AddrRange Gicv3Distributor::GICD_ISENABLER (0x0100, 0x0180);
55 const AddrRange Gicv3Distributor::GICD_ICENABLER (0x0180, 0x0200);
56 const AddrRange Gicv3Distributor::GICD_ISPENDR (0x0200, 0x0280);
57 const AddrRange Gicv3Distributor::GICD_ICPENDR (0x0280, 0x0300);
58 const AddrRange Gicv3Distributor::GICD_ISACTIVER (0x0300, 0x0380);
59 const AddrRange Gicv3Distributor::GICD_ICACTIVER (0x0380, 0x0400);
60 const AddrRange Gicv3Distributor::GICD_IPRIORITYR(0x0400, 0x0800);
61 const AddrRange Gicv3Distributor::GICD_ITARGETSR (0x0800, 0x0900);
62 const AddrRange Gicv3Distributor::GICD_ICFGR (0x0c00, 0x0d00);
63 const AddrRange Gicv3Distributor::GICD_IGRPMODR (0x0d00, 0x0d80);
64 const AddrRange Gicv3Distributor::GICD_NSACR (0x0e00, 0x0f00);
65 const AddrRange Gicv3Distributor::GICD_CPENDSGIR (0x0f10, 0x0f20);
66 const AddrRange Gicv3Distributor::GICD_SPENDSGIR (0x0f20, 0x0f30);
67 const AddrRange Gicv3Distributor::GICD_IROUTER (0x6000, 0x7fe0);
68 
70  : gic(gic),
71  itLines(it_lines),
72  ARE(true),
73  EnableGrp1S(0),
74  EnableGrp1NS(0),
75  EnableGrp0(0),
76  irqGroup(it_lines, 0),
77  irqEnabled(it_lines, false),
78  irqPending(it_lines, false),
79  irqActive(it_lines, false),
80  irqPriority(it_lines, 0xAA),
81  irqConfig(it_lines, Gicv3::INT_LEVEL_SENSITIVE),
82  irqGrpmod(it_lines, 0),
83  irqNsacr(it_lines, 0),
84  irqAffinityRouting(it_lines, 0),
85  gicdTyper(0),
86  gicdPidr0(0x92),
87  gicdPidr1(0xb4),
88  gicdPidr2(0x3b),
89  gicdPidr3(0),
90  gicdPidr4(0x44)
91 {
92  panic_if(it_lines > Gicv3::INTID_SECURE, "Invalid value for it_lines!");
93  /*
94  * RSS [26] == 1
95  * (The implementation does supports targeted SGIs with affinity
96  * level 0 values of 0 - 255)
97  * No1N [25] == 1
98  * (1 of N SPI interrupts are not supported)
99  * A3V [24] == 1
100  * (Supports nonzero values of Affinity level 3)
101  * IDbits [23:19] == 0xf
102  * (The number of interrupt identifier bits supported, minus one)
103  * DVIS [18] == 0
104  * (The implementation does not support Direct Virtual LPI
105  * injection)
106  * LPIS [17] == 1
107  * (The implementation does not support LPIs)
108  * MBIS [16] == 1
109  * (The implementation supports message-based interrupts
110  * by writing to Distributor registers)
111  * SecurityExtn [10] == X
112  * (The GIC implementation supports two Security states)
113  * CPUNumber [7:5] == 0
114  * (since for us ARE is always 1 [(ARE = 0) == Gicv2 legacy])
115  * ITLinesNumber [4:0] == N
116  * (MaxSPIIntId = 32 (N + 1) - 1)
117  */
118  int max_spi_int_id = itLines - 1;
119  int it_lines_number = divCeil(max_spi_int_id + 1, 32) - 1;
120  gicdTyper = (1 << 26) | (1 << 25) | (1 << 24) | (IDBITS << 19) |
121  (1 << 17) | (1 << 16) |
122  ((gic->getSystem()->haveSecurity() ? 1 : 0) << 10) |
123  (it_lines_number << 0);
124 
125  if (gic->getSystem()->haveSecurity()) {
126  DS = false;
127  } else {
128  DS = true;
129  }
130 }
131 
132 void
134 {
135 }
136 
137 uint64_t
138 Gicv3Distributor::read(Addr addr, size_t size, bool is_secure_access)
139 {
140  if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
141  uint64_t val = 0x0;
142 
143  if (!DS && !is_secure_access) {
144  // RAZ/WI for non-secure accesses
145  return 0;
146  }
147 
148  int first_intid = (addr - GICD_IGROUPR.start()) * 8;
149 
150  if (isNotSPI(first_intid)) {
151  return 0;
152  }
153 
154  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
155  i++, int_id++) {
156  val |= irqGroup[int_id] << i;
157  }
158 
159  return val;
160  } else if (GICD_ISENABLER.contains(addr)) {
161  // Interrupt Set-Enable Registers
162  uint64_t val = 0x0;
163  int first_intid = (addr - GICD_ISENABLER.start()) * 8;
164 
165  if (isNotSPI(first_intid)) {
166  return 0;
167  }
168 
169  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
170  i++, int_id++) {
171 
172  if (nsAccessToSecInt(int_id, is_secure_access))
173  {
174  continue;
175  }
176 
177  val |= irqEnabled[int_id] << i;
178  }
179 
180  return val;
181  } else if (GICD_ICENABLER.contains(addr)) {
182  // Interrupt Clear-Enable Registers
183  uint64_t val = 0x0;
184  int first_intid = (addr - GICD_ICENABLER.start()) * 8;
185 
186  if (isNotSPI(first_intid)) {
187  return 0;
188  }
189 
190  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
191  i++, int_id++) {
192 
193  if (nsAccessToSecInt(int_id, is_secure_access))
194  {
195  continue;
196  }
197 
198  val |= (irqEnabled[int_id] << i);
199  }
200 
201  return val;
202  } else if (GICD_ISPENDR.contains(addr)) {
203  // Interrupt Set-Pending Registers
204  uint64_t val = 0x0;
205  int first_intid = (addr - GICD_ISPENDR.start()) * 8;
206 
207  if (isNotSPI(first_intid)) {
208  return 0;
209  }
210 
211  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
212  i++, int_id++) {
213 
214  if (nsAccessToSecInt(int_id, is_secure_access))
215  {
216  if (irqNsacr[int_id] == 0) {
217  // Group 0 or Secure Group 1 interrupts are RAZ/WI
218  continue;
219  }
220  }
221 
222  val |= (irqPending[int_id] << i);
223  }
224 
225  return val;
226  } else if (GICD_ICPENDR.contains(addr)) {
227  // Interrupt Clear-Pending Registers
228  uint64_t val = 0x0;
229  int first_intid = (addr - GICD_ICPENDR.start()) * 8;
230 
231  if (isNotSPI(first_intid)) {
232  return 0;
233  }
234 
235  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
236  i++, int_id++) {
237 
238  if (nsAccessToSecInt(int_id, is_secure_access))
239  {
240  if (irqNsacr[int_id] < 2) {
241  // Group 0 or Secure Group 1 interrupts are RAZ/WI
242  continue;
243  }
244  }
245 
246  val |= (irqPending[int_id] << i);
247  }
248 
249  return val;
250  } else if (GICD_ISACTIVER.contains(addr)) {
251  // Interrupt Set-Active Registers
252  int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
253 
254  if (isNotSPI(first_intid)) {
255  return 0;
256  }
257 
258  uint64_t val = 0x0;
259 
260  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
261  i++, int_id++) {
262 
263  if (nsAccessToSecInt(int_id, is_secure_access))
264  {
265  // Group 0 or Secure Group 1 interrupts are RAZ/WI
266  if (irqNsacr[int_id] < 2) {
267  continue;
268  }
269  }
270 
271  val |= (irqActive[int_id] << i);
272  }
273 
274  return val;
275  } else if (GICD_ICACTIVER.contains(addr)) {
276  // Interrupt Clear-Active Registers
277  int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
278 
279  if (isNotSPI(first_intid)) {
280  return 0;
281  }
282 
283  uint64_t val = 0x0;
284 
285  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
286  i++, int_id++) {
287 
288  if (nsAccessToSecInt(int_id, is_secure_access))
289  {
290  if (irqNsacr[int_id] < 2) {
291  continue;
292  }
293  }
294 
295  val |= (irqActive[int_id] << i);
296  }
297 
298  return val;
299  } else if (GICD_IPRIORITYR.contains(addr)) {
300  // Interrupt Priority Registers
301  uint64_t val = 0x0;
302  int first_intid = addr - GICD_IPRIORITYR.start();
303 
304  if (isNotSPI(first_intid)) {
305  return 0;
306  }
307 
308  for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
309  i++, int_id++) {
310 
311  uint8_t prio = irqPriority[int_id];
312 
313  if (!DS && !is_secure_access) {
314  if (getIntGroup(int_id) != Gicv3::G1NS) {
315  // RAZ/WI for non-secure accesses for secure interrupts
316  continue;
317  } else {
318  // NS view
319  prio = (prio << 1) & 0xff;
320  }
321  }
322 
323  val |= prio << (i * 8);
324  }
325 
326  return val;
327  } else if (GICD_ITARGETSR.contains(addr)) {
328  // Interrupt Processor Targets Registers
329  // ARE always on, RAZ/WI
330  warn("Gicv3Distributor::read(): "
331  "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
332  return 0;
333  } else if (GICD_ICFGR.contains(addr)) {
334  // Interrupt Configuration Registers
335  int first_intid = (addr - GICD_ICFGR.start()) * 4;
336 
337  if (isNotSPI(first_intid)) {
338  return 0;
339  }
340 
341  uint64_t val = 0x0;
342 
343  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
344  i = i + 2, int_id++) {
345 
346  if (nsAccessToSecInt(int_id, is_secure_access))
347  {
348  continue;
349  }
350 
351  if (irqConfig[int_id] == Gicv3::INT_EDGE_TRIGGERED) {
352  val |= (0x2 << i);
353  }
354  }
355 
356  return val;
357  } else if (GICD_IGRPMODR.contains(addr)) {
358  // Interrupt Group Modifier Registers
359  if (DS) {
360  // RAZ/WI if security disabled
361  return 0;
362  } else {
363  if (!is_secure_access) {
364  // RAZ/WI for non-secure accesses
365  return 0;
366  } else {
367  int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
368 
369  if (isNotSPI(first_intid)) {
370  return 0;
371  }
372 
373  uint64_t val = 0x0;
374 
375  for (int i = 0, int_id = first_intid;
376  i < 8 * size && int_id < itLines; i++, int_id++) {
377  val |= irqGrpmod[int_id] << i;
378  }
379 
380  return val;
381  }
382  }
383  } else if (GICD_NSACR.contains(addr)) {
384  // Non-secure Access Control Registers
385  // 2 bits per interrupt
386  int first_intid = (addr - GICD_NSACR.start()) * 4;
387 
388  if (isNotSPI(first_intid)) {
389  return 0;
390  }
391 
392  if (DS || (!DS && !is_secure_access)) {
393  return 0;
394  }
395 
396  uint64_t val = 0x0;
397 
398  for (int i = 0, int_id = first_intid;
399  i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
400  val |= irqNsacr[int_id] << i;
401  }
402 
403  return val;
404  } else if (GICD_CPENDSGIR.contains(addr)) { // SGI Clear-Pending Registers
405  // ARE always on, RAZ/WI
406  warn("Gicv3Distributor::read(): "
407  "GICD_CPENDSGIR is RAZ/WI, legacy not supported!\n");
408  return 0x0;
409  } else if (GICD_SPENDSGIR.contains(addr)) { // SGI Set-Pending Registers
410  // ARE always on, RAZ/WI
411  warn("Gicv3Distributor::read(): "
412  "GICD_SPENDSGIR is RAZ/WI, legacy not supported!\n");
413  return 0x0;
414  } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
415  // 64 bit registers. 2 or 1 access.
416  int int_id = (addr - GICD_IROUTER.start()) / 8;
417 
418  if (isNotSPI(int_id)) {
419  return 0;
420  }
421 
422  if (nsAccessToSecInt(int_id, is_secure_access))
423  {
424  if (irqNsacr[int_id] < 3) {
425  return 0;
426  }
427  }
428 
429  if (size == 4) {
430  if (addr & 7) { // high half of 64 bit register
431  return irqAffinityRouting[int_id] >> 32;
432  } else { // high low of 64 bit register
433  return irqAffinityRouting[int_id] & 0xFFFFFFFF;
434  }
435  } else {
436  return irqAffinityRouting[int_id];
437  }
438  }
439 
440  switch (addr) {
441  case GICD_CTLR: // Control Register
442  if (!DS) {
443  if (is_secure_access) {
444  // E1NWF [7] RAZ/WI
445  // DS [6] - Disable Security
446  // ARE_NS [5] RAO/WI
447  // ARE_S [4] RAO/WI
448  // EnableGrp1S [2]
449  // EnableGrp1NS [1]
450  // EnableGrp0 [0]
451  return (EnableGrp0 << 0) |
452  (EnableGrp1NS << 1) |
453  (EnableGrp1S << 2) |
454  (1 << 4) |
455  (1 << 5) |
456  (DS << 6);
457  } else {
458  // ARE_NS [4] RAO/WI;
459  // EnableGrp1A [1] is a read-write alias of the Secure
460  // GICD_CTLR.EnableGrp1NS
461  // EnableGrp1 [0] RES0
462  return (1 << 4) | (EnableGrp1NS << 1);
463  }
464  } else {
465  return (DS << 6) | (ARE << 4) |
466  (EnableGrp1NS << 1) | (EnableGrp0 << 0);
467  }
468 
469  case GICD_TYPER: // Interrupt Controller Type Register
470  return gicdTyper;
471 
472  case GICD_IIDR: // Implementer Identification Register
473  //return 0x43b; // ARM JEP106 code (r0p0 GIC-500)
474  return 0;
475 
476  case GICD_STATUSR: // Error Reporting Status Register
477  // Optional register, RAZ/WI
478  return 0x0;
479 
480  case GICD_PIDR0: // Peripheral ID0 Register
481  return gicdPidr0;
482 
483  case GICD_PIDR1: // Peripheral ID1 Register
484  return gicdPidr1;
485 
486  case GICD_PIDR2: // Peripheral ID2 Register
487  return gicdPidr2;
488 
489  case GICD_PIDR3: // Peripheral ID3 Register
490  return gicdPidr3;
491 
492  case GICD_PIDR4: // Peripheral ID4 Register
493  return gicdPidr4;
494 
495  case GICD_PIDR5: // Peripheral ID5 Register
496  case GICD_PIDR6: // Peripheral ID6 Register
497  case GICD_PIDR7: // Peripheral ID7 Register
498  return 0; // RES0
499 
500  default:
501  panic("Gicv3Distributor::read(): invalid offset %#x\n", addr);
502  break;
503  }
504 }
505 
506 void
507 Gicv3Distributor::write(Addr addr, uint64_t data, size_t size,
508  bool is_secure_access)
509 {
510  if (GICD_IGROUPR.contains(addr)) { // Interrupt Group Registers
511  if (!DS && !is_secure_access) {
512  // RAZ/WI for non-secure accesses
513  return;
514  }
515 
516  int first_intid = (addr - GICD_IGROUPR.start()) * 8;
517 
518  if (isNotSPI(first_intid)) {
519  return;
520  }
521 
522  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
523  i++, int_id++) {
524  irqGroup[int_id] = data & (1 << i) ? 1 : 0;
525  DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d group %d\n",
526  int_id, irqGroup[int_id]);
527  }
528 
529  return;
530  } else if (GICD_ISENABLER.contains(addr)) {
531  // Interrupt Set-Enable Registers
532  int first_intid = (addr - GICD_ISENABLER.start()) * 8;
533 
534  if (isNotSPI(first_intid)) {
535  return;
536  }
537 
538  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
539  i++, int_id++) {
540 
541  if (nsAccessToSecInt(int_id, is_secure_access))
542  {
543  continue;
544  }
545 
546  bool enable = data & (1 << i) ? 1 : 0;
547 
548  if (enable) {
549  if (!irqEnabled[int_id]) {
550  DPRINTF(GIC, "Gicv3Distributor::write(): "
551  "int_id %d enabled\n", int_id);
552  }
553 
554  irqEnabled[int_id] = true;
555  }
556  }
557 
558  return;
559  } else if (GICD_ICENABLER.contains(addr)) {
560  // Interrupt Clear-Enable Registers
561  int first_intid = (addr - GICD_ICENABLER.start()) * 8;
562 
563  if (isNotSPI(first_intid)) {
564  return;
565  }
566 
567  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
568  i++, int_id++) {
569 
570  if (nsAccessToSecInt(int_id, is_secure_access))
571  {
572  continue;
573  }
574 
575  bool disable = data & (1 << i) ? 1 : 0;
576 
577  if (disable) {
578  if (irqEnabled[int_id]) {
579  DPRINTF(GIC, "Gicv3Distributor::write(): "
580  "int_id %d disabled\n", int_id);
581  }
582 
583  irqEnabled[int_id] = false;
584  }
585  }
586 
587  return;
588  } else if (GICD_ISPENDR.contains(addr)) {
589  // Interrupt Set-Pending Registers
590  int first_intid = (addr - GICD_ISPENDR.start()) * 8;
591 
592  if (isNotSPI(first_intid)) {
593  return;
594  }
595 
596  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
597  i++, int_id++) {
598 
599  if (nsAccessToSecInt(int_id, is_secure_access))
600  {
601  if (irqNsacr[int_id] == 0) {
602  // Group 0 or Secure Group 1 interrupts are RAZ/WI
603  continue;
604  }
605  }
606 
607  bool pending = data & (1 << i) ? 1 : 0;
608 
609  if (pending) {
610  DPRINTF(GIC, "Gicv3Distributor::write() (GICD_ISPENDR): "
611  "int_id %d (SPI) pending bit set\n", int_id);
612  irqPending[int_id] = true;
613  }
614  }
615 
616  update();
617  return;
618  } else if (GICD_ICPENDR.contains(addr)) {
619  // Interrupt Clear-Pending Registers
620  int first_intid = (addr - GICD_ICPENDR.start()) * 8;
621 
622  if (isNotSPI(first_intid)) {
623  return;
624  }
625 
626  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
627  i++, int_id++) {
628 
629  if (nsAccessToSecInt(int_id, is_secure_access))
630  {
631  if (irqNsacr[int_id] < 2) {
632  // Group 0 or Secure Group 1 interrupts are RAZ/WI
633  continue;
634  }
635  }
636 
637  bool clear = data & (1 << i) ? 1 : 0;
638 
639  if (clear) {
640  irqPending[int_id] = false;
641  clearIrqCpuInterface(int_id);
642  }
643  }
644 
645  update();
646  return;
647  } else if (GICD_ISACTIVER.contains(addr)) {
648  // Interrupt Set-Active Registers
649  int first_intid = (addr - GICD_ISACTIVER.start()) * 8;
650 
651  if (isNotSPI(first_intid)) {
652  return;
653  }
654 
655  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
656  i++, int_id++) {
657 
658  if (nsAccessToSecInt(int_id, is_secure_access))
659  {
660  continue;
661  }
662 
663  bool active = data & (1 << i) ? 1 : 0;
664 
665  if (active) {
666  irqActive[int_id] = 1;
667  }
668  }
669 
670  return;
671  } else if (GICD_ICACTIVER.contains(addr)) {
672  // Interrupt Clear-Active Registers
673  int first_intid = (addr - GICD_ICACTIVER.start()) * 8;
674 
675  if (isNotSPI(first_intid)) {
676  return;
677  }
678 
679  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
680  i++, int_id++) {
681 
682  if (nsAccessToSecInt(int_id, is_secure_access))
683  {
684  continue;
685  }
686 
687  bool clear = data & (1 << i) ? 1 : 0;
688 
689  if (clear) {
690  if (irqActive[int_id]) {
691  DPRINTF(GIC, "Gicv3Distributor::write(): "
692  "int_id %d active cleared\n", int_id);
693  }
694 
695  irqActive[int_id] = false;
696  }
697  }
698 
699  return;
700  } else if (GICD_IPRIORITYR.contains(addr)) {
701  // Interrupt Priority Registers
702  int first_intid = addr - GICD_IPRIORITYR.start();
703 
704  if (isNotSPI(first_intid)) {
705  return;
706  }
707 
708  for (int i = 0, int_id = first_intid; i < size && int_id < itLines;
709  i++, int_id++) {
710  uint8_t prio = bits(data, (i + 1) * 8 - 1, (i * 8));
711 
712  if (!DS && !is_secure_access) {
713  if (getIntGroup(int_id) != Gicv3::G1NS) {
714  // RAZ/WI for non-secure accesses to secure interrupts
715  continue;
716  } else {
717  prio = 0x80 | (prio >> 1);
718  }
719  }
720 
721  irqPriority[int_id] = prio;
722  DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d priority %d\n",
723  int_id, irqPriority[int_id]);
724  }
725 
726  return;
727  } else if (GICD_ITARGETSR.contains(addr)) {
728  // Interrupt Processor Targets Registers
729  // ARE always on, RAZ/WI
730  warn("Gicv3Distributor::write(): "
731  "GICD_ITARGETSR is RAZ/WI, legacy not supported!\n");
732  return;
733  } else if (GICD_ICFGR.contains(addr)) {
734  // Interrupt Configuration Registers
735  // for x = 0 to 15:
736  // GICD_ICFGR[2x] = RES0
737  // GICD_ICFGR[2x + 1] =
738  // 0 level-sensitive
739  // 1 edge-triggered
740  int first_intid = (addr - GICD_ICFGR.start()) * 4;
741 
742  if (isNotSPI(first_intid)) {
743  return;
744  }
745 
746  for (int i = 0, int_id = first_intid; i < 8 * size && int_id < itLines;
747  i = i + 2, int_id++) {
748  irqConfig[int_id] = data & (0x2 << i) ?
751  DPRINTF(GIC, "Gicv3Distributor::write(): int_id %d config %d\n",
752  int_id, irqConfig[int_id]);
753  }
754 
755  return;
756  } else if (GICD_IGRPMODR.contains(addr)) {
757  // Interrupt Group Modifier Registers
758  if (DS) {
759  return;
760  } else {
761  if (!is_secure_access) {
762  // RAZ/WI for non-secure accesses
763  return;
764  } else {
765  int first_intid = (addr - GICD_IGRPMODR.start()) * 8;
766 
767  if (isNotSPI(first_intid)) {
768  return;
769  }
770 
771  for (int i = 0, int_id = first_intid;
772  i < 8 * size && int_id < itLines; i++, int_id++) {
773  irqGrpmod[int_id] = bits(data, i);
774  }
775 
776  return ;
777  }
778  }
779 
780  } else if (GICD_NSACR.contains(addr)) {
781  // Non-secure Access Control Registers
782  // 2 bits per interrupt
783  int first_intid = (addr - GICD_NSACR.start()) * 4;
784 
785  if (isNotSPI(first_intid)) {
786  return;
787  }
788 
789  if (DS || (!DS && !is_secure_access)) {
790  return;
791  }
792 
793  for (int i = 0, int_id = first_intid;
794  i < 8 * size && int_id < itLines; i = i + 2, int_id++) {
795  irqNsacr[int_id] = (data >> (2 * int_id)) & 0x3;
796  }
797 
798  return;
799  } else if (GICD_IROUTER.contains(addr)) { // Interrupt Routing Registers
800  // 64 bit registers. 2 accesses.
801  int int_id = (addr - GICD_IROUTER.start()) / 8;
802 
803  if (isNotSPI(int_id)) {
804  return;
805  }
806 
807  if (nsAccessToSecInt(int_id, is_secure_access))
808  {
809  if (irqNsacr[int_id] < 3) {
810  // Group 0 or Secure Group 1 interrupts are RAZ/WI
811  return;
812  }
813  }
814 
815  if (size == 4) {
816  if (addr & 7) { // high half of 64 bit register
817  irqAffinityRouting[int_id] =
818  (irqAffinityRouting[int_id] & 0xffffffff) | (data << 32);
819  } else { // low half of 64 bit register
820  irqAffinityRouting[int_id] =
821  (irqAffinityRouting[int_id] & 0xffffffff00000000) |
822  (data & 0xffffffff);
823  }
824  } else {
825  irqAffinityRouting[int_id] = data;
826  }
827 
828  DPRINTF(GIC, "Gicv3Distributor::write(): "
829  "int_id %d GICD_IROUTER %#llx\n",
830  int_id, irqAffinityRouting[int_id]);
831  return;
832  }
833 
834  switch (addr) {
835  case GICD_CTLR: // Control Register
836  if (DS) {
837  /*
838  * E1NWF [7]
839  * 1 of N wakeup functionality not supported, RAZ/WI
840  * DS [6] - RAO/WI
841  * ARE [4]
842  * affinity routing always on, no GICv2 legacy, RAO/WI
843  * EnableGrp1 [1]
844  * EnableGrp0 [0]
845  */
846  if ((data & (1 << 4)) == 0) {
847  warn("Gicv3Distributor::write(): "
848  "setting ARE to 0 is not supported!\n");
849  }
850 
852  EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
853  DPRINTF(GIC, "Gicv3Distributor::write(): (DS 1)"
854  "EnableGrp1NS %d EnableGrp0 %d\n",
856  } else {
857  if (is_secure_access) {
858  /*
859  * E1NWF [7]
860  * 1 of N wakeup functionality not supported, RAZ/WI
861  * DS [6]
862  * ARE_NS [5]
863  * affinity routing always on, no GICv2 legacy, RAO/WI
864  * ARE_S [4]
865  * affinity routing always on, no GICv2 legacy, RAO/WI
866  * EnableGrp1S [2]
867  * EnableGrp1NS [1]
868  * EnableGrp0 [0]
869  */
870  if ((data & (1 << 5)) == 0) {
871  warn("Gicv3Distributor::write(): "
872  "setting ARE_NS to 0 is not supported!\n");
873  }
874 
875  if ((data & (1 << 4)) == 0) {
876  warn("Gicv3Distributor::write(): "
877  "setting ARE_S to 0 is not supported!\n");
878  }
879 
880  DS = data & GICD_CTLR_DS;
883  EnableGrp0 = data & GICD_CTLR_ENABLEGRP0;
884  DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 secure)"
885  "DS %d "
886  "EnableGrp1S %d EnableGrp1NS %d EnableGrp0 %d\n",
888 
889  if (data & GICD_CTLR_DS) {
890  EnableGrp1S = 0;
891  }
892  } else {
893  /*
894  * ARE_NS [4] RAO/WI;
895  * EnableGrp1A [1] is a read-write alias of the Secure
896  * GICD_CTLR.EnableGrp1NS
897  * EnableGrp1 [0] RES0
898  */
899  if ((data & (1 << 4)) == 0) {
900  warn("Gicv3Distributor::write(): "
901  "setting ARE_NS to 0 is not supported!\n");
902  }
903 
905  DPRINTF(GIC, "Gicv3Distributor::write(): (DS 0 non-secure)"
906  "EnableGrp1NS %d\n", EnableGrp1NS);
907  }
908  }
909 
910  update();
911 
912  break;
913 
914  case GICD_SGIR: // Error Reporting Status Register
915  // Only if affinity routing is disabled, RES0
916  break;
917 
918  case GICD_SETSPI_NSR: {
919  // Writes to this register have no effect if:
920  // * The value written specifies an invalid SPI.
921  // * The SPI is already pending.
922  // * The value written specifies a Secure SPI, the value is
923  // written by a Non-secure access, and the value of the
924  // corresponding GICD_NSACR<n> register is 0.
925  const uint32_t intid = bits(data, 9, 0);
926  if (isNotSPI(intid) || irqPending[intid] ||
927  (nsAccessToSecInt(intid, is_secure_access) &&
928  irqNsacr[intid] == 0)) {
929  return;
930  } else {
931  // Valid SPI, set interrupt pending
932  sendInt(intid);
933  }
934  break;
935  }
936 
937  case GICD_CLRSPI_NSR: {
938  // Writes to this register have no effect if:
939  // * The value written specifies an invalid SPI.
940  // * The SPI is not pending.
941  // * The value written specifies a Secure SPI, the value is
942  // written by a Non-secure access, and the value of the
943  // corresponding GICD_NSACR<n> register is less than 0b10.
944  const uint32_t intid = bits(data, 9, 0);
945  if (isNotSPI(intid) || !irqPending[intid] ||
946  (nsAccessToSecInt(intid, is_secure_access) &&
947  irqNsacr[intid] < 2)) {
948  return;
949  } else {
950  // Valid SPI, clear interrupt pending
951  deassertSPI(intid);
952  }
953  break;
954  }
955 
956  case GICD_SETSPI_SR: {
957  // Writes to this register have no effect if:
958  // * GICD_CTLR.DS = 1 (WI)
959  // * The value written specifies an invalid SPI.
960  // * The SPI is already pending.
961  // * The value is written by a Non-secure access.
962  const uint32_t intid = bits(data, 9, 0);
963  if (DS || isNotSPI(intid) || irqPending[intid] || !is_secure_access) {
964  return;
965  } else {
966  // Valid SPI, set interrupt pending
967  sendInt(intid);
968  }
969  break;
970  }
971 
972  case GICD_CLRSPI_SR: {
973  // Writes to this register have no effect if:
974  // * GICD_CTLR.DS = 1 (WI)
975  // * The value written specifies an invalid SPI.
976  // * The SPI is not pending.
977  // * The value is written by a Non-secure access.
978  const uint32_t intid = bits(data, 9, 0);
979  if (DS || isNotSPI(intid) || !irqPending[intid] || !is_secure_access) {
980  return;
981  } else {
982  // Valid SPI, clear interrupt pending
983  deassertSPI(intid);
984  }
985  break;
986  }
987 
988  default:
989  panic("Gicv3Distributor::write(): invalid offset %#x\n", addr);
990  break;
991  }
992 }
993 
994 void
996 {
997  panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
998  panic_if(int_id > itLines, "Invalid SPI!");
999  irqPending[int_id] = true;
1000  DPRINTF(GIC, "Gicv3Distributor::sendInt(): "
1001  "int_id %d (SPI) pending bit set\n", int_id);
1002  update();
1003 }
1004 
1005 void
1007 {
1008  panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1009  panic_if(int_id > itLines, "Invalid SPI!");
1010  irqPending[int_id] = false;
1011  clearIrqCpuInterface(int_id);
1012 
1013  update();
1014 }
1015 
1017 Gicv3Distributor::route(uint32_t int_id)
1018 {
1019  IROUTER affinity_routing = irqAffinityRouting[int_id];
1020  Gicv3Redistributor * target_redistributor = nullptr;
1021 
1022  const Gicv3::GroupId int_group = getIntGroup(int_id);
1023 
1024  if (affinity_routing.IRM) {
1025  // Interrupts routed to any PE defined as a participating node
1026  for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1027  Gicv3Redistributor * redistributor_i =
1029 
1030  if (redistributor_i->
1031  canBeSelectedFor1toNInterrupt(int_group)) {
1032  target_redistributor = redistributor_i;
1033  break;
1034  }
1035  }
1036  } else {
1037  uint32_t affinity = (affinity_routing.Aff3 << 24) |
1038  (affinity_routing.Aff2 << 16) |
1039  (affinity_routing.Aff1 << 8) |
1040  (affinity_routing.Aff0 << 0);
1041  target_redistributor =
1042  gic->getRedistributorByAffinity(affinity);
1043  }
1044 
1045  if (!target_redistributor) {
1046  // Interrrupts targeting not present cpus must remain pending
1047  return nullptr;
1048  } else {
1049  return target_redistributor->getCPUInterface();
1050  }
1051 }
1052 
1053 void
1055 {
1056  auto cpu_interface = route(int_id);
1057  if (cpu_interface)
1058  cpu_interface->resetHppi(int_id);
1059 }
1060 
1061 void
1063 {
1064  // Find the highest priority pending SPI
1065  for (int int_id = Gicv3::SGI_MAX + Gicv3::PPI_MAX; int_id < itLines;
1066  int_id++) {
1067  Gicv3::GroupId int_group = getIntGroup(int_id);
1068  bool group_enabled = groupEnabled(int_group);
1069 
1070  if (irqPending[int_id] && irqEnabled[int_id] &&
1071  !irqActive[int_id] && group_enabled) {
1072 
1073  // Find the cpu interface where to route the interrupt
1074  Gicv3CPUInterface *target_cpu_interface = route(int_id);
1075 
1076  // Invalid routing
1077  if (!target_cpu_interface) continue;
1078 
1079  if ((irqPriority[int_id] < target_cpu_interface->hppi.prio) ||
1080  (irqPriority[int_id] == target_cpu_interface->hppi.prio &&
1081  int_id < target_cpu_interface->hppi.intid)) {
1082 
1083  target_cpu_interface->hppi.intid = int_id;
1084  target_cpu_interface->hppi.prio = irqPriority[int_id];
1085  target_cpu_interface->hppi.group = int_group;
1086  }
1087  }
1088  }
1089 
1090  // Update all redistributors
1091  for (int i = 0; i < gic->getSystem()->numContexts(); i++) {
1093  }
1094 }
1095 
1097 Gicv3Distributor::intStatus(uint32_t int_id) const
1098 {
1099  panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1100  panic_if(int_id > itLines, "Invalid SPI!");
1101 
1102  if (irqPending[int_id]) {
1103  if (irqActive[int_id]) {
1105  }
1106 
1107  return Gicv3::INT_PENDING;
1108  } else if (irqActive[int_id]) {
1109  return Gicv3::INT_ACTIVE;
1110  } else {
1111  return Gicv3::INT_INACTIVE;
1112  }
1113 }
1114 
1117 {
1118  panic_if(int_id < Gicv3::SGI_MAX + Gicv3::PPI_MAX, "Invalid SPI!");
1119  panic_if(int_id > itLines, "Invalid SPI!");
1120 
1121  if (DS) {
1122  if (irqGroup[int_id] == 1) {
1123  return Gicv3::G1NS;
1124  } else {
1125  return Gicv3::G0S;
1126  }
1127  } else {
1128  if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 0) {
1129  return Gicv3::G0S;
1130  } else if (irqGrpmod[int_id] == 0 && irqGroup[int_id] == 1) {
1131  return Gicv3::G1NS;
1132  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 0) {
1133  return Gicv3::G1S;
1134  } else if (irqGrpmod[int_id] == 1 && irqGroup[int_id] == 1) {
1135  return Gicv3::G1NS;
1136  }
1137  }
1138 
1139  M5_UNREACHABLE;
1140 }
1141 
1142 void
1144 {
1145  irqPending[int_id] = false;
1146  irqActive[int_id] = true;
1147 }
1148 
1149 void
1151 {
1152  irqActive[int_id] = false;
1153 }
1154 
1155 void
1157 {
1172 }
1173 
1174 void
1176 {
1191 }
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:167
#define DPRINTF(x,...)
Definition: trace.hh:229
static const AddrRange GICD_SPENDSGIR
static const int PPI_MAX
Definition: gic_v3.hh:80
Definition: gic_v3.hh:54
Bitfield< 7 > i
std::vector< uint8_t > irqGrpmod
bool haveSecurity() const
Returns true if this system implements the Security Extensions.
Definition: system.hh:185
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:406
static const AddrRange GICD_ISENABLER
ip6_addr_t addr
Definition: inet.hh:335
uint64_t read(Addr addr, size_t size, bool is_secure_access)
std::vector< Gicv3::IntTriggerType > irqConfig
std::vector< uint8_t > irqPriority
std::vector< uint8_t > irqPriority
bool nsAccessToSecInt(uint32_t int_id, bool is_secure_access) const
std::vector< uint8_t > irqNsacr
void write(Addr addr, uint64_t data, size_t size, bool is_secure_access)
Definition: cprintf.cc:42
std::vector< IROUTER > irqAffinityRouting
bool canBeSelectedFor1toNInterrupt(Gicv3::GroupId group) const
void sendInt(uint32_t int_id)
static const AddrRange GICD_CPENDSGIR
static const AddrRange GICD_IGROUPR
std::vector< bool > irqEnabled
static const AddrRange GICD_ITARGETSR
void deassertSPI(uint32_t int_id)
Bitfield< 63 > val
Definition: misc.hh:771
void clearIrqCpuInterface(uint32_t int_id)
static const int SGI_MAX
Definition: gic_v3.hh:78
Gicv3Redistributor * getRedistributorByAffinity(uint32_t affinity) const
Definition: gic_v3.cc:226
static const AddrRange GICD_ICENABLER
std::vector< bool > irqPending
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
static const AddrRange GICD_ICFGR
#define SERIALIZE_CONTAINER(member)
Definition: serialize.hh:664
Bitfield< 11 > enable
Definition: misc.hh:1053
static const AddrRange GICD_ISACTIVER
Gicv3CPUInterface * getCPUInterface() const
std::vector< bool > irqActive
static const uint32_t IDBITS
static const AddrRange GICD_ISPENDR
std::vector< uint8_t > irqGroup
std::vector< bool > irqPending
bool isNotSPI(uint32_t int_id) const
unsigned numContexts() const
Definition: system.hh:206
Gicv3Distributor(Gicv3 *gic, uint32_t it_lines)
void activateIRQ(uint32_t int_id)
std::vector< bool > irqEnabled
GroupId
Definition: gic_v3.hh:91
static const AddrRange GICD_ICACTIVER
const uint32_t itLines
void unserialize(CheckpointIn &cp) override
Unserialize an object.
#define UNSERIALIZE_CONTAINER(member)
Definition: serialize.hh:667
Gicv3Redistributor * getRedistributor(ContextID context_id) const
Definition: gic_v3.hh:149
static const AddrRange GICD_NSACR
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
Gicv3::IntStatus intStatus(uint32_t int_id) const
std::vector< uint8_t > irqGrpmod
std::vector< bool > irqActive
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:643
IntStatus
Definition: gic_v3.hh:83
Gicv3::GroupId getIntGroup(int int_id) const
std::ostream CheckpointOut
Definition: serialize.hh:68
static const AddrRange GICD_IPRIORITYR
static const uint32_t GICD_CTLR_ENABLEGRP1S
Gicv3CPUInterface * route(uint32_t int_id)
T divCeil(const T &a, const U &b)
Definition: intmath.hh:153
Bitfield< 27, 24 > gic
std::vector< Gicv3::IntTriggerType > irqConfig
static const uint32_t GICD_CTLR_ENABLEGRP1NS
static const uint32_t GICD_CTLR_DS
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
void serialize(CheckpointOut &cp) const override
Serialize an object.
#define warn(...)
Definition: logging.hh:212
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
ArmSystem * getSystem() const
Definition: base_gic.hh:106
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:185
const char data[]
static const AddrRange GICD_IGRPMODR
static const uint32_t GICD_CTLR_ENABLEGRP1A
static const AddrRange GICD_IROUTER
static const AddrRange GICD_ICPENDR
std::vector< uint8_t > irqGroup
void deactivateIRQ(uint32_t int_id)
void disable()
Definition: trace.cc:102
static const int INTID_SECURE
Definition: gic_v3.hh:73

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