gem5
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
gic_pl390.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 2013, 2015-2017 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) 2005 The Regents of The University of Michigan
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: Ali Saidi
41  * Prakash Ramrakhyani
42  */
43 
44 #include "dev/arm/gic_pl390.hh"
45 
46 #include "base/trace.hh"
47 #include "debug/Checkpoint.hh"
48 #include "debug/GIC.hh"
49 #include "debug/IPI.hh"
50 #include "debug/Interrupt.hh"
51 #include "dev/terminal.hh"
52 #include "mem/packet.hh"
53 #include "mem/packet_access.hh"
54 
55 const AddrRange Pl390::GICD_IGROUPR (0x080, 0x0ff);
56 const AddrRange Pl390::GICD_ISENABLER (0x100, 0x17f);
57 const AddrRange Pl390::GICD_ICENABLER (0x180, 0x1ff);
58 const AddrRange Pl390::GICD_ISPENDR (0x200, 0x27f);
59 const AddrRange Pl390::GICD_ICPENDR (0x280, 0x2ff);
60 const AddrRange Pl390::GICD_ISACTIVER (0x300, 0x37f);
61 const AddrRange Pl390::GICD_ICACTIVER (0x380, 0x3ff);
62 const AddrRange Pl390::GICD_IPRIORITYR(0x400, 0x7ff);
63 const AddrRange Pl390::GICD_ITARGETSR (0x800, 0xbff);
64 const AddrRange Pl390::GICD_ICFGR (0xc00, 0xcff);
65 
67  : BaseGic(p),
68  distRange(RangeSize(p->dist_addr, DIST_SIZE)),
69  cpuRange(RangeSize(p->cpu_addr, CPU_SIZE)),
70  addrRanges{distRange, cpuRange},
71  distPioDelay(p->dist_pio_delay),
72  cpuPioDelay(p->cpu_pio_delay), intLatency(p->int_latency),
73  enabled(false), haveGem5Extensions(p->gem5_extensions),
74  itLines(p->it_lines),
75  intEnabled {}, pendingInt {}, activeInt {},
76  intPriority {}, cpuTarget {}, intConfig {},
77  cpuSgiPending {}, cpuSgiActive {},
78  cpuSgiPendingExt {}, cpuSgiActiveExt {},
79  cpuPpiPending {}, cpuPpiActive {},
80  irqEnable(false),
81  pendingDelayedInterrupts(0)
82 {
83  for (int x = 0; x < CPU_MAX; x++) {
84  iccrpr[x] = 0xff;
85  cpuEnabled[x] = false;
86  cpuPriority[x] = 0xff;
87  cpuBpr[x] = GICC_BPR_MINIMUM;
88  // Initialize cpu highest int
89  cpuHighestInt[x] = SPURIOUS_INT;
90  postIntEvent[x] = new PostIntEvent(*this, x);
91  }
92  DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled[0],
93  cpuEnabled[1]);
94 
95  gem5ExtensionsEnabled = false;
96 }
97 
98 Tick
100 {
101  const Addr addr = pkt->getAddr();
102 
103  if (distRange.contains(addr))
104  return readDistributor(pkt);
105  else if (cpuRange.contains(addr))
106  return readCpu(pkt);
107  else
108  panic("Read to unknown address %#x\n", pkt->getAddr());
109 }
110 
111 
112 Tick
114 {
115  const Addr addr = pkt->getAddr();
116 
117  if (distRange.contains(addr))
118  return writeDistributor(pkt);
119  else if (cpuRange.contains(addr))
120  return writeCpu(pkt);
121  else
122  panic("Write to unknown address %#x\n", pkt->getAddr());
123 }
124 
125 Tick
127 {
128  const Addr daddr = pkt->getAddr() - distRange.start();
129  const ContextID ctx = pkt->req->contextId();
130 
131  DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
132 
133  const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize());
134 
135  switch (pkt->getSize()) {
136  case 1:
137  pkt->set<uint8_t>(resp);
138  break;
139  case 2:
140  pkt->set<uint16_t>(resp);
141  break;
142  case 4:
143  pkt->set<uint32_t>(resp);
144  break;
145  default:
146  panic("Invalid size while reading Distributor regs in GIC: %d\n",
147  pkt->getSize());
148  }
149 
150  pkt->makeAtomicResponse();
151  return distPioDelay;
152 }
153 
154 uint32_t
155 Pl390::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
156 {
157  if (GICD_IGROUPR.contains(daddr)) {
158  return 0; // unimplemented; RAZ (read as zero)
159  }
160 
161  if (GICD_ISENABLER.contains(daddr)) {
162  uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
163  assert(ix < 32);
164  return getIntEnabled(ctx, ix);
165  }
166 
167  if (GICD_ICENABLER.contains(daddr)) {
168  uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
169  assert(ix < 32);
170  return getIntEnabled(ctx, ix);
171  }
172 
173  if (GICD_ISPENDR.contains(daddr)) {
174  uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
175  assert(ix < 32);
176  return getPendingInt(ctx, ix);
177  }
178 
179  if (GICD_ICPENDR.contains(daddr)) {
180  uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
181  assert(ix < 32);
182  return getPendingInt(ctx, ix);
183  }
184 
185  if (GICD_ISACTIVER.contains(daddr)) {
186  uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
187  assert(ix < 32);
188  return getActiveInt(ctx, ix);
189  }
190 
191  if (GICD_ICACTIVER.contains(daddr)) {
192  uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
193  assert(ix < 32);
194  return getActiveInt(ctx, ix);
195  }
196 
197  if (GICD_IPRIORITYR.contains(daddr)) {
198  Addr int_num = daddr - GICD_IPRIORITYR.start();
199  assert(int_num < INT_LINES_MAX);
200  DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",int_num);
201 
202  switch (resp_sz) {
203  default: // will panic() after return to caller anyway
204  case 1:
205  return getIntPriority(ctx, int_num);
206  case 2:
207  assert((int_num + 1) < INT_LINES_MAX);
208  return (getIntPriority(ctx, int_num) |
209  getIntPriority(ctx, int_num+1) << 8);
210  case 4:
211  assert((int_num + 3) < INT_LINES_MAX);
212  return (getIntPriority(ctx, int_num) |
213  getIntPriority(ctx, int_num+1) << 8 |
214  getIntPriority(ctx, int_num+2) << 16 |
215  getIntPriority(ctx, int_num+3) << 24);
216  }
217  }
218 
219  if (GICD_ITARGETSR.contains(daddr)) {
220  Addr int_num = daddr - GICD_ITARGETSR.start();
221  DPRINTF(GIC, "Reading processor target register for int# %#x \n",
222  int_num);
223  assert(int_num < INT_LINES_MAX);
224 
225  if (resp_sz == 1) {
226  return getCpuTarget(ctx, int_num);
227  } else {
228  assert(resp_sz == 4);
229  int_num = mbits(int_num, 31, 2);
230  return (getCpuTarget(ctx, int_num) |
231  getCpuTarget(ctx, int_num+1) << 8 |
232  getCpuTarget(ctx, int_num+2) << 16 |
233  getCpuTarget(ctx, int_num+3) << 24) ;
234  }
235  }
236 
237  if (GICD_ICFGR.contains(daddr)) {
238  uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
239  assert(ix < 64);
242  return intConfig[ix];
243  }
244 
245  switch(daddr) {
246  case GICD_CTLR:
247  return enabled;
248  case GICD_TYPER:
249  /* The 0x100 is a made-up flag to show that gem5 extensions
250  * are available,
251  * write 0x200 to this register to enable it. */
252  return (((sys->numRunningContexts() - 1) << 5) |
253  (itLines/INT_BITS_MAX -1) |
254  (haveGem5Extensions ? 0x100 : 0x0));
255  default:
256  panic("Tried to read Gic distributor at offset %#x\n", daddr);
257  break;
258  }
259 }
260 
261 Tick
263 {
264  const Addr daddr = pkt->getAddr() - cpuRange.start();
265 
266  assert(pkt->req->hasContextId());
267  const ContextID ctx = pkt->req->contextId();
268  assert(ctx < sys->numRunningContexts());
269 
270  DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr,
271  ctx);
272 
273  pkt->set<uint32_t>(readCpu(ctx, daddr));
274 
275  pkt->makeAtomicResponse();
276  return cpuPioDelay;
277 }
278 
279 uint32_t
281 {
282  switch(daddr) {
283  case GICC_IIDR:
284  return 0;
285  case GICC_CTLR:
286  return cpuEnabled[ctx];
287  case GICC_PMR:
288  return cpuPriority[ctx];
289  case GICC_BPR:
290  return cpuBpr[ctx];
291  case GICC_IAR:
292  if (enabled && cpuEnabled[ctx]) {
293  int active_int = cpuHighestInt[ctx];
294  IAR iar = 0;
295  iar.ack_id = active_int;
296  iar.cpu_id = 0;
297  if (active_int < SGI_MAX) {
298  // this is a software interrupt from another CPU
299  if (!gem5ExtensionsEnabled) {
300  panic_if(!cpuSgiPending[active_int],
301  "Interrupt %d active but no CPU generated it?\n",
302  active_int);
303  for (int x = 0; x < sys->numRunningContexts(); x++) {
304  // See which CPU generated the interrupt
305  uint8_t cpugen =
306  bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
307  if (cpugen & (1 << ctx)) {
308  iar.cpu_id = x;
309  break;
310  }
311  }
312  uint64_t sgi_num = ULL(1) << (ctx + 8 * iar.cpu_id);
313  cpuSgiActive[iar.ack_id] |= sgi_num;
314  cpuSgiPending[iar.ack_id] &= ~sgi_num;
315  } else {
316  uint64_t sgi_num = ULL(1) << iar.ack_id;
317  cpuSgiActiveExt[ctx] |= sgi_num;
318  cpuSgiPendingExt[ctx] &= ~sgi_num;
319  }
320  } else if (active_int < (SGI_MAX + PPI_MAX) ) {
321  uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX);
322  cpuPpiActive[ctx] |= int_num;
323  updateRunPri();
324  cpuPpiPending[ctx] &= ~int_num;
325 
326  } else {
327  uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]);
328  getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num;
329  updateRunPri();
331  &= ~int_num;
332  }
333 
334  DPRINTF(Interrupt,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
335  ctx, iar.ack_id, iar.cpu_id, iar);
337  updateIntState(-1);
339  return iar;
340  } else {
341  return SPURIOUS_INT;
342  }
343 
344  break;
345  case GICC_RPR:
346  return iccrpr[0];
347  case GICC_HPPIR:
348  panic("Need to implement HPIR");
349  break;
350  default:
351  panic("Tried to read Gic cpu at offset %#x\n", daddr);
352  break;
353  }
354 }
355 
356 Tick
358 {
359  const Addr daddr = pkt->getAddr() - distRange.start();
360 
361  assert(pkt->req->hasContextId());
362  const ContextID ctx = pkt->req->contextId();
363  const size_t data_sz = pkt->getSize();
364 
365  uint32_t pkt_data M5_VAR_USED;
366  switch (data_sz)
367  {
368  case 1:
369  pkt_data = pkt->get<uint8_t>();
370  break;
371  case 2:
372  pkt_data = pkt->get<uint16_t>();
373  break;
374  case 4:
375  pkt_data = pkt->get<uint32_t>();
376  break;
377  default:
378  panic("Invalid size when writing to priority regs in Gic: %d\n",
379  data_sz);
380  }
381 
382  DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
383  daddr, data_sz, pkt_data);
384 
385  writeDistributor(ctx, daddr, pkt_data, data_sz);
386 
387  pkt->makeAtomicResponse();
388  return distPioDelay;
389 }
390 
391 void
393  size_t data_sz)
394 {
395  if (GICD_IGROUPR.contains(daddr)) {
396  return; // unimplemented; WI (writes ignored)
397  }
398 
399  if (GICD_ISENABLER.contains(daddr)) {
400  uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
401  assert(ix < 32);
402  getIntEnabled(ctx, ix) |= data;
403  return;
404  }
405 
406  if (GICD_ICENABLER.contains(daddr)) {
407  uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
408  assert(ix < 32);
409  getIntEnabled(ctx, ix) &= ~data;
410  return;
411  }
412 
413  if (GICD_ISPENDR.contains(daddr)) {
414  uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
415  auto mask = data;
416  if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
417  getPendingInt(ctx, ix) |= mask;
418  updateIntState(ix);
419  return;
420  }
421 
422  if (GICD_ICPENDR.contains(daddr)) {
423  uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
424  auto mask = data;
425  if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
426  getPendingInt(ctx, ix) &= ~mask;
427  updateIntState(ix);
428  return;
429  }
430 
431  if (GICD_ISACTIVER.contains(daddr)) {
432  uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
433  getActiveInt(ctx, ix) |= data;
434  return;
435  }
436 
437  if (GICD_ICACTIVER.contains(daddr)) {
438  uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
439  getActiveInt(ctx, ix) &= ~data;
440  return;
441  }
442 
443  if (GICD_IPRIORITYR.contains(daddr)) {
444  Addr int_num = daddr - GICD_IPRIORITYR.start();
445  switch(data_sz) {
446  case 1:
447  getIntPriority(ctx, int_num) = data;
448  break;
449  case 2: {
450  getIntPriority(ctx, int_num) = bits(data, 7, 0);
451  getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
452  break;
453  }
454  case 4: {
455  getIntPriority(ctx, int_num) = bits(data, 7, 0);
456  getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
457  getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
458  getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
459  break;
460  }
461  default:
462  panic("Invalid size when writing to priority regs in Gic: %d\n",
463  data_sz);
464  }
465 
466  updateIntState(-1);
467  updateRunPri();
468  return;
469  }
470 
471  if (GICD_ITARGETSR.contains(daddr)) {
472  Addr int_num = daddr - GICD_ITARGETSR.start();
473  // Interrupts 0-31 are read only
474  unsigned offset = SGI_MAX + PPI_MAX;
475  if (int_num >= offset) {
476  unsigned ix = int_num - offset; // index into cpuTarget array
477  if (data_sz == 1) {
478  cpuTarget[ix] = data & 0xff;
479  } else {
480  assert (data_sz == 4);
481  cpuTarget[ix] = bits(data, 7, 0);
482  cpuTarget[ix+1] = bits(data, 15, 8);
483  cpuTarget[ix+2] = bits(data, 23, 16);
484  cpuTarget[ix+3] = bits(data, 31, 24);
485  }
486  updateIntState(int_num >> 2);
487  }
488  return;
489  }
490 
491  if (GICD_ICFGR.contains(daddr)) {
492  uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
493  assert(ix < INT_BITS_MAX*2);
494  intConfig[ix] = data;
495  if (data & NN_CONFIG_MASK)
496  warn("GIC N:N mode selected and not supported at this time\n");
497  return;
498  }
499 
500  switch(daddr) {
501  case GICD_CTLR:
502  enabled = data;
503  DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
504  break;
505  case GICD_TYPER:
506  /* 0x200 is a made-up flag to enable gem5 extension functionality.
507  * This reg is not normally written.
508  */
509  gem5ExtensionsEnabled = (data & 0x200) && haveGem5Extensions;
510  DPRINTF(GIC, "gem5 extensions %s\n",
511  gem5ExtensionsEnabled ? "enabled" : "disabled");
512  break;
513  case GICD_SGIR:
514  softInt(ctx, data);
515  break;
516  default:
517  panic("Tried to write Gic distributor at offset %#x\n", daddr);
518  break;
519  }
520 }
521 
522 Tick
524 {
525  const Addr daddr = pkt->getAddr() - cpuRange.start();
526 
527  assert(pkt->req->hasContextId());
528  const ContextID ctx = pkt->req->contextId();
529  const uint32_t data = pkt->get<uint32_t>();
530 
531  DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
532  ctx, daddr, data);
533 
534  writeCpu(ctx, daddr, data);
535 
536  pkt->makeAtomicResponse();
537  return cpuPioDelay;
538 }
539 
540 void
541 Pl390::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
542 {
543  switch(daddr) {
544  case GICC_CTLR:
545  cpuEnabled[ctx] = data;
546  break;
547  case GICC_PMR:
548  cpuPriority[ctx] = data;
549  break;
550  case GICC_BPR: {
551  auto bpr = data & 0x7;
552  if (bpr < GICC_BPR_MINIMUM)
553  bpr = GICC_BPR_MINIMUM;
554  cpuBpr[ctx] = bpr;
555  break;
556  }
557  case GICC_EOIR: {
558  const IAR iar = data;
559  if (iar.ack_id < SGI_MAX) {
560  // Clear out the bit that corresponds to the cleared int
561  uint64_t clr_int = ULL(1) << (ctx + 8 * iar.cpu_id);
562  if (!(cpuSgiActive[iar.ack_id] & clr_int) &&
563  !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id)))
564  panic("Done handling a SGI that isn't active?\n");
566  cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id);
567  else
568  cpuSgiActive[iar.ack_id] &= ~clr_int;
569  } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
570  uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
571  if (!(cpuPpiActive[ctx] & int_num))
572  panic("CPU %d Done handling a PPI interrupt "
573  "that isn't active?\n", ctx);
574  cpuPpiActive[ctx] &= ~int_num;
575  } else {
576  uint32_t int_num = 1 << intNumToBit(iar.ack_id);
577  if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num))
578  warn("Done handling interrupt that isn't active: %d\n",
579  intNumToBit(iar.ack_id));
580  getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num;
581  }
582  updateRunPri();
583  DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
584  ctx, iar.ack_id, iar.cpu_id);
585  break;
586  }
587  default:
588  panic("Tried to write Gic cpu at offset %#x\n", daddr);
589  break;
590  }
591  if (cpuEnabled[ctx]) updateIntState(-1);
592 }
593 
596  if (bankedRegs.size() <= ctx)
597  bankedRegs.resize(ctx + 1);
598 
599  if (!bankedRegs[ctx])
600  bankedRegs[ctx] = new BankedRegs;
601  return *bankedRegs[ctx];
602 }
603 
604 void
606 {
607  if (gem5ExtensionsEnabled) {
608  switch (swi.list_type) {
609  case 0: {
610  // interrupt cpus specified
611  int dest = swi.cpu_list;
612  DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
613  ctx, dest);
614  if (cpuEnabled[dest]) {
615  cpuSgiPendingExt[dest] |= (1 << swi.sgi_id);
616  DPRINTF(IPI, "SGI[%d]=%#x\n", dest,
617  cpuSgiPendingExt[dest]);
618  }
619  } break;
620  case 1: {
621  // interrupt all
622  for (int i = 0; i < sys->numContexts(); i++) {
623  DPRINTF(IPI, "Processing CPU %d\n", i);
624  if (!cpuEnabled[i])
625  continue;
626  cpuSgiPendingExt[i] |= 1 << swi.sgi_id;
627  DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
628  cpuSgiPendingExt[i]);
629  }
630  } break;
631  case 2: {
632  // Interrupt requesting cpu only
633  DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
634  ctx, ctx);
635  if (cpuEnabled[ctx]) {
636  cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id);
637  DPRINTF(IPI, "SGI[%d]=%#x\n", ctx,
638  cpuSgiPendingExt[ctx]);
639  }
640  } break;
641  }
642  } else {
643  switch (swi.list_type) {
644  case 1:
645  // interrupt all
646  uint8_t cpu_list;
647  cpu_list = 0;
648  for (int x = 0; x < sys->numContexts(); x++)
649  cpu_list |= cpuEnabled[x] ? 1 << x : 0;
650  swi.cpu_list = cpu_list;
651  break;
652  case 2:
653  // interrupt requesting cpu only
654  swi.cpu_list = 1 << ctx;
655  break;
656  // else interrupt cpus specified
657  }
658 
659  DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx,
660  swi.cpu_list);
661  for (int i = 0; i < sys->numContexts(); i++) {
662  DPRINTF(IPI, "Processing CPU %d\n", i);
663  if (!cpuEnabled[i])
664  continue;
665  if (swi.cpu_list & (1 << i))
666  cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx);
667  DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
668  cpuSgiPending[swi.sgi_id]);
669  }
670  }
671  updateIntState(-1);
672 }
673 
674 uint64_t
676 {
677  if (cpu > sys->numContexts())
678  panic("Invalid CPU ID\n");
679  return ULL(0x0101010101010101) << cpu;
680 }
681 
682 uint8_t
684 {
685  // see Table 3-2 in IHI0048B.b (GICv2)
686  // mask some low-order priority bits per BPR value
687  // NB: the GIC prioritization scheme is upside down:
688  // lower values are higher priority; masking off bits
689  // actually creates a higher priority, not lower.
690  return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu]));
691 }
692 
693 void
695 {
696  for (int cpu = 0; cpu < sys->numContexts(); cpu++) {
697  if (!cpuEnabled[cpu])
698  continue;
699 
700  /*@todo use hint to do less work. */
701  int highest_int = SPURIOUS_INT;
702  // Priorities below that set in GICC_PMR can be ignored
703  uint8_t highest_pri = getCpuPriority(cpu);
704 
705  // Check SGIs
706  for (int swi = 0; swi < SGI_MAX; swi++) {
707  if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu])
708  continue;
709  if ((cpuSgiPending[swi] & genSwiMask(cpu)) ||
710  (cpuSgiPendingExt[cpu] & (1 << swi)))
711  if (highest_pri > getIntPriority(cpu, swi)) {
712  highest_pri = getIntPriority(cpu, swi);
713  highest_int = swi;
714  }
715  }
716 
717  // Check PPIs
718  if (cpuPpiPending[cpu]) {
719  for (int ppi = 0; ppi < PPI_MAX; ppi++) {
720  if (cpuPpiPending[cpu] & (1 << ppi))
721  if (highest_pri > getIntPriority(cpu, SGI_MAX + ppi)) {
722  highest_pri = getIntPriority(cpu, SGI_MAX + ppi);
723  highest_int = SGI_MAX + ppi;
724  }
725  }
726  }
727 
728  bool mp_sys = sys->numRunningContexts() > 1;
729  // Check other ints
730  for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
731  if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) {
732  for (int y = 0; y < INT_BITS_MAX; y++) {
733  uint32_t int_nm = x * INT_BITS_MAX + y;
734  DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
735  /* Set current pending int as highest int for current cpu
736  if the interrupt's priority higher than current priority
737  and if current cpu is the target (for mp configs only)
738  */
739  if ((bits(getIntEnabled(cpu, x), y)
740  &bits(getPendingInt(cpu, x), y)) &&
741  (getIntPriority(cpu, int_nm) < highest_pri))
742  if ((!mp_sys) ||
744  ? (getCpuTarget(cpu, int_nm) == cpu)
745  : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) {
746  highest_pri = getIntPriority(cpu, int_nm);
747  highest_int = int_nm;
748  }
749  }
750  }
751  }
752 
753  cpuHighestInt[cpu] = highest_int;
754 
755  if (highest_int == SPURIOUS_INT)
756  continue;
757 
758  /* @todo make this work for more than one cpu, need to handle 1:N, N:N
759  * models */
760  if (enabled && cpuEnabled[cpu] &&
761  (highest_pri < getCpuPriority(cpu)) &&
762  !(getActiveInt(cpu, intNumToWord(highest_int))
763  & (1 << intNumToBit(highest_int)))) {
764 
765  DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
766  cpu);
767  postInt(cpu, curTick() + intLatency);
768  }
769  }
770 }
771 
772 void
774 {
775  for (int cpu = 0; cpu < sys->numContexts(); cpu++) {
776  if (!cpuEnabled[cpu])
777  continue;
778  uint8_t maxPriority = 0xff;
779  for (int i = 0; i < itLines; i++) {
780  if (i < SGI_MAX) {
781  if (((cpuSgiActive[i] & genSwiMask(cpu)) ||
782  (cpuSgiActiveExt[cpu] & (1 << i))) &&
783  (getIntPriority(cpu, i) < maxPriority))
784  maxPriority = getIntPriority(cpu, i);
785  } else if (i < (SGI_MAX + PPI_MAX)) {
786  if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
787  (getIntPriority(cpu, i) < maxPriority))
788  maxPriority = getIntPriority(cpu, i);
789 
790  } else {
791  if (getActiveInt(cpu, intNumToWord(i))
792  & (1 << intNumToBit(i)))
793  if (getIntPriority(cpu, i) < maxPriority)
794  maxPriority = getIntPriority(cpu, i);
795  }
796  }
797  iccrpr[cpu] = maxPriority;
798  }
799 }
800 
801 void
802 Pl390::sendInt(uint32_t num)
803 {
804  uint8_t target = getCpuTarget(0, num);
805  DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
806  num, target);
807  if ((target & (target - 1)) && !gem5ExtensionsEnabled)
808  panic("Multiple targets for peripheral interrupts is not supported\n");
809  panic_if(num < SGI_MAX + PPI_MAX,
810  "sentInt() must only be used for interrupts 32 and higher");
811  getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num);
813 }
814 
815 void
816 Pl390::sendPPInt(uint32_t num, uint32_t cpu)
817 {
818  DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n",
819  num, cpu);
820  cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
822 }
823 
824 void
825 Pl390::clearInt(uint32_t number)
826 {
827  /* @todo assume edge triggered only at the moment. Nothing to do. */
828 }
829 
830 void
831 Pl390::clearPPInt(uint32_t num, uint32_t cpu)
832 {
833  DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n",
834  num, cpu);
835  cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX));
837 }
838 
839 void
840 Pl390::postInt(uint32_t cpu, Tick when)
841 {
842  if (!(postIntEvent[cpu]->scheduled())) {
844  eventq->schedule(postIntEvent[cpu], when);
845  }
846 }
847 
848 void
850 {
853  assert(pendingDelayedInterrupts >= 0);
854  if (pendingDelayedInterrupts == 0)
855  signalDrainDone();
856 }
857 
860 {
861  if (pendingDelayedInterrupts == 0) {
862  return DrainState::Drained;
863  } else {
864  return DrainState::Draining;
865  }
866 }
867 
868 void
870 {
871  DPRINTF(Checkpoint, "Serializing Arm GIC\n");
872 
894 
895  for (uint32_t i=0; i < bankedRegs.size(); ++i) {
896  if (!bankedRegs[i])
897  continue;
898  bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i));
899  }
900 }
901 
902 void
904 {
909 }
910 
911 void
913 {
914  DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
915 
936 
937  // Handle checkpoints from before we drained the GIC to prevent
938  // in-flight interrupts.
939  if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) {
940  Tick interrupt_time[CPU_MAX];
941  UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
942 
943  for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
944  if (interrupt_time[cpu])
945  schedule(postIntEvent[cpu], interrupt_time[cpu]);
946  }
947  }
948 
950  gem5ExtensionsEnabled = false;
951 
952  for (uint32_t i=0; i < CPU_MAX; ++i) {
953  ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i));
956  }
957  }
958 }
959 
960 void
962 {
967 }
968 
969 Pl390 *
970 Pl390Params::create()
971 {
972  return new Pl390(this);
973 }
974 
975 /* Functions for debugging and testing */
976 void
977 Pl390::driveSPI(uint32_t spiVect)
978 {
979  DPRINTF(GIC, "Received SPI Vector:%x Enable: %d\n", spiVect, irqEnable);
980  getPendingInt(0, 1) |= spiVect;
981  if (irqEnable && enabled) {
982  updateIntState(-1);
983  }
984 }
985 
986 void
987 Pl390::driveIrqEn( bool state)
988 {
989  irqEnable = state;
990  DPRINTF(GIC, " Enabling Irq\n");
991  updateIntState(-1);
992 }
993 
994 void
996 {
997  if (irqEnable && !(!enabled && cpuEnabled[0])) {
998  if (state) {
999  DPRINTF(GIC, "Driving Legacy Irq\n");
1001  }
1002  else platform->intrctrl->clear(0, ArmISA::INT_IRQ, 0);
1003  }
1004 }
1005 
1006 void
1008 {
1009  if (state)
1011  else platform->intrctrl->clear(0, ArmISA::INT_FIQ, 0);
1012 }
IntrControl * intrctrl
Pointer to the interrupt controller.
Definition: platform.hh:56
EventQueue * eventq
A pointer to this object's event queue.
Definition: eventq.hh:714
#define DPRINTF(x,...)
Definition: trace.hh:212
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:398
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu() ...
Definition: gic_pl390.cc:113
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
Definition: gic_pl390.hh:233
void set(T v, ByteOrder endian)
Set the value in the data pointer to v using the specified endianness.
void clearInt(uint32_t number) override
Clear an interrupt from a device that is connected to the GIC.
Definition: gic_pl390.cc:825
Platform * platform
Platform this GIC belongs to.
Definition: base_gic.hh:92
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
Definition: gic_pl390.hh:241
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:227
std::vector< BankedRegs * > bankedRegs
Definition: gic_pl390.hh:187
Bitfield< 7 > i
Definition: miscregs.hh:1378
ContextID contextId() const
Accessor function for context ID.
Definition: request.hh:694
DrainState
Object drain/handover states.
Definition: drain.hh:71
uint32_t intEnabled[INT_BITS_MAX-1]
GICD_I{S,C}ENABLER{1..31} interrupt enable bits for global interrupts 1b per interrupt, 32 bits per word, 31 words.
Definition: gic_pl390.hh:194
static const AddrRange GICD_ITARGETSR
Definition: gic_pl390.hh:82
#define panic(...)
Definition: misc.hh:153
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: gic_pl390.cc:869
Running normally.
#define UNSERIALIZE_OPT_SCALAR(scalar)
Definition: serialize.hh:146
uint32_t itLines
Number of itLines enabled.
Definition: gic_pl390.hh:160
void post(int cpu_id, int int_num, int index)
Definition: intr_control.cc:50
EndBitUnion(IAR) protected const AddrRange cpuRange
Address range for the distributor interface.
Definition: gic_pl390.hh:128
uint8_t getCpuPriority(unsigned cpu)
Definition: gic_pl390.cc:683
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
Definition: gic_pl390.cc:523
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
Definition: gic_pl390.hh:157
ip6_addr_t addr
Definition: inet.hh:335
panic_if(!root,"Invalid expression\n")
static const AddrRange GICD_ISACTIVER
Definition: gic_pl390.hh:79
static const int SPURIOUS_INT
Definition: gic_pl390.hh:110
static const int INT_BITS_MAX
Definition: gic_pl390.hh:111
Bitfield< 23, 16 > cpu_list
Definition: gic_pl390.hh:121
uint32_t pendingInt
GICD_I{S,C}PENDR0 interrupt pending bits for first 32 interrupts, 1b per interrupt.
Definition: gic_pl390.hh:170
const Tick intLatency
Latency for a interrupt to get to CPU.
Definition: gic_pl390.hh:147
Bitfield< 23, 0 > offset
Definition: types.hh:149
static const int CPU_MAX
Definition: gic_pl390.hh:109
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:328
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu() ...
Definition: gic_pl390.cc:99
static const AddrRange GICD_ISENABLER
Definition: gic_pl390.hh:75
static const AddrRange GICD_ISPENDR
Definition: gic_pl390.hh:77
const Tick distPioDelay
Latency for a distributor operation.
Definition: gic_pl390.hh:141
static const AddrRange GICD_ICACTIVER
Definition: gic_pl390.hh:80
void clearPPInt(uint32_t num, uint32_t cpu) override
Definition: gic_pl390.cc:831
const bool haveGem5Extensions
Are gem5 extensions available?
Definition: gic_pl390.hh:154
T get(ByteOrder endian) const
Get the data in the packet byte swapped from the specified endianness.
int numRunningContexts()
Return number of running (non-halted) thread contexts in system.
Definition: system.cc:278
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
Definition: gic_pl390.hh:196
const char data[]
Definition: circlebuf.cc:43
bool hasContextId() const
Definition: request.hh:687
int intNumToBit(int num) const
Definition: gic_pl390.hh:331
uint32_t activeInt
GICD_I{S,C}ACTIVER0 interrupt active bits for first 32 interrupts, 1b per interrupt.
Definition: gic_pl390.hh:174
#define warn(...)
Definition: misc.hh:219
uint32_t intEnabled
GICD_I{S,C}ENABLER0 interrupt enable bits for first 32 interrupts, 1b per interrupt.
Definition: gic_pl390.hh:166
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
Definition: gic_pl390.cc:773
The AddrRange class encapsulates an address range, and supports a number of tests to check if two ran...
Definition: addr_range.hh:72
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
Definition: gic_pl390.hh:307
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:145
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
Definition: gic_pl390.hh:107
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
Definition: gic_pl390.hh:290
Tick curTick()
The current simulated tick.
Definition: core.hh:47
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
Definition: gic_pl390.hh:209
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
void driveLegFIQ(bool state)
Definition: gic_pl390.cc:1007
uint8_t cpuTarget[GLOBAL_INT_LINES]
GICD_ITARGETSR{8..255} an 8 bit cpu target id for each global interrupt.
Definition: gic_pl390.hh:253
void driveLegIRQ(bool state)
Definition: gic_pl390.cc:995
bool enabled
Gic enabled.
Definition: gic_pl390.hh:151
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
Definition: gic_pl390.cc:802
void makeAtomicResponse()
Definition: packet.hh:857
uint64_t Tick
Tick count type.
Definition: types.hh:63
uint32_t pendingInt[INT_BITS_MAX-1]
GICD_I{S,C}PENDR{1..31} interrupt pending bits for global interrupts 1b per interrupt, 32 bits per word, 31 words.
Definition: gic_pl390.hh:207
uint32_t cpuSgiActiveExt[CPU_MAX]
Definition: gic_pl390.hh:303
uint32_t cpuSgiPendingExt[CPU_MAX]
SGI pending arrays for gem5 GIC extension mode, which instead keeps 16 SGI pending bits for each of t...
Definition: gic_pl390.hh:302
void driveSPI(uint32_t spi)
Definition: gic_pl390.cc:977
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: gic_pl390.cc:903
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:158
static const AddrRange GICD_ICPENDR
Definition: gic_pl390.hh:78
const RequestPtr req
A pointer to the original request.
Definition: packet.hh:304
uint8_t getCpuTarget(ContextID ctx, uint32_t ix)
Definition: gic_pl390.hh:255
uint8_t intPriority[GLOBAL_INT_LINES]
GICD_IPRIORITYR{8..255} an 8 bit priority (lower is higher priority) for each of the global (not repl...
Definition: gic_pl390.hh:239
Registers "banked for each connected processor" per ARM IHI0048B.
Definition: gic_pl390.hh:163
uint32_t cpuPpiActive[CPU_MAX]
Definition: gic_pl390.hh:308
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:142
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
Definition: gic_pl390.hh:287
Draining buffers pending serialization/handover.
#define ULL(N)
uint64_t constant
Definition: types.hh:50
struct BaseGicParams Params
Definition: base_gic.hh:54
System * sys
Definition: io_device.hh:87
DrainState drain() override
Notify an object that it needs to drain its state.
Definition: gic_pl390.cc:859
A Packet is used to encapsulate a transfer between two objects in the memory system (e...
Definition: packet.hh:245
int numContexts()
Definition: system.hh:208
bool cpuEnabled[CPU_MAX]
CPU enabled.
Definition: gic_pl390.hh:280
bool enabled()
Definition: statistics.cc:502
Implementation of a PL390 GIC.
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
Definition: gic_pl390.cc:840
uint8_t cpuPriority[CPU_MAX]
CPU priority.
Definition: gic_pl390.hh:283
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:143
Pl390(const Params *p)
Definition: gic_pl390.cc:66
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:161
static const int NumArgumentRegs M5_VAR_USED
Definition: process.cc:83
static const int INT_LINES_MAX
Definition: gic_pl390.hh:112
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
Definition: gic_pl390.hh:223
int intNumToWord(int num) const
Definition: gic_pl390.hh:330
uint32_t intConfig[INT_BITS_MAX *2]
2 bit per interrupt signaling if it's level or edge sensitive and if it is 1:N or N:N ...
Definition: gic_pl390.hh:277
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
Definition: gic_pl390.hh:104
Declaration of the Packet class.
std::ostream CheckpointOut
Definition: serialize.hh:67
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
Definition: gic_pl390.hh:296
static const AddrRange GICD_ICFGR
Definition: gic_pl390.hh:83
uint8_t intPriority[SGI_MAX+PPI_MAX]
GICD_IPRIORITYR{0..7} interrupt priority for SGIs and PPIs.
Definition: gic_pl390.hh:178
bool sectionExists(const std::string &section)
Definition: serialize.cc:724
uint32_t activeInt[INT_BITS_MAX-1]
GICD_I{S,C}ACTIVER{1..31} interrupt active bits for global interrupts 1b per interrupt, 32 bits per word, 31 words.
Definition: gic_pl390.hh:221
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
Definition: gic_pl390.cc:357
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
Definition: eventq_impl.hh:42
static const AddrRange GICD_IPRIORITYR
Definition: gic_pl390.hh:81
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:267
uint64_t cpuSgiActive[SGI_MAX]
Definition: gic_pl390.hh:297
static const std::string & currentSection()
Get the fully-qualified name of the active section.
Definition: serialize.cc:652
void driveIrqEn(bool state)
Definition: gic_pl390.cc:987
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: gic_pl390.cc:912
bool irqEnable
IRQ Enable Used for debug.
Definition: gic_pl390.hh:311
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
Definition: gic_pl390.cc:126
void schedule(Event &event, Tick when)
Definition: eventq.hh:728
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: gic_pl390.cc:961
static const AddrRange GICD_IGROUPR
Definition: gic_pl390.hh:74
static const AddrRange GICD_ICENABLER
Definition: gic_pl390.hh:76
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
Definition: gic_pl390.cc:675
static const int GLOBAL_INT_LINES
Definition: gic_pl390.hh:113
bool entryExists(const std::string &section, const std::string &entry)
Definition: serialize.cc:697
int pendingDelayedInterrupts
Definition: gic_pl390.hh:358
Bitfield< 3, 0 > mask
Definition: types.hh:64
PostIntEvent * postIntEvent[CPU_MAX]
Definition: gic_pl390.hh:357
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
Definition: gic_pl390.cc:816
unsigned getSize() const
Definition: packet.hh:649
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Lin...
Definition: gic_pl390.hh:117
T mbits(T val, int first, int last)
Mask off the given bits in place like bits() but without shifting.
Definition: bitfield.hh:91
T bits(T val, int first, int last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it...
Definition: bitfield.hh:67
void clear(int cpu_id, int int_num, int index)
Definition: intr_control.cc:59
Scoped checkpoint section helper class.
Definition: serialize.hh:240
Bitfield< 0 > p
void softInt(ContextID ctx, SWI swi)
software generated interrupt
Definition: gic_pl390.cc:605
Bitfield< 1 > x
Definition: types.hh:105
static const int SGI_MAX
Definition: gic_pl390.hh:100
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
Definition: gic_pl390.cc:262
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
Definition: gic_pl390.cc:849
int ContextID
Globally unique thread context ID.
Definition: types.hh:175
BankedRegs & getBankedRegs(ContextID)
Definition: gic_pl390.cc:595
const Tick cpuPioDelay
Latency for a cpu operation.
Definition: gic_pl390.hh:144
Addr getAddr() const
Definition: packet.hh:639
static const int PPI_MAX
Definition: gic_pl390.hh:101
void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
Definition: gic_pl390.cc:694

Generated on Fri Jun 9 2017 13:03:45 for gem5 by doxygen 1.8.6