gem5  v22.1.0.0
gic_v2.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2010, 2013, 2015-2018, 2020-2022 Arm Limited
3  * All rights reserved
4  *
5  * The license below extends only to copyright in the software and shall
6  * not be construed as granting a license to any other intellectual
7  * property including but not limited to intellectual property relating
8  * to a hardware implementation of the functionality of the software
9  * licensed hereunder. You may use the software subject to the license
10  * terms below provided that you ensure that this notice is replicated
11  * unmodified and in its entirety in all distributions of the software,
12  * modified or unmodified, in source code or in binary form.
13  *
14  * Copyright (c) 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 
41 #include "dev/arm/gic_v2.hh"
42 
43 #include "base/compiler.hh"
44 #include "base/trace.hh"
45 #include "cpu/base.hh"
46 #include "debug/Checkpoint.hh"
47 #include "debug/GIC.hh"
48 #include "debug/IPI.hh"
49 #include "debug/Interrupt.hh"
50 #include "mem/packet.hh"
51 #include "mem/packet_access.hh"
52 
53 namespace gem5
54 {
55 
56 const AddrRange GicV2::GICD_IGROUPR (0x080, 0x100);
57 const AddrRange GicV2::GICD_ISENABLER (0x100, 0x180);
58 const AddrRange GicV2::GICD_ICENABLER (0x180, 0x200);
59 const AddrRange GicV2::GICD_ISPENDR (0x200, 0x280);
60 const AddrRange GicV2::GICD_ICPENDR (0x280, 0x300);
61 const AddrRange GicV2::GICD_ISACTIVER (0x300, 0x380);
62 const AddrRange GicV2::GICD_ICACTIVER (0x380, 0x400);
63 const AddrRange GicV2::GICD_IPRIORITYR(0x400, 0x800);
64 const AddrRange GicV2::GICD_ITARGETSR (0x800, 0xc00);
65 const AddrRange GicV2::GICD_ICFGR (0xc00, 0xd00);
66 
67 void
70  ContextID ctx, Addr daddr)
71 {
72  auto val = from->readDistributor(ctx, daddr);
73  DPRINTF(GIC, "copy dist 0x%x 0x%08x\n", daddr, val);
74  to->writeDistributor(ctx, daddr, val);
75 }
76 
77 void
80  ContextID ctx, Addr daddr)
81 {
82  auto val = from->readCpu(ctx, daddr);
83  DPRINTF(GIC, "copy cpu 0x%x 0x%08x\n", daddr, val);
84  to->writeCpu(ctx, daddr, val);
85 }
86 
87 void
90  Addr daddr, size_t size)
91 {
92  for (int ctx = 0; ctx < sys->threads.size(); ++ctx)
93  for (auto a = daddr; a < daddr + size; a += 4)
94  copyDistRegister(from, to, ctx, a);
95 }
96 
97 void
99  Addr daddr, size_t size)
100 {
101  for (int ctx = 0; ctx < sys->threads.size(); ++ctx)
102  for (auto a = daddr; a < daddr + size; a += 4)
103  to->writeDistributor(ctx, a, 0xFFFFFFFF);
104 }
105 
106 void
109  Addr daddr, size_t size)
110 {
111  for (auto a = daddr; a < daddr + size; a += 4)
112  copyDistRegister(from, to, 0, a);
113 }
114 
115 void
117 {
118  for (auto a = daddr; a < daddr + size; a += 4)
119  to->writeDistributor(0, a, 0xFFFFFFFF);
120 }
121 
123  : BaseGic(p),
124  gicdPIDR(p.gicd_pidr),
125  gicdIIDR(p.gicd_iidr),
126  giccIIDR(p.gicc_iidr),
127  distRange(RangeSize(p.dist_addr, DIST_SIZE)),
128  cpuRange(RangeSize(p.cpu_addr, p.cpu_size)),
129  addrRanges{distRange, cpuRange},
130  distPioDelay(p.dist_pio_delay),
131  cpuPioDelay(p.cpu_pio_delay), intLatency(p.int_latency),
132  enabled(false), haveGem5Extensions(p.gem5_extensions),
133  itLines(p.it_lines),
134  intEnabled {}, pendingInt {}, activeInt {}, intGroup {},
135  intPriority {}, intConfig {}, cpuTarget {},
136  cpuSgiPending {}, cpuSgiActive {},
137  cpuSgiPendingExt {}, cpuSgiActiveExt {},
138  cpuPpiPending {}, cpuPpiActive {},
139  pendingDelayedInterrupts(0)
140 {
141  for (int x = 0; x < CPU_MAX; x++) {
142  iccrpr[x] = 0xff;
143  cpuControl[x] = 0;
144  cpuPriority[x] = 0xff;
146  // Initialize cpu highest int
148  postIntEvent[x] =
149  new EventFunctionWrapper([this, x]{ postDelayedInt(x); },
150  "Post Interrupt to CPU");
151  postFiqEvent[x] =
152  new EventFunctionWrapper([this, x]{ postDelayedFiq(x); },
153  "Post FIQ to CPU");
154  }
155  DPRINTF(Interrupt, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled(0),
156  cpuEnabled(1));
157 
158  gem5ExtensionsEnabled = false;
159 }
160 
162 {
163  for (int x = 0; x < CPU_MAX; x++) {
164  delete postIntEvent[x];
165  delete postFiqEvent[x];
166  }
167 }
168 
169 Tick
171 {
172  const Addr addr = pkt->getAddr();
173 
174  if (distRange.contains(addr))
175  return readDistributor(pkt);
176  else if (cpuRange.contains(addr))
177  return readCpu(pkt);
178  else
179  panic("Read to unknown address %#x\n", pkt->getAddr());
180 }
181 
182 
183 Tick
185 {
186  const Addr addr = pkt->getAddr();
187 
188  if (distRange.contains(addr))
189  return writeDistributor(pkt);
190  else if (cpuRange.contains(addr))
191  return writeCpu(pkt);
192  else
193  panic("Write to unknown address %#x\n", pkt->getAddr());
194 }
195 
196 Tick
198 {
199  const Addr daddr = pkt->getAddr() - distRange.start();
200  const ContextID ctx = pkt->req->contextId();
201 
202  DPRINTF(GIC, "gic distributor read register %#x\n", daddr);
203 
204  const uint32_t resp = readDistributor(ctx, daddr, pkt->getSize());
205 
206  switch (pkt->getSize()) {
207  case 1:
208  pkt->setLE<uint8_t>(resp);
209  break;
210  case 2:
211  pkt->setLE<uint16_t>(resp);
212  break;
213  case 4:
214  pkt->setLE<uint32_t>(resp);
215  break;
216  default:
217  panic("Invalid size while reading Distributor regs in GIC: %d\n",
218  pkt->getSize());
219  }
220 
221  pkt->makeAtomicResponse();
222  return distPioDelay;
223 }
224 
225 uint32_t
226 GicV2::readDistributor(ContextID ctx, Addr daddr, size_t resp_sz)
227 {
228  if (GICD_IGROUPR.contains(daddr)) {
229  uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2;
230  assert(ix < 32);
231  return getIntGroup(ctx, ix);
232  }
233 
234  if (GICD_ISENABLER.contains(daddr)) {
235  uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
236  assert(ix < 32);
237  return getIntEnabled(ctx, ix);
238  }
239 
240  if (GICD_ICENABLER.contains(daddr)) {
241  uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
242  assert(ix < 32);
243  return getIntEnabled(ctx, ix);
244  }
245 
246  if (GICD_ISPENDR.contains(daddr)) {
247  uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
248  assert(ix < 32);
249  return getPendingInt(ctx, ix);
250  }
251 
252  if (GICD_ICPENDR.contains(daddr)) {
253  uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
254  assert(ix < 32);
255  return getPendingInt(ctx, ix);
256  }
257 
258  if (GICD_ISACTIVER.contains(daddr)) {
259  uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
260  assert(ix < 32);
261  return getActiveInt(ctx, ix);
262  }
263 
264  if (GICD_ICACTIVER.contains(daddr)) {
265  uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
266  assert(ix < 32);
267  return getActiveInt(ctx, ix);
268  }
269 
270  if (GICD_IPRIORITYR.contains(daddr)) {
271  Addr int_num = daddr - GICD_IPRIORITYR.start();
272  assert(int_num < INT_LINES_MAX);
273  DPRINTF(Interrupt, "Reading interrupt priority at int# %#x \n",
274  int_num);
275 
276  switch (resp_sz) {
277  default: // will panic() after return to caller anyway
278  case 1:
279  return getIntPriority(ctx, int_num);
280  case 2:
281  assert((int_num + 1) < INT_LINES_MAX);
282  return (getIntPriority(ctx, int_num) |
283  getIntPriority(ctx, int_num+1) << 8);
284  case 4:
285  assert((int_num + 3) < INT_LINES_MAX);
286  return (getIntPriority(ctx, int_num) |
287  getIntPriority(ctx, int_num+1) << 8 |
288  getIntPriority(ctx, int_num+2) << 16 |
289  getIntPriority(ctx, int_num+3) << 24);
290  }
291  }
292 
293  if (GICD_ITARGETSR.contains(daddr)) {
294  Addr int_num = daddr - GICD_ITARGETSR.start();
295  DPRINTF(GIC, "Reading processor target register for int# %#x \n",
296  int_num);
297  assert(int_num < INT_LINES_MAX);
298 
299  if (resp_sz == 1) {
300  return getCpuTarget(ctx, int_num);
301  } else {
302  assert(resp_sz == 4);
303  int_num = mbits(int_num, 31, 2);
304  return (getCpuTarget(ctx, int_num) |
305  getCpuTarget(ctx, int_num+1) << 8 |
306  getCpuTarget(ctx, int_num+2) << 16 |
307  getCpuTarget(ctx, int_num+3) << 24) ;
308  }
309  }
310 
311  if (GICD_ICFGR.contains(daddr)) {
312  uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
313  return getIntConfig(ctx, ix);
314  }
315 
316  switch(daddr) {
317  case GICD_CTLR:
318  return enabled;
319  case GICD_TYPER:
320  /* The 0x100 is a made-up flag to show that gem5 extensions
321  * are available,
322  * write 0x200 to this register to enable it. */
323  return (((sys->threads.numRunning() - 1) << 5) |
324  (itLines/INT_BITS_MAX -1) |
325  (haveGem5Extensions ? 0x100 : 0x0));
326  case GICD_PIDR0:
327  //ARM defined DevID
328  return (gicdPIDR & 0xFF);
329  case GICD_PIDR1:
330  return ((gicdPIDR >> 8) & 0xFF);
331  case GICD_PIDR2:
332  return ((gicdPIDR >> 16) & 0xFF);
333  case GICD_PIDR3:
334  return ((gicdPIDR >> 24) & 0xFF);
335  case GICD_IIDR:
336  /* revision id is resorted to 1 and variant to 0*/
337  return gicdIIDR;
338  default:
339  panic("Tried to read Gic distributor at offset %#x\n", daddr);
340  break;
341  }
342 }
343 
344 Tick
346 {
347  const Addr daddr = pkt->getAddr() - cpuRange.start();
348 
349  assert(pkt->req->hasContextId());
350  const ContextID ctx = pkt->req->contextId();
351  assert(ctx < sys->threads.numRunning());
352 
353  DPRINTF(GIC, "gic cpu read register %#x cpu context: %d\n", daddr, ctx);
354 
355  pkt->setLE<uint32_t>(readCpu(ctx, daddr));
356 
357  pkt->makeAtomicResponse();
358  return cpuPioDelay;
359 }
360 
361 uint32_t
363 {
364  switch(daddr) {
365  case GICC_IIDR:
366  return giccIIDR;
367  case GICC_CTLR:
368  return cpuControl[ctx];
369  case GICC_PMR:
370  return cpuPriority[ctx];
371  case GICC_BPR:
372  return cpuBpr[ctx];
373  case GICC_IAR:
374  if (enabled && cpuEnabled(ctx)) {
375  int active_int = cpuHighestInt[ctx];
376  IAR iar = 0;
377  iar.ack_id = active_int;
378  iar.cpu_id = 0;
379  if (active_int < SGI_MAX) {
380  // this is a software interrupt from another CPU
381  if (!gem5ExtensionsEnabled) {
382  panic_if(!cpuSgiPending[active_int],
383  "Interrupt %d active but no CPU generated it?\n",
384  active_int);
385  for (int x = 0; x < sys->threads.numRunning(); x++) {
386  // See which CPU generated the interrupt
387  uint8_t cpugen =
388  bits(cpuSgiPending[active_int], 7 + 8 * x, 8 * x);
389  if (cpugen & (1 << ctx)) {
390  iar.cpu_id = x;
391  break;
392  }
393  }
394  uint64_t sgi_num = 1ULL << (ctx + 8 * iar.cpu_id);
395  cpuSgiActive[iar.ack_id] |= sgi_num;
396  cpuSgiPending[iar.ack_id] &= ~sgi_num;
397  } else {
398  uint64_t sgi_num = 1ULL << iar.ack_id;
399  cpuSgiActiveExt[ctx] |= sgi_num;
400  cpuSgiPendingExt[ctx] &= ~sgi_num;
401  }
402  } else if (active_int < (SGI_MAX + PPI_MAX) ) {
403  uint32_t int_num = 1 << (cpuHighestInt[ctx] - SGI_MAX);
404  cpuPpiActive[ctx] |= int_num;
405  updateRunPri();
406  if (!isLevelSensitive(ctx, active_int)) {
407  cpuPpiPending[ctx] &= ~int_num;
408  }
409 
410  } else {
411  uint32_t int_num = 1 << intNumToBit(cpuHighestInt[ctx]);
412  getActiveInt(ctx, intNumToWord(cpuHighestInt[ctx])) |= int_num;
413  updateRunPri();
414  if (!isLevelSensitive(ctx, active_int)) {
416  &= ~int_num;
417  }
418  }
419 
421  "CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
422  ctx, iar.ack_id, iar.cpu_id, iar);
424  updateIntState(-1);
425  clearInt(ctx, active_int);
426  return iar;
427  } else {
428  return SPURIOUS_INT;
429  }
430 
431  break;
432  case GICC_RPR:
433  return iccrpr[0];
434  case GICC_HPPIR:
435  panic("Need to implement HPIR");
436  break;
437  default:
438  panic("Tried to read Gic cpu at offset %#x\n", daddr);
439  break;
440  }
441 }
442 
443 Tick
445 {
446  const Addr daddr = pkt->getAddr() - distRange.start();
447 
448  assert(pkt->req->hasContextId());
449  const ContextID ctx = pkt->req->contextId();
450  const size_t data_sz = pkt->getSize();
451 
452  [[maybe_unused]] uint32_t pkt_data;
453  switch (data_sz)
454  {
455  case 1:
456  pkt_data = pkt->getLE<uint8_t>();
457  break;
458  case 2:
459  pkt_data = pkt->getLE<uint16_t>();
460  break;
461  case 4:
462  pkt_data = pkt->getLE<uint32_t>();
463  break;
464  default:
465  panic("Invalid size when writing to priority regs in Gic: %d\n",
466  data_sz);
467  }
468 
469  DPRINTF(GIC, "gic distributor write register %#x size %#x value %#x \n",
470  daddr, data_sz, pkt_data);
471 
472  writeDistributor(ctx, daddr, pkt_data, data_sz);
473 
474  pkt->makeAtomicResponse();
475  return distPioDelay;
476 }
477 
478 void
480  size_t data_sz)
481 {
482  if (GICD_IGROUPR.contains(daddr)) {
483  uint32_t ix = (daddr - GICD_IGROUPR.start()) >> 2;
484  assert(ix < 32);
485  getIntGroup(ctx, ix) |= data;
486  return;
487  }
488 
489  if (GICD_ISENABLER.contains(daddr)) {
490  uint32_t ix = (daddr - GICD_ISENABLER.start()) >> 2;
491  assert(ix < 32);
492  getIntEnabled(ctx, ix) |= data;
493  return;
494  }
495 
496  if (GICD_ICENABLER.contains(daddr)) {
497  uint32_t ix = (daddr - GICD_ICENABLER.start()) >> 2;
498  assert(ix < 32);
499  getIntEnabled(ctx, ix) &= ~data;
500  return;
501  }
502 
503  if (GICD_ISPENDR.contains(daddr)) {
504  uint32_t ix = (daddr - GICD_ISPENDR.start()) >> 2;
505  auto mask = data;
506  if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
507  getPendingInt(ctx, ix) |= mask;
508  updateIntState(ix);
509  return;
510  }
511 
512  if (GICD_ICPENDR.contains(daddr)) {
513  uint32_t ix = (daddr - GICD_ICPENDR.start()) >> 2;
514  auto mask = data;
515  if (ix == 0) mask &= SGI_MASK; // Don't allow SGIs to be changed
516  getPendingInt(ctx, ix) &= ~mask;
517  updateIntState(ix);
518  return;
519  }
520 
521  if (GICD_ISACTIVER.contains(daddr)) {
522  uint32_t ix = (daddr - GICD_ISACTIVER.start()) >> 2;
523  getActiveInt(ctx, ix) |= data;
524  return;
525  }
526 
527  if (GICD_ICACTIVER.contains(daddr)) {
528  uint32_t ix = (daddr - GICD_ICACTIVER.start()) >> 2;
529  getActiveInt(ctx, ix) &= ~data;
530  return;
531  }
532 
533  if (GICD_IPRIORITYR.contains(daddr)) {
534  Addr int_num = daddr - GICD_IPRIORITYR.start();
535  switch(data_sz) {
536  case 1:
537  getIntPriority(ctx, int_num) = data;
538  break;
539  case 2: {
540  getIntPriority(ctx, int_num) = bits(data, 7, 0);
541  getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
542  break;
543  }
544  case 4: {
545  getIntPriority(ctx, int_num) = bits(data, 7, 0);
546  getIntPriority(ctx, int_num + 1) = bits(data, 15, 8);
547  getIntPriority(ctx, int_num + 2) = bits(data, 23, 16);
548  getIntPriority(ctx, int_num + 3) = bits(data, 31, 24);
549  break;
550  }
551  default:
552  panic("Invalid size when writing to priority regs in Gic: %d\n",
553  data_sz);
554  }
555 
556  updateIntState(-1);
557  updateRunPri();
558  return;
559  }
560 
561  if (GICD_ITARGETSR.contains(daddr)) {
562  Addr int_num = daddr - GICD_ITARGETSR.start();
563  // Interrupts 0-31 are read only
564  unsigned offset = SGI_MAX + PPI_MAX;
565  if (int_num >= offset) {
566  unsigned ix = int_num - offset; // index into cpuTarget array
567  if (data_sz == 1) {
568  cpuTarget[ix] = data & 0xff;
569  } else {
570  assert (data_sz == 4);
571  cpuTarget[ix] = bits(data, 7, 0);
572  cpuTarget[ix+1] = bits(data, 15, 8);
573  cpuTarget[ix+2] = bits(data, 23, 16);
574  cpuTarget[ix+3] = bits(data, 31, 24);
575  }
576  updateIntState(int_num >> 2);
577  }
578  return;
579  }
580 
581  if (GICD_ICFGR.contains(daddr)) {
582  uint32_t ix = (daddr - GICD_ICFGR.start()) >> 2;
583  // Since the GICD_ICFGR0 is RO (WI), we are discarding the write
584  // if ix = 0
585  if (ix != 0)
586  getIntConfig(ctx, ix) = data;
587  if (data & NN_CONFIG_MASK)
588  warn("GIC N:N mode selected and not supported at this time\n");
589  return;
590  }
591 
592  switch(daddr) {
593  case GICD_CTLR:
594  enabled = data;
595  DPRINTF(Interrupt, "Distributor enable flag set to = %d\n", enabled);
596  break;
597  case GICD_TYPER:
598  /* 0x200 is a made-up flag to enable gem5 extension functionality.
599  * This reg is not normally written.
600  */
602  DPRINTF(GIC, "gem5 extensions %s\n",
603  gem5ExtensionsEnabled ? "enabled" : "disabled");
604  break;
605  case GICD_SGIR:
606  softInt(ctx, data);
607  break;
608  default:
609  panic("Tried to write Gic distributor at offset %#x\n", daddr);
610  break;
611  }
612 }
613 
614 Tick
616 {
617  const Addr daddr = pkt->getAddr() - cpuRange.start();
618 
619  assert(pkt->req->hasContextId());
620  const ContextID ctx = pkt->req->contextId();
621  const uint32_t data = pkt->getLE<uint32_t>();
622 
623  DPRINTF(GIC, "gic cpu write register cpu:%d %#x val: %#x\n",
624  ctx, daddr, data);
625 
626  writeCpu(ctx, daddr, data);
627 
628  pkt->makeAtomicResponse();
629  return cpuPioDelay;
630 }
631 
632 void
633 GicV2::writeCpu(ContextID ctx, Addr daddr, uint32_t data)
634 {
635  switch(daddr) {
636  case GICC_CTLR:
637  cpuControl[ctx] = data;
638  break;
639  case GICC_PMR:
640  cpuPriority[ctx] = data;
641  break;
642  case GICC_BPR: {
643  auto bpr = data & 0x7;
644  if (bpr < GICC_BPR_MINIMUM)
645  bpr = GICC_BPR_MINIMUM;
646  cpuBpr[ctx] = bpr;
647  break;
648  }
649  case GICC_EOIR: {
650  const IAR iar = data;
651  if (iar.ack_id < SGI_MAX) {
652  // Clear out the bit that corresponds to the cleared int
653  uint64_t clr_int = 1ULL << (ctx + 8 * iar.cpu_id);
654  if (!(cpuSgiActive[iar.ack_id] & clr_int) &&
655  !(cpuSgiActiveExt[ctx] & (1 << iar.ack_id)))
656  panic("Done handling a SGI that isn't active?\n");
658  cpuSgiActiveExt[ctx] &= ~(1 << iar.ack_id);
659  else
660  cpuSgiActive[iar.ack_id] &= ~clr_int;
661  } else if (iar.ack_id < (SGI_MAX + PPI_MAX) ) {
662  uint32_t int_num = 1 << (iar.ack_id - SGI_MAX);
663  if (!(cpuPpiActive[ctx] & int_num))
664  warn("CPU %d Done handling a PPI interrupt "
665  "that isn't active?\n", ctx);
666  cpuPpiActive[ctx] &= ~int_num;
667  } else {
668  uint32_t int_num = 1 << intNumToBit(iar.ack_id);
669  if (!(getActiveInt(ctx, intNumToWord(iar.ack_id)) & int_num))
670  warn("Done handling interrupt that isn't active: %d\n",
671  intNumToBit(iar.ack_id));
672  getActiveInt(ctx, intNumToWord(iar.ack_id)) &= ~int_num;
673  }
674  updateRunPri();
675  DPRINTF(Interrupt, "CPU %d done handling intr IAR = %d from cpu %d\n",
676  ctx, iar.ack_id, iar.cpu_id);
677  break;
678  }
679  case GICC_APR0:
680  case GICC_APR1:
681  case GICC_APR2:
682  case GICC_APR3:
683  warn("GIC APRn write ignored because not implemented: %#x\n", daddr);
684  break;
685  case GICC_DIR:
686  warn("GIC DIR write ignored because not implemented: %#x\n", daddr);
687  break;
688  default:
689  panic("Tried to write Gic cpu at offset %#x\n", daddr);
690  break;
691  }
692  if (cpuEnabled(ctx)) updateIntState(-1);
693 }
694 
697  if (bankedRegs.size() <= ctx)
698  bankedRegs.resize(ctx + 1);
699 
700  if (!bankedRegs[ctx])
701  bankedRegs[ctx] = new BankedRegs;
702  return *bankedRegs[ctx];
703 }
704 
705 void
707 {
708  if (gem5ExtensionsEnabled) {
709  switch (swi.list_type) {
710  case 0: {
711  // interrupt cpus specified
712  int dest = swi.cpu_list;
713  DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
714  ctx, dest);
715  if (cpuEnabled(dest)) {
716  cpuSgiPendingExt[dest] |= (1 << swi.sgi_id);
717  DPRINTF(IPI, "SGI[%d]=%#x\n", dest,
718  cpuSgiPendingExt[dest]);
719  }
720  } break;
721  case 1: {
722  // interrupt all
723  for (int i = 0; i < sys->threads.size(); i++) {
724  DPRINTF(IPI, "Processing CPU %d\n", i);
725  if (!cpuEnabled(i))
726  continue;
727  cpuSgiPendingExt[i] |= 1 << swi.sgi_id;
728  DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
730  }
731  } break;
732  case 2: {
733  // Interrupt requesting cpu only
734  DPRINTF(IPI, "Generating softIRQ from CPU %d for CPU %d\n",
735  ctx, ctx);
736  if (cpuEnabled(ctx)) {
737  cpuSgiPendingExt[ctx] |= (1 << swi.sgi_id);
738  DPRINTF(IPI, "SGI[%d]=%#x\n", ctx,
739  cpuSgiPendingExt[ctx]);
740  }
741  } break;
742  }
743  } else {
744  switch (swi.list_type) {
745  case 1:
746  // interrupt all
747  uint8_t cpu_list;
748  cpu_list = 0;
749  for (int x = 0; x < sys->threads.size(); x++)
750  cpu_list |= cpuEnabled(x) ? 1 << x : 0;
751  swi.cpu_list = cpu_list;
752  break;
753  case 2:
754  // interrupt requesting cpu only
755  swi.cpu_list = 1 << ctx;
756  break;
757  // else interrupt cpus specified
758  }
759 
760  DPRINTF(IPI, "Generating softIRQ from CPU %d for %#x\n", ctx,
761  swi.cpu_list);
762  for (int i = 0; i < sys->threads.size(); i++) {
763  DPRINTF(IPI, "Processing CPU %d\n", i);
764  if (!cpuEnabled(i))
765  continue;
766  if (swi.cpu_list & (1 << i))
767  cpuSgiPending[swi.sgi_id] |= (1 << i) << (8 * ctx);
768  DPRINTF(IPI, "SGI[%d]=%#x\n", swi.sgi_id,
769  cpuSgiPending[swi.sgi_id]);
770  }
771  }
772  updateIntState(-1);
773 }
774 
775 uint64_t
777 {
778  panic_if(cpu > sys->threads.size(), "Invalid CPU ID.");
779  return 0x0101010101010101ULL << cpu;
780 }
781 
782 uint8_t
784 {
785  // see Table 3-2 in IHI0048B.b (GICv2)
786  // mask some low-order priority bits per BPR value
787  // NB: the GIC prioritization scheme is upside down:
788  // lower values are higher priority; masking off bits
789  // actually creates a higher priority, not lower.
790  return cpuPriority[cpu] & (0xff00 >> (7 - cpuBpr[cpu]));
791 }
792 
793 void
795 {
796  if (blockIntUpdate())
797  return;
798 
799  for (int cpu = 0; cpu < sys->threads.size(); cpu++) {
800  if (!cpuEnabled(cpu))
801  continue;
802 
803  /*@todo use hint to do less work. */
804  int highest_int = SPURIOUS_INT;
805  // Priorities below that set in GICC_PMR can be ignored
806  uint8_t highest_pri = getCpuPriority(cpu);
807 
808  // Check SGIs
809  for (int swi = 0; swi < SGI_MAX; swi++) {
810  if (!cpuSgiPending[swi] && !cpuSgiPendingExt[cpu])
811  continue;
812  if ((cpuSgiPending[swi] & genSwiMask(cpu)) ||
813  (cpuSgiPendingExt[cpu] & (1 << swi)))
814  if (highest_pri > getIntPriority(cpu, swi)) {
815  highest_pri = getIntPriority(cpu, swi);
816  highest_int = swi;
817  }
818  }
819 
820  // Check PPIs
821  if (cpuPpiPending[cpu]) {
822  for (int ppi_idx = 0, int_num = SGI_MAX;
823  int_num < PPI_MAX + SGI_MAX;
824  ppi_idx++, int_num++) {
825 
826  const bool ppi_pending = bits(cpuPpiPending[cpu], ppi_idx);
827  const bool ppi_enabled = bits(getIntEnabled(cpu, 0), int_num);
828  const bool higher_priority =
829  highest_pri > getIntPriority(cpu, int_num);
830 
831  if (ppi_pending && ppi_enabled && higher_priority) {
832  highest_pri = getIntPriority(cpu, int_num);
833  highest_int = int_num;
834  }
835  }
836  }
837 
838  bool mp_sys = sys->threads.numRunning() > 1;
839  // Check other ints
840  for (int x = 0; x < (itLines/INT_BITS_MAX); x++) {
841  if (getIntEnabled(cpu, x) & getPendingInt(cpu, x)) {
842  for (int y = 0; y < INT_BITS_MAX; y++) {
843  uint32_t int_nm = x * INT_BITS_MAX + y;
844  DPRINTF(GIC, "Checking for interrupt# %d \n",int_nm);
845  /* Set current pending int as highest int for current cpu
846  if the interrupt's priority higher than current priority
847  and if current cpu is the target (for mp configs only)
848  */
849  if ((bits(getIntEnabled(cpu, x), y)
850  &bits(getPendingInt(cpu, x), y)) &&
851  (getIntPriority(cpu, int_nm) < highest_pri))
852  if ((!mp_sys) ||
854  ? (getCpuTarget(cpu, int_nm) == cpu)
855  : (getCpuTarget(cpu, int_nm) & (1 << cpu)))) {
856  highest_pri = getIntPriority(cpu, int_nm);
857  highest_int = int_nm;
858  }
859  }
860  }
861  }
862 
863  uint32_t prev_highest = cpuHighestInt[cpu];
864  cpuHighestInt[cpu] = highest_int;
865 
866  if (highest_int == SPURIOUS_INT) {
867  if (isLevelSensitive(cpu, prev_highest)) {
868 
869  DPRINTF(Interrupt, "Clear IRQ for cpu%d\n", cpu);
870  clearInt(cpu, prev_highest);
871  }
872  continue;
873  }
874 
875  /* @todo make this work for more than one cpu, need to handle 1:N, N:N
876  * models */
877  if (enabled && cpuEnabled(cpu) &&
878  (highest_pri < getCpuPriority(cpu)) &&
879  !(getActiveInt(cpu, intNumToWord(highest_int))
880  & (1 << intNumToBit(highest_int)))) {
881 
882  DPRINTF(Interrupt, "Posting interrupt %d to cpu%d\n", highest_int,
883  cpu);
884 
885  if (isFiq(cpu, highest_int)) {
886  postFiq(cpu, curTick() + intLatency);
887  } else {
888  postInt(cpu, curTick() + intLatency);
889  }
890  }
891  }
892 }
893 
894 void
896 {
897  for (int cpu = 0; cpu < sys->threads.size(); cpu++) {
898  if (!cpuEnabled(cpu))
899  continue;
900  uint8_t maxPriority = 0xff;
901  for (int i = 0; i < itLines; i++) {
902  if (i < SGI_MAX) {
903  if (((cpuSgiActive[i] & genSwiMask(cpu)) ||
904  (cpuSgiActiveExt[cpu] & (1 << i))) &&
905  (getIntPriority(cpu, i) < maxPriority))
906  maxPriority = getIntPriority(cpu, i);
907  } else if (i < (SGI_MAX + PPI_MAX)) {
908  if ((cpuPpiActive[cpu] & ( 1 << (i - SGI_MAX))) &&
909  (getIntPriority(cpu, i) < maxPriority))
910  maxPriority = getIntPriority(cpu, i);
911 
912  } else {
913  if (getActiveInt(cpu, intNumToWord(i))
914  & (1 << intNumToBit(i)))
915  if (getIntPriority(cpu, i) < maxPriority)
916  maxPriority = getIntPriority(cpu, i);
917  }
918  }
919  iccrpr[cpu] = maxPriority;
920  }
921 }
922 
923 void
924 GicV2::sendInt(uint32_t num)
925 {
926  uint8_t target = getCpuTarget(0, num);
927  DPRINTF(Interrupt, "Received Interrupt number %d, cpuTarget %#x: \n",
928  num, target);
929  if ((target & (target - 1)) && !gem5ExtensionsEnabled)
930  panic("Multiple targets for peripheral interrupts is not supported\n");
931  panic_if(num < SGI_MAX + PPI_MAX,
932  "sentInt() must only be used for interrupts 32 and higher");
933  getPendingInt(target, intNumToWord(num)) |= 1 << intNumToBit(num);
935 }
936 
937 void
938 GicV2::sendPPInt(uint32_t num, uint32_t cpu)
939 {
940  DPRINTF(Interrupt, "Received PPI %d, cpuTarget %#x: \n",
941  num, cpu);
942  cpuPpiPending[cpu] |= 1 << (num - SGI_MAX);
944 }
945 
946 void
947 GicV2::clearInt(uint32_t num)
948 {
949  if (isLevelSensitive(0, num)) {
950  uint8_t target = getCpuTarget(0, num);
951 
953  "Received Clear interrupt number %d, cpuTarget %#x:\n",
954  num, target);
955 
956  getPendingInt(target, intNumToWord(num)) &= ~(1 << intNumToBit(num));
958  } else {
959  /* Nothing to do :
960  * Edge-triggered interrupt remain pending until software
961  * writes GICD_ICPENDR or reads GICC_IAR */
962  }
963 }
964 
965 void
966 GicV2::clearPPInt(uint32_t num, uint32_t cpu)
967 {
968  if (isLevelSensitive(cpu, num)) {
969  DPRINTF(Interrupt, "Clearing PPI %d, cpuTarget %#x: \n",
970  num, cpu);
971  cpuPpiPending[cpu] &= ~(1 << (num - SGI_MAX));
973  } else {
974  /* Nothing to do :
975  * Edge-triggered interrupt remain pending until software
976  * writes GICD_ICPENDR or reads GICC_IAR */
977  }
978 }
979 
980 void
981 GicV2::clearInt(ContextID ctx, uint32_t int_num)
982 {
983  auto tc = sys->threads[ctx];
984  if (isFiq(ctx, int_num)) {
985  tc->getCpuPtr()->clearInterrupt(tc->threadId(), ArmISA::INT_FIQ, 0);
986  } else {
987  tc->getCpuPtr()->clearInterrupt(tc->threadId(), ArmISA::INT_IRQ, 0);
988  }
989 }
990 
991 void
992 GicV2::postInt(uint32_t cpu, Tick when)
993 {
994  if (!(postIntEvent[cpu]->scheduled())) {
996  eventq->schedule(postIntEvent[cpu], when);
997  }
998 }
999 
1000 void
1002 {
1003  auto tc = sys->threads[cpu];
1004  tc->getCpuPtr()->postInterrupt(tc->threadId(), ArmISA::INT_IRQ, 0);
1006  assert(pendingDelayedInterrupts >= 0);
1007  if (pendingDelayedInterrupts == 0)
1008  signalDrainDone();
1009 }
1010 
1011 void
1012 GicV2::postFiq(uint32_t cpu, Tick when)
1013 {
1014  if (!(postFiqEvent[cpu]->scheduled())) {
1016  eventq->schedule(postFiqEvent[cpu], when);
1017  }
1018 }
1019 
1020 bool
1022 {
1023  return version == GicVersion::GIC_V2;
1024 }
1025 
1026 void
1028 {
1029  auto tc = sys->threads[cpu];
1030  tc->getCpuPtr()->postInterrupt(tc->threadId(), ArmISA::INT_FIQ, 0);
1032  assert(pendingDelayedInterrupts >= 0);
1033  if (pendingDelayedInterrupts == 0)
1034  signalDrainDone();
1035 }
1036 
1037 DrainState
1039 {
1040  if (pendingDelayedInterrupts == 0) {
1041  return DrainState::Drained;
1042  } else {
1043  return DrainState::Draining;
1044  }
1045 }
1046 
1047 
1048 void
1050 {
1051  // There may be pending interrupts if checkpointed from Kvm; post them.
1052  updateIntState(-1);
1053 }
1054 
1055 void
1057 {
1058  Addr set, clear;
1059  size_t size;
1060 
1062  // Copy CPU Interface Control Register (CTLR),
1063  // Interrupt Priority Mask Register (PMR), and
1064  // Binary Point Register (BPR)
1065  for (int ctx = 0; ctx < sys->threads.size(); ++ctx) {
1066  copyCpuRegister(from, to, ctx, GICC_CTLR);
1067  copyCpuRegister(from, to, ctx, GICC_PMR);
1068  copyCpuRegister(from, to, ctx, GICC_BPR);
1069  }
1070 
1072  // Copy Distributor Control Register (CTLR)
1073  copyDistRegister(from, to, 0, GICD_CTLR);
1074 
1075  // Copy interrupt-enabled statuses (I[CS]ENABLERn; R0 is per-CPU banked)
1076  set = GICD_ISENABLER.start();
1077  clear = GICD_ICENABLER.start();
1078  size = itLines / 8;
1079  clearBankedDistRange(sys, to, clear, 4);
1080  copyBankedDistRange(sys, from, to, set, 4);
1081 
1082  set += 4, clear += 4, size -= 4;
1083  clearDistRange(to, clear, size);
1084  copyDistRange(from, to, set, size);
1085 
1086  // Copy pending interrupts (I[CS]PENDRn; R0 is per-CPU banked)
1087  set = GICD_ISPENDR.start();
1088  clear = GICD_ICPENDR.start();
1089  size = itLines / 8;
1090  clearBankedDistRange(sys, to, clear, 4);
1091  copyBankedDistRange(sys, from, to, set, 4);
1092 
1093  set += 4, clear += 4, size -= 4;
1094  clearDistRange(to, clear, size);
1095  copyDistRange(from, to, set, size);
1096 
1097  // Copy active interrupts (I[CS]ACTIVERn; R0 is per-CPU banked)
1098  set = GICD_ISACTIVER.start();
1099  clear = GICD_ICACTIVER.start();
1100  size = itLines / 8;
1101  clearBankedDistRange(sys, to, clear, 4);
1102  copyBankedDistRange(sys, from, to, set, 4);
1103 
1104  set += 4, clear += 4, size -= 4;
1105  clearDistRange(to, clear, size);
1106  copyDistRange(from, to, set, size);
1107 
1108  // Copy interrupt priorities (IPRIORITYRn; R0-7 are per-CPU banked)
1110  copyBankedDistRange(sys, from, to, set, 32);
1111 
1112  set += 32;
1113  size = itLines - 32;
1114  copyDistRange(from, to, set, size);
1115 
1116  // Copy interrupt processor target regs (ITARGETRn; R0-7 are read-only)
1117  set = GICD_ITARGETSR.start() + 32;
1118  size = itLines - 32;
1119  copyDistRange(from, to, set, size);
1120 
1121  // Copy interrupt configuration registers (ICFGRn)
1122  set = GICD_ICFGR.start();
1123  size = itLines / 4;
1124  copyDistRange(from, to, set, size);
1125 }
1126 
1127 void
1129 {
1130  DPRINTF(Checkpoint, "Serializing Arm GIC\n");
1131 
1153 
1154  for (uint32_t i=0; i < bankedRegs.size(); ++i) {
1155  if (!bankedRegs[i])
1156  continue;
1157  bankedRegs[i]->serializeSection(cp, csprintf("bankedRegs%i", i));
1158  }
1159 }
1160 
1161 void
1163 {
1170 }
1171 
1172 void
1174 {
1175  DPRINTF(Checkpoint, "Unserializing Arm GIC\n");
1176 
1197 
1198  // Handle checkpoints from before we drained the GIC to prevent
1199  // in-flight interrupts.
1200  if (cp.entryExists(Serializable::currentSection(), "interrupt_time")) {
1201  Tick interrupt_time[CPU_MAX];
1202  UNSERIALIZE_ARRAY(interrupt_time, CPU_MAX);
1203 
1204  for (uint32_t cpu = 0; cpu < CPU_MAX; cpu++) {
1205  if (interrupt_time[cpu])
1206  schedule(postIntEvent[cpu], interrupt_time[cpu]);
1207  }
1208  }
1209 
1211  gem5ExtensionsEnabled = false;
1212 
1213  for (uint32_t i=0; i < CPU_MAX; ++i) {
1214  ScopedCheckpointSection sec(cp, csprintf("bankedRegs%i", i));
1217  }
1218  }
1219 }
1220 
1221 void
1223 {
1230 }
1231 
1232 } // namespace gem5
#define DPRINTF(x,...)
Definition: trace.hh:186
const char data[]
virtual bool blockIntUpdate() const
When trasferring the state between two GICs (essentially writing architectural registers) an interrup...
Definition: base_gic.hh:130
BaseGicParams Params
Definition: base_gic.hh:75
EventQueue * eventq
A pointer to this object's event queue.
Definition: eventq.hh:991
static void clearDistRange(GicV2Registers *to, Addr daddr, size_t size)
Definition: gic_v2.cc:116
virtual uint32_t readDistributor(ContextID ctx, Addr daddr)=0
static void copyDistRange(GicV2Registers *from, GicV2Registers *to, Addr daddr, size_t size)
Definition: gic_v2.cc:107
static void copyBankedDistRange(System *sys, GicV2Registers *from, GicV2Registers *to, Addr daddr, size_t size)
Definition: gic_v2.cc:88
static void copyDistRegister(GicV2Registers *from, GicV2Registers *to, ContextID ctx, Addr daddr)
Definition: gic_v2.cc:68
virtual uint32_t readCpu(ContextID ctx, Addr daddr)=0
static void clearBankedDistRange(System *sys, GicV2Registers *to, Addr daddr, size_t size)
Definition: gic_v2.cc:98
static void copyCpuRegister(GicV2Registers *from, GicV2Registers *to, ContextID ctx, Addr daddr)
Definition: gic_v2.cc:78
static const int GLOBAL_INT_LINES
Definition: gic_v2.hh:156
const uint32_t gicdIIDR
Definition: gic_v2.hh:110
const Tick distPioDelay
Latency for a distributor operation.
Definition: gic_v2.hh:190
std::vector< BankedRegs * > bankedRegs
Definition: gic_v2.hh:246
int intNumToBit(int num) const
Definition: gic_v2.hh:490
EventFunctionWrapper * postIntEvent[CPU_MAX]
Definition: gic_v2.hh:507
uint32_t itLines
Number of itLines enabled.
Definition: gic_v2.hh:209
static const AddrRange GICD_IPRIORITYR
Definition: gic_v2.hh:120
bool isFiq(ContextID ctx, uint32_t int_num)
This method checks if an interrupt ID must be signaled or has been signaled as a FIQ to the cpu.
Definition: gic_v2.hh:417
static const AddrRange GICD_ICACTIVER
Definition: gic_v2.hh:119
void postFiq(uint32_t cpu, Tick when)
Definition: gic_v2.cc:1012
uint32_t intEnabled[INT_BITS_MAX-1]
GICD_I{S,C}ENABLER{1..31} interrupt enable bits for global interrupts 1b per interrupt,...
Definition: gic_v2.hh:253
@ GICD_PIDR2
Definition: gic_v2.hh:103
@ GICD_IIDR
Definition: gic_v2.hh:99
@ GICD_CTLR
Definition: gic_v2.hh:97
@ GICD_PIDR3
Definition: gic_v2.hh:104
@ GICD_PIDR1
Definition: gic_v2.hh:102
@ GICD_TYPER
Definition: gic_v2.hh:98
@ GICD_PIDR0
Definition: gic_v2.hh:101
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_v2.hh:464
static const AddrRange GICD_ICFGR
Definition: gic_v2.hh:122
static const AddrRange GICD_ICENABLER
Definition: gic_v2.hh:115
static const int INT_LINES_MAX
Definition: gic_v2.hh:155
void softInt(ContextID ctx, SWI swi)
software generated interrupt
Definition: gic_v2.cc:706
uint64_t cpuSgiPending[SGI_MAX]
One bit per cpu per software interrupt that is pending for each possible sgi source.
Definition: gic_v2.hh:458
uint32_t & getActiveInt(ContextID ctx, uint32_t ix)
Definition: gic_v2.hh:287
static const AddrRange GICD_ISPENDR
Definition: gic_v2.hh:116
Tick readDistributor(PacketPtr pkt)
Handle a read to the distributor portion of the GIC.
Definition: gic_v2.cc:197
EndBitUnion(CTLR) protected const AddrRange cpuRange
Address range for the distributor interface.
Definition: gic_v2.hh:177
Tick writeDistributor(PacketPtr pkt)
Handle a write to the distributor portion of the GIC.
Definition: gic_v2.cc:444
uint8_t cpuPriority[CPU_MAX]
CPU priority.
Definition: gic_v2.hh:445
int pendingDelayedInterrupts
Definition: gic_v2.hh:509
uint32_t pendingInt[INT_BITS_MAX-1]
GICD_I{S,C}PENDR{1..31} interrupt pending bits for global interrupts 1b per interrupt,...
Definition: gic_v2.hh:268
uint32_t & getIntGroup(ContextID ctx, uint32_t ix)
Definition: gic_v2.hh:303
BankedRegs & getBankedRegs(ContextID)
Definition: gic_v2.cc:696
static const int INT_BITS_MAX
Definition: gic_v2.hh:154
void copyGicState(GicV2Registers *from, GicV2Registers *to)
GIC state transfer.
Definition: gic_v2.cc:1056
static const int SGI_MAX
Definition: gic_v2.hh:143
void postDelayedFiq(uint32_t cpu)
Definition: gic_v2.cc:1027
EventFunctionWrapper * postFiqEvent[CPU_MAX]
Definition: gic_v2.hh:508
DrainState drain() override
Draining is the process of clearing out the states of SimObjects.These are the SimObjects that are pa...
Definition: gic_v2.cc:1038
uint32_t cpuPpiActive[CPU_MAX]
Definition: gic_v2.hh:470
static const AddrRange GICD_ISACTIVER
Definition: gic_v2.hh:118
static const AddrRange GICD_IGROUPR
Definition: gic_v2.hh:113
uint8_t getCpuPriority(unsigned cpu)
Definition: gic_v2.cc:783
int intNumToWord(int num) const
Definition: gic_v2.hh:489
void drainResume() override
Resume execution after a successful drain.
Definition: gic_v2.cc:1049
bool enabled
Gic enabled.
Definition: gic_v2.hh:200
static const int SGI_MASK
Mask off SGI's when setting/clearing pending bits.
Definition: gic_v2.hh:147
uint32_t intGroup[INT_BITS_MAX-1]
GICD_IGROUPR{1..31} interrupt group bits for global interrupts 1b per interrupt, 32 bits per word,...
Definition: gic_v2.hh:300
uint32_t intConfig[INT_BITS_MAX *2 - 2]
GICD_ICFGR{2...63} 2 bit per interrupt signaling if it's level or edge sensitive and if it is 1:N or ...
Definition: gic_v2.hh:337
const Tick intLatency
Latency for a interrupt to get to CPU.
Definition: gic_v2.hh:196
void updateIntState(int hint)
See if some processor interrupt flags need to be enabled/disabled.
Definition: gic_v2.cc:794
Tick readCpu(PacketPtr pkt)
Handle a read to the cpu portion of the GIC.
Definition: gic_v2.cc:345
const bool haveGem5Extensions
Are gem5 extensions available?
Definition: gic_v2.hh:203
bool isLevelSensitive(ContextID ctx, uint32_t int_num)
Definition: gic_v2.hh:388
Tick write(PacketPtr pkt) override
A PIO read to the device, immediately split up into writeDistributor() or writeCpu()
Definition: gic_v2.cc:184
static const int CPU_MAX
Definition: gic_v2.hh:152
void sendPPInt(uint32_t num, uint32_t cpu) override
Interface call for private peripheral interrupts.
Definition: gic_v2.cc:938
static const int GICC_BPR_MINIMUM
minimum value for Binary Point Register ("IMPLEMENTATION DEFINED"); chosen for consistency with Linux...
Definition: gic_v2.hh:160
uint32_t & getPendingInt(ContextID ctx, uint32_t ix)
Definition: gic_v2.hh:271
uint8_t cpuBpr[CPU_MAX]
Binary point registers.
Definition: gic_v2.hh:449
uint64_t cpuSgiActive[SGI_MAX]
Definition: gic_v2.hh:459
Tick writeCpu(PacketPtr pkt)
Handle a write to the cpu portion of the GIC.
Definition: gic_v2.cc:615
@ GICC_HPPIR
Definition: gic_v2.hh:133
CTLR cpuControl[CPU_MAX]
GICC_CTLR: CPU interface control register.
Definition: gic_v2.hh:442
void updateRunPri()
Update the register that records priority of the highest priority active interrupt.
Definition: gic_v2.cc:895
uint32_t cpuSgiActiveExt[CPU_MAX]
Definition: gic_v2.hh:465
static const AddrRange GICD_ISENABLER
Definition: gic_v2.hh:114
const uint32_t giccIIDR
Definition: gic_v2.hh:111
void sendInt(uint32_t number) override
Post an interrupt from a device that is connected to the GIC.
Definition: gic_v2.cc:924
uint32_t cpuPpiPending[CPU_MAX]
One bit per private peripheral interrupt.
Definition: gic_v2.hh:469
uint32_t cpuHighestInt[CPU_MAX]
highest interrupt that is interrupting CPU
Definition: gic_v2.hh:452
Tick read(PacketPtr pkt) override
A PIO read to the device, immediately split up into readDistributor() or readCpu()
Definition: gic_v2.cc:170
uint8_t cpuTarget[GLOBAL_INT_LINES]
GICD_ITARGETSR{8..255} an 8 bit cpu target id for each global interrupt.
Definition: gic_v2.hh:360
GicV2(const Params &p)
Definition: gic_v2.cc:122
bool cpuEnabled(ContextID ctx) const
CPU enabled: Checks if GICC_CTLR.EnableGrp0 or EnableGrp1 are set.
Definition: gic_v2.hh:433
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: gic_v2.cc:1128
uint64_t genSwiMask(int cpu)
generate a bit mask to check cpuSgi for an interrupt.
Definition: gic_v2.cc:776
static const int SPURIOUS_INT
Definition: gic_v2.hh:153
static const int NN_CONFIG_MASK
Mask for bits that config N:N mode in GICD_ICFGR's.
Definition: gic_v2.hh:150
bool supportsVersion(GicVersion version) override
Check if version supported.
Definition: gic_v2.cc:1021
void clearPPInt(uint32_t num, uint32_t cpu) override
Definition: gic_v2.cc:966
bool gem5ExtensionsEnabled
gem5 many-core extension enabled by driver
Definition: gic_v2.hh:206
const uint32_t gicdPIDR
Definition: gic_v2.hh:109
uint32_t & getIntConfig(ContextID ctx, uint32_t ix)
Reads the GICD_ICFGRn register.
Definition: gic_v2.hh:346
const Tick cpuPioDelay
Latency for a cpu operation.
Definition: gic_v2.hh:193
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: gic_v2.cc:1173
uint32_t & getIntEnabled(ContextID ctx, uint32_t ix)
Definition: gic_v2.hh:256
uint8_t getCpuTarget(ContextID ctx, uint32_t ix) const
Definition: gic_v2.hh:363
static const int PPI_MAX
Definition: gic_v2.hh:144
static const AddrRange GICD_ITARGETSR
Definition: gic_v2.hh:121
Bitfield< 23, 16 > cpu_list
Definition: gic_v2.hh:164
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_v2.hh:320
void clearInt(ContextID ctx, uint32_t int_num)
Clears a cpu IRQ or FIQ signal.
Definition: gic_v2.cc:981
void postInt(uint32_t cpu, Tick when)
Post an interrupt to a CPU with a delay.
Definition: gic_v2.cc:992
uint32_t activeInt[INT_BITS_MAX-1]
GICD_I{S,C}ACTIVER{1..31} interrupt active bits for global interrupts 1b per interrupt,...
Definition: gic_v2.hh:284
uint32_t iccrpr[CPU_MAX]
read only running priority register, 1 per cpu
Definition: gic_v2.hh:314
void postDelayedInt(uint32_t cpu)
Deliver a delayed interrupt to the target CPU.
Definition: gic_v2.cc:1001
static const AddrRange GICD_ICPENDR
Definition: gic_v2.hh:117
uint8_t & getIntPriority(ContextID ctx, uint32_t ix)
Definition: gic_v2.hh:323
A Packet is used to encapsulate a transfer between two objects in the memory system (e....
Definition: packet.hh:294
Addr getAddr() const
Definition: packet.hh:805
void setLE(T v)
Set the value in the data pointer to v as little endian.
RequestPtr req
A pointer to the original request.
Definition: packet.hh:376
unsigned getSize() const
Definition: packet.hh:815
void makeAtomicResponse()
Definition: packet.hh:1071
T getLE() const
Get the data in the packet byte swapped from little endian to host endian.
System * sys
Definition: io_device.hh:105
int size() const
Definition: system.hh:213
int numRunning() const
Definition: system.cc:131
Threads threads
Definition: system.hh:313
Implementation of a GICv2.
AddrRange RangeSize(Addr start, Addr size)
Definition: addr_range.hh:815
bool contains(const Addr &a) const
Determine if the range contains an address.
Definition: addr_range.hh:471
Addr start() const
Get the start address of the range.
Definition: addr_range.hh:343
constexpr T bits(T val, unsigned first, unsigned last)
Extract the bitfield from position 'first' to 'last' (inclusive) from 'val' and right justify it.
Definition: bitfield.hh:76
constexpr T mbits(T val, unsigned first, unsigned last)
Mask off the given bits in place like bits() but without shifting.
Definition: bitfield.hh:103
constexpr uint64_t mask(unsigned nbits)
Generate a 64-bit mask of 'nbits' 1s, right justified.
Definition: bitfield.hh:63
void signalDrainDone() const
Signal that an object is drained.
Definition: drain.hh:305
DrainState
Object drain/handover states.
Definition: drain.hh:75
@ Draining
Draining buffers pending serialization/handover.
@ Drained
Buffers drained, ready for serialization/handover.
void schedule(Event *event, Tick when, bool global=false)
Schedule the given event on this queue.
Definition: eventq.hh:764
void schedule(Event &event, Tick when)
Definition: eventq.hh:1019
#define panic(...)
This implements a cprintf based panic() function.
Definition: logging.hh:178
#define panic_if(cond,...)
Conditional panic macro that checks the supplied condition and only panics if the condition is true a...
Definition: logging.hh:204
bool entryExists(const std::string &section, const std::string &entry)
Definition: serialize.cc:178
#define UNSERIALIZE_OPT_SCALAR(scalar)
Definition: serialize.hh:582
static const std::string & currentSection()
Gets the fully-qualified name of the active section.
Definition: serialize.cc:130
#define UNSERIALIZE_ARRAY(member, size)
Definition: serialize.hh:618
#define SERIALIZE_ARRAY(member, size)
Definition: serialize.hh:610
bool sectionExists(const std::string &section)
Definition: serialize.cc:200
#define warn(...)
Definition: logging.hh:246
Bitfield< 7 > i
Definition: misc_types.hh:67
Bitfield< 23, 0 > offset
Definition: types.hh:144
Bitfield< 8 > a
Definition: misc_types.hh:66
Bitfield< 12, 11 > set
Definition: misc_types.hh:709
Bitfield< 25, 21 > to
Definition: types.hh:96
Bitfield< 4 > x
Definition: pagetable.hh:61
Bitfield< 54 > p
Definition: pagetable.hh:70
Bitfield< 63 > val
Definition: misc.hh:776
Bitfield< 3 > addr
Definition: types.hh:84
Reference material can be found at the JEDEC website: UFS standard http://www.jedec....
Tick curTick()
The universal simulation clock.
Definition: cur_tick.hh:46
std::ostream CheckpointOut
Definition: serialize.hh:66
uint64_t Addr
Address type This will probably be moved somewhere else in the near future.
Definition: types.hh:147
uint64_t Tick
Tick count type.
Definition: types.hh:58
int ContextID
Globally unique thread context ID.
Definition: types.hh:239
std::string csprintf(const char *format, const Args &...args)
Definition: cprintf.hh:161
Declaration of the Packet class.
#define UNSERIALIZE_SCALAR(scalar)
Definition: serialize.hh:575
#define SERIALIZE_SCALAR(scalar)
Definition: serialize.hh:568
Registers "banked for each connected processor" per ARM IHI0048B.
Definition: gic_v2.hh:213
uint32_t intEnabled
GICD_I{S,C}ENABLER0 interrupt enable bits for first 32 interrupts, 1b per interrupt.
Definition: gic_v2.hh:216
uint32_t intGroup
GICD_IGROUPR0 interrupt group bits for first 32 interrupts, 1b per interrupt.
Definition: gic_v2.hh:228
uint32_t activeInt
GICD_I{S,C}ACTIVER0 interrupt active bits for first 32 interrupts, 1b per interrupt.
Definition: gic_v2.hh:224
void unserialize(CheckpointIn &cp) override
Unserialize an object.
Definition: gic_v2.cc:1222
uint8_t intPriority[SGI_MAX+PPI_MAX]
GICD_IPRIORITYR{0..7} interrupt priority for SGIs and PPIs.
Definition: gic_v2.hh:236
void serialize(CheckpointOut &cp) const override
Serialize an object.
Definition: gic_v2.cc:1162
uint32_t pendingInt
GICD_I{S,C}PENDR0 interrupt pending bits for first 32 interrupts, 1b per interrupt.
Definition: gic_v2.hh:220
uint32_t intConfig[2]
GICD_ICFGR0, GICD_ICFGR1 interrupt config bits for first 32 interrupts, 2b per interrupt.
Definition: gic_v2.hh:232

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