ced2464851ae26ff732fd4c0f9271ab4ada3b703
2 * Copyright (c) 2010, 2013 ARM Limited
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.
14 * Copyright (c) 2005 The Regents of The University of Michigan
15 * All rights reserved.
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.
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.
44 #include "base/trace.hh"
45 #include "debug/Checkpoint.hh"
46 #include "debug/GIC.hh"
47 #include "debug/IPI.hh"
48 #include "debug/Interrupt.hh"
49 #include "dev/arm/gic_pl390.hh"
50 #include "dev/terminal.hh"
51 #include "mem/packet.hh"
52 #include "mem/packet_access.hh"
54 Pl390::Pl390(const Params
*p
)
55 : BaseGic(p
), distAddr(p
->dist_addr
),
56 cpuAddr(p
->cpu_addr
), distPioDelay(p
->dist_pio_delay
),
57 cpuPioDelay(p
->cpu_pio_delay
), intLatency(p
->int_latency
),
58 enabled(false), itLines(p
->it_lines
), irqEnable(false)
60 itLinesLog2
= ceilLog2(itLines
);
62 for (int x
= 0; x
< CPU_MAX
; x
++) {
63 cpuEnabled
[x
] = false;
64 cpuPriority
[x
] = 0xff;
66 // Initialize cpu highest int
67 cpuHighestInt
[x
] = SPURIOUS_INT
;
68 postIntEvent
[x
] = new PostIntEvent(x
, p
->platform
);
70 DPRINTF(Interrupt
, "cpuEnabled[0]=%d cpuEnabled[1]=%d\n", cpuEnabled
[0],
73 for (int x
= 0; x
< INT_BITS_MAX
; x
++) {
79 for (int x
= 0; x
< INT_LINES_MAX
; x
++) {
84 for (int x
= 0; x
< INT_BITS_MAX
*2; x
++) {
88 for (int x
= 0; x
< SGI_MAX
; x
++) {
92 for (int x
= 0; x
< CPU_MAX
; x
++) {
97 for (int i
= 0; i
< CPU_MAX
; i
++) {
98 for (int j
= 0; j
< (SGI_MAX
+ PPI_MAX
); j
++) {
99 bankedIntPriority
[i
][j
] = 0;
105 Pl390::read(PacketPtr pkt
)
108 Addr addr
= pkt
->getAddr();
110 if (addr
>= distAddr
&& addr
< distAddr
+ DIST_SIZE
)
111 return readDistributor(pkt
);
112 else if (addr
>= cpuAddr
&& addr
< cpuAddr
+ CPU_SIZE
)
115 panic("Read to unknown address %#x\n", pkt
->getAddr());
120 Pl390::write(PacketPtr pkt
)
123 Addr addr
= pkt
->getAddr();
125 if (addr
>= distAddr
&& addr
< distAddr
+ DIST_SIZE
)
126 return writeDistributor(pkt
);
127 else if (addr
>= cpuAddr
&& addr
< cpuAddr
+ CPU_SIZE
)
128 return writeCpu(pkt
);
130 panic("Write to unknown address %#x\n", pkt
->getAddr());
134 Pl390::readDistributor(PacketPtr pkt
)
136 Addr daddr
= pkt
->getAddr() - distAddr
;
138 int ctx_id
= pkt
->req
->contextId();
140 DPRINTF(GIC
, "gic distributor read register %#x\n", daddr
);
142 if (daddr
>= ICDISER_ST
&& daddr
< ICDISER_ED
+ 4) {
143 assert((daddr
-ICDISER_ST
) >> 2 < 32);
144 pkt
->set
<uint32_t>(intEnabled
[(daddr
-ICDISER_ST
)>>2]);
148 if (daddr
>= ICDICER_ST
&& daddr
< ICDICER_ED
+ 4) {
149 assert((daddr
-ICDICER_ST
) >> 2 < 32);
150 pkt
->set
<uint32_t>(intEnabled
[(daddr
-ICDICER_ST
)>>2]);
154 if (daddr
>= ICDISPR_ST
&& daddr
< ICDISPR_ED
+ 4) {
155 assert((daddr
-ICDISPR_ST
) >> 2 < 32);
156 pkt
->set
<uint32_t>(pendingInt
[(daddr
-ICDISPR_ST
)>>2]);
160 if (daddr
>= ICDICPR_ST
&& daddr
< ICDICPR_ED
+ 4) {
161 assert((daddr
-ICDICPR_ST
) >> 2 < 32);
162 pkt
->set
<uint32_t>(pendingInt
[(daddr
-ICDICPR_ST
)>>2]);
166 if (daddr
>= ICDABR_ST
&& daddr
< ICDABR_ED
+ 4) {
167 assert((daddr
-ICDABR_ST
) >> 2 < 32);
168 pkt
->set
<uint32_t>(activeInt
[(daddr
-ICDABR_ST
)>>2]);
172 if (daddr
>= ICDIPR_ST
&& daddr
< ICDIPR_ED
+ 4) {
174 int_num
= daddr
- ICDIPR_ST
;
175 assert(int_num
< INT_LINES_MAX
);
176 DPRINTF(Interrupt
, "Reading interrupt priority at int# %#x \n",int_num
);
179 if (int_num
< (SGI_MAX
+ PPI_MAX
))
180 int_p
= bankedIntPriority
[ctx_id
];
184 switch (pkt
->getSize()) {
186 pkt
->set
<uint8_t>(int_p
[int_num
]);
189 assert((int_num
+ 1) < INT_LINES_MAX
);
190 pkt
->set
<uint16_t>(int_p
[int_num
] |
191 int_p
[int_num
+1] << 8);
194 assert((int_num
+ 3) < INT_LINES_MAX
);
195 pkt
->set
<uint32_t>(int_p
[int_num
] |
196 int_p
[int_num
+1] << 8 |
197 int_p
[int_num
+2] << 16 |
198 int_p
[int_num
+3] << 24);
201 panic("Invalid size while reading priority regs in GIC: %d\n",
207 if (daddr
>= ICDIPTR_ST
&& daddr
< ICDIPTR_ED
+ 4) {
209 int_num
= (daddr
-ICDIPTR_ST
) ;
210 DPRINTF(GIC
, "Reading processor target register for int# %#x \n",
212 assert(int_num
< INT_LINES_MAX
);
214 // First 31 interrupts only target single processor (SGI)
216 if (pkt
->getSize() == 1) {
217 pkt
->set
<uint8_t>(cpuTarget
[int_num
]);
219 assert(pkt
->getSize() == 4);
220 int_num
= mbits(int_num
, 31, 2);
221 pkt
->set
<uint32_t>(cpuTarget
[int_num
] |
222 cpuTarget
[int_num
+1] << 8 |
223 cpuTarget
[int_num
+2] << 16 |
224 cpuTarget
[int_num
+3] << 24) ;
227 assert(ctx_id
< sys
->numRunningContexts());
228 // convert the CPU id number into a bit mask
229 uint32_t ctx_mask
= power(2, ctx_id
);
230 // replicate the 8-bit mask 4 times in a 32-bit word
231 ctx_mask
|= ctx_mask
<< 8;
232 ctx_mask
|= ctx_mask
<< 16;
233 pkt
->set
<uint32_t>(ctx_mask
);
238 if (daddr
>= ICDICFR_ST
&& daddr
< ICDICFR_ED
+ 4) {
239 assert((daddr
-ICDICFR_ST
) >> 2 < 64);
240 /** @todo software generated interrutps and PPIs
241 * can't be configured in some ways
243 pkt
->set
<uint32_t>(intConfig
[(daddr
-ICDICFR_ST
)>>2]);
249 pkt
->set
<uint32_t>(enabled
);
253 tmp
= ((sys
->numRunningContexts() - 1) << 5) |
254 (itLines
/INT_BITS_MAX
-1);
255 pkt
->set
<uint32_t>(tmp
);
258 panic("Tried to read Gic distributor at offset %#x\n", daddr
);
262 pkt
->makeAtomicResponse();
267 Pl390::readCpu(PacketPtr pkt
)
269 Addr daddr
= pkt
->getAddr() - cpuAddr
;
271 assert(pkt
->req
->hasContextId());
272 int ctx_id
= pkt
->req
->contextId();
273 assert(ctx_id
< sys
->numRunningContexts());
275 DPRINTF(GIC
, "gic cpu read register %#x cpu context: %d\n", daddr
,
280 pkt
->set
<uint32_t>(cpuEnabled
[ctx_id
]);
283 pkt
->set
<uint32_t>(cpuPriority
[ctx_id
]);
286 pkt
->set
<uint32_t>(cpuBpr
[ctx_id
]);
289 if (enabled
&& cpuEnabled
[ctx_id
]) {
290 int active_int
= cpuHighestInt
[ctx_id
];
292 iar
.ack_id
= active_int
;
294 if (active_int
< SGI_MAX
) {
295 // this is a software interrupt from another CPU
296 if (!cpuSgiPending
[active_int
])
297 panic("Interrupt %d active but no CPU generated it?\n",
299 for (int x
= 0; x
< CPU_MAX
; x
++) {
300 // See which CPU generated the interrupt
302 bits(cpuSgiPending
[active_int
], 7 + 8 * x
, 8 * x
);
303 if (cpugen
& (1 << ctx_id
)) {
308 uint64_t sgi_num
= ULL(1) << (ctx_id
+ 8 * iar
.cpu_id
);
309 cpuSgiActive
[iar
.ack_id
] |= sgi_num
;
310 cpuSgiPending
[iar
.ack_id
] &= ~sgi_num
;
311 } else if (active_int
< (SGI_MAX
+ PPI_MAX
) ) {
312 uint32_t int_num
= 1 << (cpuHighestInt
[ctx_id
] - SGI_MAX
);
313 cpuPpiActive
[ctx_id
] |= int_num
;
315 cpuPpiPending
[ctx_id
] &= ~int_num
;
318 uint32_t int_num
= 1 << intNumToBit(cpuHighestInt
[ctx_id
]);
319 activeInt
[intNumToWord(cpuHighestInt
[ctx_id
])] |= int_num
;
321 pendingInt
[intNumToWord(cpuHighestInt
[ctx_id
])] &= ~int_num
;
324 DPRINTF(Interrupt
,"CPU %d reading IAR.id=%d IAR.cpu=%d, iar=0x%x\n",
325 ctx_id
, iar
.ack_id
, iar
.cpu_id
, iar
);
326 cpuHighestInt
[ctx_id
] = SPURIOUS_INT
;
328 pkt
->set
<uint32_t>(iar
);
329 platform
->intrctrl
->clear(ctx_id
, ArmISA::INT_IRQ
, 0);
331 pkt
->set
<uint32_t>(SPURIOUS_INT
);
336 pkt
->set
<uint32_t>(iccrpr
[0]);
339 pkt
->set
<uint32_t>(0);
340 panic("Need to implement HPIR");
343 panic("Tried to read Gic cpu at offset %#x\n", daddr
);
346 pkt
->makeAtomicResponse();
351 Pl390::writeDistributor(PacketPtr pkt
)
353 Addr daddr
= pkt
->getAddr() - distAddr
;
355 assert(pkt
->req
->hasContextId());
356 int ctx_id
= pkt
->req
->contextId();
358 uint32_t pkt_data M5_VAR_USED
;
359 switch (pkt
->getSize())
362 pkt_data
= pkt
->get
<uint8_t>();
365 pkt_data
= pkt
->get
<uint16_t>();
368 pkt_data
= pkt
->get
<uint32_t>();
371 panic("Invalid size when writing to priority regs in Gic: %d\n",
375 DPRINTF(GIC
, "gic distributor write register %#x size %#x value %#x \n",
376 daddr
, pkt
->getSize(), pkt_data
);
378 if (daddr
>= ICDISER_ST
&& daddr
< ICDISER_ED
+ 4) {
379 assert((daddr
-ICDISER_ST
) >> 2 < 32);
380 intEnabled
[(daddr
-ICDISER_ST
) >> 2] |= pkt
->get
<uint32_t>();
384 if (daddr
>= ICDICER_ST
&& daddr
< ICDICER_ED
+ 4) {
385 assert((daddr
-ICDICER_ST
) >> 2 < 32);
386 intEnabled
[(daddr
-ICDICER_ST
) >> 2] &= ~pkt
->get
<uint32_t>();
390 if (daddr
>= ICDISPR_ST
&& daddr
< ICDISPR_ED
+ 4) {
391 assert((daddr
-ICDISPR_ST
) >> 2 < 32);
392 pendingInt
[(daddr
-ICDISPR_ST
) >> 2] |= pkt
->get
<uint32_t>();
393 pendingInt
[0] &= SGI_MASK
; // Don't allow SGIs to be changed
394 updateIntState((daddr
-ICDISPR_ST
) >> 2);
398 if (daddr
>= ICDICPR_ST
&& daddr
< ICDICPR_ED
+ 4) {
399 assert((daddr
-ICDICPR_ST
) >> 2 < 32);
400 pendingInt
[(daddr
-ICDICPR_ST
) >> 2] &= ~pkt
->get
<uint32_t>();
401 pendingInt
[0] &= SGI_MASK
; // Don't allow SGIs to be changed
402 updateIntState((daddr
-ICDICPR_ST
) >> 2);
406 if (daddr
>= ICDIPR_ST
&& daddr
< ICDIPR_ED
+ 4) {
407 Addr int_num
= daddr
- ICDIPR_ST
;
408 assert(int_num
< INT_LINES_MAX
);
410 if (int_num
< (SGI_MAX
+ PPI_MAX
))
411 int_p
= bankedIntPriority
[ctx_id
];
415 switch(pkt
->getSize()) {
417 tmp
= pkt
->get
<uint8_t>();
418 int_p
[int_num
] = bits(tmp
, 7, 0);
421 tmp
= pkt
->get
<uint16_t>();
422 int_p
[int_num
] = bits(tmp
, 7, 0);
423 int_p
[int_num
+ 1] = bits(tmp
, 15, 8);
426 tmp
= pkt
->get
<uint32_t>();
427 int_p
[int_num
] = bits(tmp
, 7, 0);
428 int_p
[int_num
+ 1] = bits(tmp
, 15, 8);
429 int_p
[int_num
+ 2] = bits(tmp
, 23, 16);
430 int_p
[int_num
+ 3] = bits(tmp
, 31, 24);
433 panic("Invalid size when writing to priority regs in Gic: %d\n",
442 if (daddr
>= ICDIPTR_ST
&& daddr
< ICDIPTR_ED
+ 4) {
443 Addr int_num
= (daddr
-ICDIPTR_ST
) ;
444 assert(int_num
< INT_LINES_MAX
);
445 // First 31 interrupts only target single processor
446 if (int_num
>= SGI_MAX
) {
447 if (pkt
->getSize() == 1) {
448 uint8_t tmp
= pkt
->get
<uint8_t>();
449 cpuTarget
[int_num
] = tmp
& 0xff;
451 assert (pkt
->getSize() == 4);
452 int_num
= mbits(int_num
, 31, 2);
453 uint32_t tmp
= pkt
->get
<uint32_t>();
454 cpuTarget
[int_num
] = bits(tmp
, 7, 0);
455 cpuTarget
[int_num
+1] = bits(tmp
, 15, 8);
456 cpuTarget
[int_num
+2] = bits(tmp
, 23, 16);
457 cpuTarget
[int_num
+3] = bits(tmp
, 31, 24);
459 updateIntState((daddr
-ICDIPTR_ST
)>>2);
464 if (daddr
>= ICDICFR_ST
&& daddr
< ICDICFR_ED
+ 4) {
465 assert((daddr
-ICDICFR_ST
) >> 2 < 64);
466 intConfig
[(daddr
-ICDICFR_ST
)>>2] = pkt
->get
<uint32_t>();
467 if (pkt
->get
<uint32_t>() & NN_CONFIG_MASK
)
468 warn("GIC N:N mode selected and not supported at this time\n");
474 enabled
= pkt
->get
<uint32_t>();
475 DPRINTF(Interrupt
, "Distributor enable flag set to = %d\n", enabled
);
478 softInt(ctx_id
, pkt
->get
<uint32_t>());
481 panic("Tried to write Gic distributor at offset %#x\n", daddr
);
486 pkt
->makeAtomicResponse();
491 Pl390::writeCpu(PacketPtr pkt
)
493 Addr daddr
= pkt
->getAddr() - cpuAddr
;
495 assert(pkt
->req
->hasContextId());
496 int ctx_id
= pkt
->req
->contextId();
499 DPRINTF(GIC
, "gic cpu write register cpu:%d %#x val: %#x\n",
500 ctx_id
, daddr
, pkt
->get
<uint32_t>());
504 cpuEnabled
[ctx_id
] = pkt
->get
<uint32_t>();
507 cpuPriority
[ctx_id
] = pkt
->get
<uint32_t>();
510 cpuBpr
[ctx_id
] = pkt
->get
<uint32_t>();
513 iar
= pkt
->get
<uint32_t>();
514 if (iar
.ack_id
< SGI_MAX
) {
515 // Clear out the bit that corrseponds to the cleared int
516 uint64_t clr_int
= ULL(1) << (ctx_id
+ 8 * iar
.cpu_id
);
517 if (!(cpuSgiActive
[iar
.ack_id
] & clr_int
))
518 panic("Done handling a SGI that isn't active?\n");
519 cpuSgiActive
[iar
.ack_id
] &= ~clr_int
;
520 } else if (iar
.ack_id
< (SGI_MAX
+ PPI_MAX
) ) {
521 uint32_t int_num
= 1 << (iar
.ack_id
- SGI_MAX
);
522 if (!(cpuPpiActive
[ctx_id
] & int_num
))
523 panic("CPU %d Done handling a PPI interrupt that isn't active?\n", ctx_id
);
524 cpuPpiActive
[ctx_id
] &= ~int_num
;
526 uint32_t int_num
= 1 << intNumToBit(iar
.ack_id
);
527 if (!(activeInt
[intNumToWord(iar
.ack_id
)] & int_num
))
528 panic("Done handling interrupt that isn't active?\n");
529 activeInt
[intNumToWord(iar
.ack_id
)] &= ~int_num
;
532 DPRINTF(Interrupt
, "CPU %d done handling intr IAR = %d from cpu %d\n",
533 ctx_id
, iar
.ack_id
, iar
.cpu_id
);
536 panic("Tried to write Gic cpu at offset %#x\n", daddr
);
539 if (cpuEnabled
[ctx_id
]) updateIntState(-1);
540 pkt
->makeAtomicResponse();
545 Pl390::softInt(int ctx_id
, SWI swi
)
547 switch (swi
.list_type
) {
552 for (int x
= 0; x
< CPU_MAX
; x
++)
553 cpu_list
|= cpuEnabled
[x
] ? 1 << x
: 0;
554 swi
.cpu_list
= cpu_list
;
557 // interrupt requesting cpu only
558 swi
.cpu_list
= 1 << ctx_id
;
560 // else interrupt cpus specified
563 DPRINTF(IPI
, "Generating softIRQ from CPU %d for %#x\n", ctx_id
,
565 for (int i
= 0; i
< CPU_MAX
; i
++) {
566 DPRINTF(IPI
, "Processing CPU %d\n", i
);
569 if (swi
.cpu_list
& (1 << i
))
570 cpuSgiPending
[swi
.sgi_id
] |= (1 << i
) << (8 * ctx_id
);
571 DPRINTF(IPI
, "SGI[%d]=%#x\n", swi
.sgi_id
, cpuSgiPending
[swi
.sgi_id
]);
577 Pl390::genSwiMask(int cpu
)
580 panic("Invalid CPU ID\n");
581 return ULL(0x0101010101010101) << cpu
;
585 Pl390::updateIntState(int hint
)
587 for (int cpu
= 0; cpu
< CPU_MAX
; cpu
++) {
588 if (!cpuEnabled
[cpu
])
590 if (cpu
>= sys
->numContexts())
593 /*@todo use hint to do less work. */
594 int highest_int
= SPURIOUS_INT
;
595 // Priorities below that set in ICCPMR can be ignored
596 uint8_t highest_pri
= cpuPriority
[cpu
];
599 for (int swi
= 0; swi
< SGI_MAX
; swi
++) {
600 if (!cpuSgiPending
[swi
])
602 if (cpuSgiPending
[swi
] & genSwiMask(cpu
))
603 if (highest_pri
> bankedIntPriority
[cpu
][swi
]) {
604 highest_pri
= bankedIntPriority
[cpu
][swi
];
610 if (cpuPpiPending
[cpu
]) {
611 for (int ppi
= 0; ppi
< PPI_MAX
; ppi
++) {
612 if (cpuPpiPending
[cpu
] & (1 << ppi
))
613 if (highest_pri
> bankedIntPriority
[cpu
][SGI_MAX
+ ppi
]) {
614 highest_pri
= bankedIntPriority
[cpu
][SGI_MAX
+ ppi
];
615 highest_int
= SGI_MAX
+ ppi
;
620 bool mp_sys
= sys
->numRunningContexts() > 1;
622 for (int x
= 0; x
< (itLines
/INT_BITS_MAX
); x
++) {
623 if (intEnabled
[x
] & pendingInt
[x
]) {
624 for (int y
= 0; y
< INT_BITS_MAX
; y
++) {
625 uint32_t int_nm
= x
* INT_BITS_MAX
+ y
;
626 DPRINTF(GIC
, "Checking for interrupt# %d \n",int_nm
);
627 /* Set current pending int as highest int for current cpu
628 if the interrupt's priority higher than current prioirty
629 and if currrent cpu is the target (for mp configs only)
631 if ((bits(intEnabled
[x
], y
) & bits(pendingInt
[x
], y
)) &&
632 (intPriority
[int_nm
] < highest_pri
))
633 if ( (!mp_sys
) || (cpuTarget
[int_nm
] & (1 << cpu
))) {
634 highest_pri
= intPriority
[int_nm
];
635 highest_int
= int_nm
;
641 cpuHighestInt
[cpu
] = highest_int
;
643 if (highest_int
== SPURIOUS_INT
)
646 /* @todo make this work for more than one cpu, need to handle 1:N, N:N
648 if (enabled
&& cpuEnabled
[cpu
] && (highest_pri
< cpuPriority
[cpu
]) &&
649 !(activeInt
[intNumToWord(highest_int
)]
650 & (1 << intNumToBit(highest_int
)))) {
652 DPRINTF(Interrupt
, "Posting interrupt %d to cpu%d\n", highest_int
,
654 postInt(cpu
, curTick() + intLatency
);
660 Pl390::updateRunPri()
662 for (int cpu
= 0; cpu
< CPU_MAX
; cpu
++) {
663 if (!cpuEnabled
[cpu
])
665 uint8_t maxPriority
= 0xff;
666 for (int i
= 0; i
< itLines
; i
++){
668 if ((cpuSgiActive
[i
] & genSwiMask(cpu
)) &&
669 (bankedIntPriority
[cpu
][i
] < maxPriority
))
670 maxPriority
= bankedIntPriority
[cpu
][i
];
671 } else if (i
< (SGI_MAX
+ PPI_MAX
)) {
672 if ((cpuPpiActive
[cpu
] & ( 1 << (i
- SGI_MAX
))) &&
673 (bankedIntPriority
[cpu
][i
] < maxPriority
))
674 maxPriority
= bankedIntPriority
[cpu
][i
];
677 if (activeInt
[intNumToWord(i
)] & (1 << intNumToBit(i
)))
678 if (intPriority
[i
] < maxPriority
)
679 maxPriority
= intPriority
[i
];
682 iccrpr
[cpu
] = maxPriority
;
687 Pl390::sendInt(uint32_t num
)
689 DPRINTF(Interrupt
, "Received Interupt number %d, cpuTarget %#x: \n",
690 num
, cpuTarget
[num
]);
691 if (cpuTarget
[num
] & (cpuTarget
[num
] - 1))
692 panic("Multiple targets for peripheral interrupts is not supported\n");
693 pendingInt
[intNumToWord(num
)] |= 1 << intNumToBit(num
);
694 updateIntState(intNumToWord(num
));
699 Pl390::sendPPInt(uint32_t num
, uint32_t cpu
)
701 DPRINTF(Interrupt
, "Received PPI %d, cpuTarget %#x: \n",
703 cpuPpiPending
[cpu
] |= 1 << (num
- SGI_MAX
);
704 updateIntState(intNumToWord(num
));
708 Pl390::clearInt(uint32_t number
)
710 /* @todo assume edge triggered only at the moment. Nothing to do. */
714 Pl390::clearPPInt(uint32_t num
, uint32_t cpu
)
716 DPRINTF(Interrupt
, "Clearing PPI %d, cpuTarget %#x: \n",
718 cpuPpiPending
[cpu
] &= ~(1 << (num
- SGI_MAX
));
719 updateIntState(intNumToWord(num
));
723 Pl390::postInt(uint32_t cpu
, Tick when
)
725 if (!(postIntEvent
[cpu
]->scheduled()))
726 eventq
->schedule(postIntEvent
[cpu
], when
);
730 Pl390::getAddrRanges() const
732 AddrRangeList ranges
;
733 ranges
.push_back(RangeSize(distAddr
, DIST_SIZE
));
734 ranges
.push_back(RangeSize(cpuAddr
, CPU_SIZE
));
740 Pl390::serialize(std::ostream
&os
)
742 DPRINTF(Checkpoint
, "Serializing Arm GIC\n");
744 SERIALIZE_SCALAR(distAddr
);
745 SERIALIZE_SCALAR(cpuAddr
);
746 SERIALIZE_SCALAR(distPioDelay
);
747 SERIALIZE_SCALAR(cpuPioDelay
);
748 SERIALIZE_SCALAR(enabled
);
749 SERIALIZE_SCALAR(itLines
);
750 SERIALIZE_SCALAR(itLinesLog2
);
751 SERIALIZE_ARRAY(intEnabled
, INT_BITS_MAX
);
752 SERIALIZE_ARRAY(pendingInt
, INT_BITS_MAX
);
753 SERIALIZE_ARRAY(activeInt
, INT_BITS_MAX
);
754 SERIALIZE_ARRAY(iccrpr
, CPU_MAX
);
755 SERIALIZE_ARRAY(intPriority
, INT_LINES_MAX
);
756 SERIALIZE_ARRAY(cpuTarget
, INT_LINES_MAX
);
757 SERIALIZE_ARRAY(intConfig
, INT_BITS_MAX
* 2);
758 SERIALIZE_ARRAY(cpuEnabled
, CPU_MAX
);
759 SERIALIZE_ARRAY(cpuPriority
, CPU_MAX
);
760 SERIALIZE_ARRAY(cpuBpr
, CPU_MAX
);
761 SERIALIZE_ARRAY(cpuHighestInt
, CPU_MAX
);
762 SERIALIZE_ARRAY(cpuSgiActive
, SGI_MAX
);
763 SERIALIZE_ARRAY(cpuSgiPending
, SGI_MAX
);
764 SERIALIZE_ARRAY(cpuPpiActive
, CPU_MAX
);
765 SERIALIZE_ARRAY(cpuPpiPending
, CPU_MAX
);
766 SERIALIZE_ARRAY(*bankedIntPriority
, CPU_MAX
* (SGI_MAX
+ PPI_MAX
));
767 SERIALIZE_SCALAR(irqEnable
);
768 Tick interrupt_time
[CPU_MAX
];
769 for (uint32_t cpu
= 0; cpu
< CPU_MAX
; cpu
++) {
770 interrupt_time
[cpu
] = 0;
771 if (postIntEvent
[cpu
]->scheduled()) {
772 interrupt_time
[cpu
] = postIntEvent
[cpu
]->when();
775 SERIALIZE_ARRAY(interrupt_time
, CPU_MAX
);
780 Pl390::unserialize(Checkpoint
*cp
, const std::string
§ion
)
782 DPRINTF(Checkpoint
, "Unserializing Arm GIC\n");
784 UNSERIALIZE_SCALAR(distAddr
);
785 UNSERIALIZE_SCALAR(cpuAddr
);
786 UNSERIALIZE_SCALAR(distPioDelay
);
787 UNSERIALIZE_SCALAR(cpuPioDelay
);
788 UNSERIALIZE_SCALAR(enabled
);
789 UNSERIALIZE_SCALAR(itLines
);
790 UNSERIALIZE_SCALAR(itLinesLog2
);
791 UNSERIALIZE_ARRAY(intEnabled
, INT_BITS_MAX
);
792 UNSERIALIZE_ARRAY(pendingInt
, INT_BITS_MAX
);
793 UNSERIALIZE_ARRAY(activeInt
, INT_BITS_MAX
);
794 UNSERIALIZE_ARRAY(iccrpr
, CPU_MAX
);
795 UNSERIALIZE_ARRAY(intPriority
, INT_LINES_MAX
);
796 UNSERIALIZE_ARRAY(cpuTarget
, INT_LINES_MAX
);
797 UNSERIALIZE_ARRAY(intConfig
, INT_BITS_MAX
* 2);
798 UNSERIALIZE_ARRAY(cpuEnabled
, CPU_MAX
);
799 UNSERIALIZE_ARRAY(cpuPriority
, CPU_MAX
);
800 UNSERIALIZE_ARRAY(cpuBpr
, CPU_MAX
);
801 UNSERIALIZE_ARRAY(cpuHighestInt
, CPU_MAX
);
802 UNSERIALIZE_ARRAY(cpuSgiActive
, SGI_MAX
);
803 UNSERIALIZE_ARRAY(cpuSgiPending
, SGI_MAX
);
804 UNSERIALIZE_ARRAY(cpuPpiActive
, CPU_MAX
);
805 UNSERIALIZE_ARRAY(cpuPpiPending
, CPU_MAX
);
806 UNSERIALIZE_ARRAY(*bankedIntPriority
, CPU_MAX
* (SGI_MAX
+ PPI_MAX
));
807 UNSERIALIZE_SCALAR(irqEnable
);
809 Tick interrupt_time
[CPU_MAX
];
810 UNSERIALIZE_ARRAY(interrupt_time
, CPU_MAX
);
812 for (uint32_t cpu
= 0; cpu
< CPU_MAX
; cpu
++) {
813 if (interrupt_time
[cpu
])
814 schedule(postIntEvent
[cpu
], interrupt_time
[cpu
]);
820 Pl390Params::create()
822 return new Pl390(this);
825 /* Functions for debugging and testing */
827 Pl390::driveSPI(unsigned int spiVect
)
829 DPRINTF(GIC
, "Received SPI Vector:%x Enable: %d\n", spiVect
, irqEnable
);
830 pendingInt
[1] |= spiVect
;
831 if (irqEnable
&& enabled
) {
837 Pl390::driveIrqEn( bool state
)
840 DPRINTF(GIC
, " Enabling Irq\n");
845 Pl390::driveLegIRQ(bool state
)
847 if (irqEnable
&& !(!enabled
&& cpuEnabled
[0])) {
849 DPRINTF(GIC
, "Driving Legacy Irq\n");
850 platform
->intrctrl
->post(0, ArmISA::INT_IRQ
, 0);
852 else platform
->intrctrl
->clear(0, ArmISA::INT_IRQ
, 0);
857 Pl390::driveLegFIQ(bool state
)
860 platform
->intrctrl
->post(0, ArmISA::INT_FIQ
, 0);
861 else platform
->intrctrl
->clear(0, ArmISA::INT_FIQ
, 0);