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

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