diff --git a/xen/arch/riscv/domain.c b/xen/arch/riscv/domain.c index 694a03ab74..9c86581ea2 100644 --- a/xen/arch/riscv/domain.c +++ b/xen/arch/riscv/domain.c @@ -231,6 +231,33 @@ void vcpu_sync_interrupts(struct vcpu *curr) } } +void vcpu_flush_interrupts(struct vcpu *curr) +{ + ASSERT(curr == current); + + if ( ACCESS_ONCE(curr->arch.irqs_pending_mask[0]) ) + { + unsigned long mask = xchg(&curr->arch.irqs_pending_mask[0], 0UL); + unsigned long val = ACCESS_ONCE(curr->arch.irqs_pending[0]) & mask; + register_t *hvip = &curr->arch.hvip; + + *hvip &= ~mask; + *hvip |= val; + + csr_write(CSR_HVIP, *hvip); + } + +#ifdef CONFIG_RISCV_32 + /* + * Flush AIA high interrupts. + * + * It is necessary to do only for CONFIG_RISCV_32 which isn't + * supported now. + */ +# error "Update v->arch.hviph" +#endif +} + static void __init __maybe_unused build_assertions(void) { /* diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h index 1ecfe18c85..59d23e4f92 100644 --- a/xen/arch/riscv/include/asm/domain.h +++ b/xen/arch/riscv/include/asm/domain.h @@ -115,6 +115,7 @@ int vcpu_set_interrupt(struct vcpu *v, unsigned int irq); int vcpu_unset_interrupt(struct vcpu *v, unsigned int irq); void vcpu_sync_interrupts(struct vcpu *curr); +void vcpu_flush_interrupts(struct vcpu *curr); #endif /* ASM__RISCV__DOMAIN_H */ diff --git a/xen/arch/riscv/traps.c b/xen/arch/riscv/traps.c index 551f886e3a..244264c92a 100644 --- a/xen/arch/riscv/traps.c +++ b/xen/arch/riscv/traps.c @@ -175,6 +175,8 @@ static void check_for_pcpu_work(void) vcpu_sync_interrupts(curr); + vcpu_flush_interrupts(curr); + p2m_handle_vmenter(); }