hw/intc/arm_gicv3: Implement gicv3_set_irq()
Implement the code which updates the GIC state when an interrupt input into the GIC is asserted. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Shannon Zhao <shannon.zhao@linaro.org> Tested-by: Shannon Zhao <shannon.zhao@linaro.org> Message-id: 1465915112-29272-15-git-send-email-peter.maydell@linaro.org
This commit is contained in:
parent
287c181ae4
commit
c84428b33f
@ -311,7 +311,25 @@ static void gicv3_set_irq(void *opaque, int irq, int level)
|
||||
* [N+32..N+63] : PPI (internal interrupts for CPU 1
|
||||
* ...
|
||||
*/
|
||||
/* Do nothing for now */
|
||||
GICv3State *s = opaque;
|
||||
|
||||
if (irq < (s->num_irq - GIC_INTERNAL)) {
|
||||
/* external interrupt (SPI) */
|
||||
gicv3_dist_set_irq(s, irq + GIC_INTERNAL, level);
|
||||
} else {
|
||||
/* per-cpu interrupt (PPI) */
|
||||
int cpu;
|
||||
|
||||
irq -= (s->num_irq - GIC_INTERNAL);
|
||||
cpu = irq / GIC_INTERNAL;
|
||||
irq %= GIC_INTERNAL;
|
||||
assert(cpu < s->num_cpu);
|
||||
/* Raising SGIs via this function would be a bug in how the board
|
||||
* model wires up interrupts.
|
||||
*/
|
||||
assert(irq >= GIC_NR_SGIS);
|
||||
gicv3_redist_set_irq(&s->cpu[cpu], irq, level);
|
||||
}
|
||||
}
|
||||
|
||||
static void arm_gicv3_post_load(GICv3State *s)
|
||||
|
@ -856,3 +856,24 @@ MemTxResult gicv3_dist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void gicv3_dist_set_irq(GICv3State *s, int irq, int level)
|
||||
{
|
||||
/* Update distributor state for a change in an external SPI input line */
|
||||
if (level == gicv3_gicd_level_test(s, irq)) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_gicv3_dist_set_irq(irq, level);
|
||||
|
||||
gicv3_gicd_level_replace(s, irq, level);
|
||||
|
||||
if (level) {
|
||||
/* 0->1 edges latch the pending bit for edge-triggered interrupts */
|
||||
if (gicv3_gicd_edge_trigger_test(s, irq)) {
|
||||
gicv3_gicd_pending_set(s, irq);
|
||||
}
|
||||
}
|
||||
|
||||
gicv3_update(s, irq, 1);
|
||||
}
|
||||
|
@ -499,3 +499,24 @@ MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level)
|
||||
{
|
||||
/* Update redistributor state for a change in an external PPI input line */
|
||||
if (level == extract32(cs->level, irq, 1)) {
|
||||
return;
|
||||
}
|
||||
|
||||
trace_gicv3_redist_set_irq(gicv3_redist_affid(cs), irq, level);
|
||||
|
||||
cs->level = deposit32(cs->level, irq, 1, level);
|
||||
|
||||
if (level) {
|
||||
/* 0->1 edges latch the pending bit for edge-triggered interrupts */
|
||||
if (extract32(cs->edge_trigger, irq, 1)) {
|
||||
cs->gicr_ipendr0 = deposit32(cs->gicr_ipendr0, irq, 1, 1);
|
||||
}
|
||||
}
|
||||
|
||||
gicv3_redist_update(cs);
|
||||
}
|
||||
|
@ -209,6 +209,8 @@ MemTxResult gicv3_redist_read(void *opaque, hwaddr offset, uint64_t *data,
|
||||
unsigned size, MemTxAttrs attrs);
|
||||
MemTxResult gicv3_redist_write(void *opaque, hwaddr offset, uint64_t data,
|
||||
unsigned size, MemTxAttrs attrs);
|
||||
void gicv3_dist_set_irq(GICv3State *s, int irq, int level);
|
||||
void gicv3_redist_set_irq(GICv3CPUState *cs, int irq, int level);
|
||||
|
||||
/**
|
||||
* gicv3_cpuif_update:
|
||||
|
@ -2171,9 +2171,11 @@ gicv3_dist_read(uint64_t offset, uint64_t data, unsigned size, bool secure) "GIC
|
||||
gicv3_dist_badread(uint64_t offset, unsigned size, bool secure) "GICv3 distributor read: offset 0x%" PRIx64 " size %u secure %d: error"
|
||||
gicv3_dist_write(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
|
||||
gicv3_dist_badwrite(uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 distributor write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
|
||||
gicv3_dist_set_irq(int irq, int level) "GICv3 distributor interrupt %d level changed to %d"
|
||||
|
||||
# hw/intc/arm_gicv3_redist.c
|
||||
gicv3_redist_read(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x read: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
|
||||
gicv3_redist_badread(uint32_t cpu, uint64_t offset, unsigned size, bool secure) "GICv3 redistributor %x read: offset 0x%" PRIx64 " size %u secure %d: error"
|
||||
gicv3_redist_write(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d"
|
||||
gicv3_redist_badwrite(uint32_t cpu, uint64_t offset, uint64_t data, unsigned size, bool secure) "GICv3 redistributor %x write: offset 0x%" PRIx64 " data 0x%" PRIx64 " size %u secure %d: error"
|
||||
gicv3_redist_set_irq(uint32_t cpu, int irq, int level) "GICv3 redistributor %x interrupt %d level changed to %d"
|
||||
|
Loading…
Reference in New Issue
Block a user