[PATCH v2 29/39] xen/riscv: introduce aplic_reconfigure_target()
Oleksii Kurochko <[email protected]>
| Newsgroups | gmane.comp.emulators.xen.devel |
|---|---|
| Message-ID | <d90832888c1bcb08146a6c36591ac0c31b8b0ce1.1787838835.git.oleksii.kurochko@gmail.com> |
When a vCPU is migrated to a different pCPU, its IMSIC guest interrupt file changes. Any APLIC interrupt previously configured to deliver an MSI to the old interrupt file must be retargeted to the new one. Implement aplic_reconfigure_target() to scan all interrupts allocated to the domain and update their APLIC TARGET registers accordingly. Signed-off-by: Oleksii Kurochko <[email protected]> --- Changes in v2: - New patch. --- --- xen/arch/riscv/aplic.c | 42 ++++++++++++++++++++++++++++++ xen/arch/riscv/include/asm/aplic.h | 4 +++ 2 files changed, 46 insertions(+) diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c index b4c419755ac3..0af13f28e467 100644 --- a/xen/arch/riscv/aplic.c +++ b/xen/arch/riscv/aplic.c @@ -138,6 +138,48 @@ uint32_t aplic_msi_target_gen(const struct vcpu *target_vcpu, return base_val; } +void aplic_reconfigure_target(const struct vcpu *v, + unsigned int old_guest_file_id, + unsigned int old_cpu) +{ + const struct vintc *vintc = v->domain->arch.vintc; + const unsigned long *auth_irq_bmp = vintc->used_irqs; + unsigned long old_hart_field = aplic_hart_field(old_cpu); + unsigned long flags; + unsigned int irqn; + + /* Support only MSI mode at the moment */ + BUG_ON(!aplic_msi_mode()); + + spin_lock_irqsave(&aplic.lock, flags); + + bitmap_for_each ( irqn, auth_irq_bmp, vintc->nr_virqs ) + { + volatile uint32_t __iomem *ptarget; + uint32_t target_val; + unsigned int guest_index, hart_index; + + if ( !irqn ) + continue; + + ptarget = &aplic.regs->target[irqn - 1]; + target_val = readl(ptarget); + + guest_index = MASK_EXTR(target_val, APLIC_TARGET_GUEST_IDX); + hart_index = MASK_EXTR(target_val, APLIC_TARGET_HART_IDX); + + if ( (guest_index != old_guest_file_id) || + (hart_index != old_hart_field) ) + continue; + + target_val = aplic_msi_target_gen(v, target_val); + + writel(target_val, ptarget); + } + + spin_unlock_irqrestore(&aplic.lock, flags); +} + uint32_t aplic_hw_read_reg(unsigned int offset) { unsigned long flags; diff --git a/xen/arch/riscv/include/asm/aplic.h b/xen/arch/riscv/include/asm/aplic.h index d629e1c83887..8564f5954b6b 100644 --- a/xen/arch/riscv/include/asm/aplic.h +++ b/xen/arch/riscv/include/asm/aplic.h @@ -174,4 +174,8 @@ struct aplic_regs { uint32_t aplic_hw_read_reg(unsigned int offset); void aplic_hw_write_reg(unsigned int offset, uint32_t value); +void aplic_reconfigure_target(const struct vcpu *v, + unsigned int old_guest_file_id, + unsigned int old_cpu); + #endif /* ASM_RISCV_APLIC_H */ -- 2.55.0