@ -21,7 +21,7 @@
# include "hw/intc/arm_gicv3.h"
# include "gicv3_internal.h"
static bool irqbetter ( GICv3CPUState * cs , int irq , uint8_t prio )
static bool irqbetter ( GICv3CPUState * cs , int irq , uint8_t prio , bool nmi )
{
/* Return true if this IRQ at this priority should take
* precedence over the current recorded highest priority
@ -30,14 +30,23 @@ static bool irqbetter(GICv3CPUState *cs, int irq, uint8_t prio)
* is the same as this one ( a property which the calling code
* relies on ) .
*/
if ( prio < cs - > hppi . prio ) {
return true ;
if ( prio ! = cs - > hppi . prio ) {
return prio < cs - > hppi . prio ;
}
/*
* The same priority IRQ with non - maskable property should signal to
* the CPU as it have the priority higher than the labelled 0x80 or 0x00 .
*/
if ( nmi ! = cs - > hppi . nmi ) {
return nmi ;
}
/* If multiple pending interrupts have the same priority then it is an
* IMPDEF choice which of them to signal to the CPU . We choose to
* signal the one with the lowest interrupt number .
*/
if ( prio = = cs - > hppi . prio & & irq < = cs - > hppi . irq ) {
if ( irq < = cs - > hppi . irq ) {
return true ;
}
return false ;
@ -129,6 +138,40 @@ static uint32_t gicr_int_pending(GICv3CPUState *cs)
return pend ;
}
static bool gicv3_get_priority ( GICv3CPUState * cs , bool is_redist , int irq ,
uint8_t * prio )
{
uint32_t nmi = 0x0 ;
if ( is_redist ) {
nmi = extract32 ( cs - > gicr_inmir0 , irq , 1 ) ;
} else {
nmi = * gic_bmp_ptr32 ( cs - > gic - > nmi , irq ) ;
nmi = nmi & ( 1 < < ( irq & 0x1f ) ) ;
}
if ( nmi ) {
/* DS = 0 & Non-secure NMI */
if ( ! ( cs - > gic - > gicd_ctlr & GICD_CTLR_DS ) & &
( ( is_redist & & extract32 ( cs - > gicr_igroupr0 , irq , 1 ) ) | |
( ! is_redist & & gicv3_gicd_group_test ( cs - > gic , irq ) ) ) ) {
* prio = 0x80 ;
} else {
* prio = 0x0 ;
}
return true ;
}
if ( is_redist ) {
* prio = cs - > gicr_ipriorityr [ irq ] ;
} else {
* prio = cs - > gic - > gicd_ipriority [ irq ] ;
}
return false ;
}
/* Update the interrupt status after state in a redistributor
* or CPU interface has changed , but don ' t tell the CPU i / f .
*/
@ -141,6 +184,7 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
uint8_t prio ;
int i ;
uint32_t pend ;
bool nmi = false ;
/* Find out which redistributor interrupts are eligible to be
* signaled to the CPU interface .
@ -152,10 +196,11 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
if ( ! ( pend & ( 1 < < i ) ) ) {
continue ;
}
prio = cs - > gicr_ipriorityr [ i ] ;
if ( irqbetter ( cs , i , prio ) ) {
nmi = gicv3_get_priority ( cs , true , i , & prio ) ;
if ( irqbetter ( cs , i , prio , nmi ) ) {
cs - > hppi . irq = i ;
cs - > hppi . prio = prio ;
cs - > hppi . nmi = nmi ;
seenbetter = true ;
}
}
@ -168,9 +213,10 @@ static void gicv3_redist_update_noirqset(GICv3CPUState *cs)
if ( ( cs - > gicr_ctlr & GICR_CTLR_ENABLE_LPIS ) & & cs - > gic - > lpi_enable & &
( cs - > gic - > gicd_ctlr & GICD_CTLR_EN_GRP1NS ) & &
( cs - > hpplpi . prio ! = 0xff ) ) {
if ( irqbetter ( cs , cs - > hpplpi . irq , cs - > hpplpi . prio ) ) {
if ( irqbetter ( cs , cs - > hpplpi . irq , cs - > hpplpi . prio , cs - > hpplpi . nmi ) ) {
cs - > hppi . irq = cs - > hpplpi . irq ;
cs - > hppi . prio = cs - > hpplpi . prio ;
cs - > hppi . nmi = cs - > hpplpi . nmi ;
cs - > hppi . grp = cs - > hpplpi . grp ;
seenbetter = true ;
}
@ -213,6 +259,7 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len)
int i ;
uint8_t prio ;
uint32_t pend = 0 ;
bool nmi = false ;
assert ( start > = GIC_INTERNAL ) ;
assert ( len > 0 ) ;
@ -240,10 +287,11 @@ static void gicv3_update_noirqset(GICv3State *s, int start, int len)
*/
continue ;
}
prio = s - > gicd_ipriority [ i ] ;
if ( irqbetter ( cs , i , prio ) ) {
nmi = gicv3_get_priority ( cs , false , i , & prio ) ;
if ( irqbetter ( cs , i , prio , nmi ) ) {
cs - > hppi . irq = i ;
cs - > hppi . prio = prio ;
cs - > hppi . nmi = nmi ;
cs - > seenbetter = true ;
}
}
@ -293,6 +341,7 @@ void gicv3_full_update_noirqset(GICv3State *s)
for ( i = 0 ; i < s - > num_cpu ; i + + ) {
s - > cpu [ i ] . hppi . prio = 0xff ;
s - > cpu [ i ] . hppi . nmi = false ;
}
/* Note that we can guarantee that these functions will not