hw/intc/arm_gicv3_redist: Implement gicv3_redist_process_vlpi()
Implement the function gicv3_redist_process_vlpi(), which was left as just a stub earlier. This function deals with being handed a VLPI by the ITS. It must set the bit in the pending table. If the vCPU is currently resident we must recalculate the highest priority pending vLPI; otherwise we may need to ring a "doorbell" interrupt to let the hypervisor know it might want to reschedule the vCPU. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20220408141550.1271295-32-peter.maydell@linaro.org
This commit is contained in:
parent
b76eb5f4db
commit
d7d39749e6
@ -60,6 +60,19 @@ static uint32_t gicr_read_bitmap_reg(GICv3CPUState *cs, MemTxAttrs attrs,
|
||||
return reg;
|
||||
}
|
||||
|
||||
static bool vcpu_resident(GICv3CPUState *cs, uint64_t vptaddr)
|
||||
{
|
||||
/*
|
||||
* Return true if a vCPU is resident, which is defined by
|
||||
* whether the GICR_VPENDBASER register is marked VALID and
|
||||
* has the right virtual pending table address.
|
||||
*/
|
||||
if (!FIELD_EX64(cs->gicr_vpendbaser, GICR_VPENDBASER, VALID)) {
|
||||
return false;
|
||||
}
|
||||
return vptaddr == (cs->gicr_vpendbaser & R_GICR_VPENDBASER_PHYADDR_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* update_for_one_lpi: Update pending information if this LPI is better
|
||||
*
|
||||
@ -1004,10 +1017,37 @@ void gicv3_redist_vlpi_pending(GICv3CPUState *cs, int irq, int level)
|
||||
void gicv3_redist_process_vlpi(GICv3CPUState *cs, int irq, uint64_t vptaddr,
|
||||
int doorbell, int level)
|
||||
{
|
||||
/*
|
||||
* The redistributor handling for being handed a VLPI by the ITS
|
||||
* will be added in a subsequent commit.
|
||||
*/
|
||||
bool bit_changed;
|
||||
bool resident = vcpu_resident(cs, vptaddr);
|
||||
uint64_t ctbase;
|
||||
|
||||
if (resident) {
|
||||
uint32_t idbits = FIELD_EX64(cs->gicr_vpropbaser, GICR_VPROPBASER, IDBITS);
|
||||
if (irq >= (1ULL << (idbits + 1))) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
bit_changed = set_pending_table_bit(cs, vptaddr, irq, level);
|
||||
if (resident && bit_changed) {
|
||||
if (level) {
|
||||
/* Check whether this vLPI is now the best */
|
||||
ctbase = cs->gicr_vpropbaser & R_GICR_VPROPBASER_PHYADDR_MASK;
|
||||
update_for_one_lpi(cs, irq, ctbase, true, &cs->hppvlpi);
|
||||
gicv3_cpuif_virt_irq_fiq_update(cs);
|
||||
} else {
|
||||
/* Only need to recalculate if this was previously the best vLPI */
|
||||
if (irq == cs->hppvlpi.irq) {
|
||||
gicv3_redist_update_vlpi(cs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!resident && level && doorbell != INTID_SPURIOUS &&
|
||||
(cs->gicr_ctlr & GICR_CTLR_ENABLE_LPIS)) {
|
||||
/* vCPU is not currently resident: ring the doorbell */
|
||||
gicv3_redist_process_lpi(cs, doorbell, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void gicv3_redist_mov_vlpi(GICv3CPUState *src, uint64_t src_vptaddr,
|
||||
|
Loading…
Reference in New Issue
Block a user