diff --git a/arch/loongarch/kernel/paravirt.c b/arch/loongarch/kernel/paravirt.c index 9cc27c3feb69a0c51b81099a5a89d255ecbb82f3..56690e025258c180459fea355962d2f9b5e1041c 100644 --- a/arch/loongarch/kernel/paravirt.c +++ b/arch/loongarch/kernel/paravirt.c @@ -50,11 +50,18 @@ static u64 paravt_steal_clock(int cpu) } #ifdef CONFIG_SMP +static struct smp_ops native_ops; + static void pv_send_ipi_single(int cpu, unsigned int action) { int min, old; irq_cpustat_t *info = &per_cpu(irq_stat, cpu); + if (unlikely(action == ACTION_BOOT_CPU)) { + native_ops.send_ipi_single(cpu, action); + return; + } + old = atomic_fetch_or(BIT(action), &info->message); if (old) return; @@ -74,6 +81,11 @@ static void pv_send_ipi_mask(const struct cpumask *mask, unsigned int action) if (cpumask_empty(mask)) return; + if (unlikely(action == ACTION_BOOT_CPU)) { + native_ops.send_ipi_mask(mask, action); + return; + } + action = BIT(action); for_each_cpu(i, mask) { info = &per_cpu(irq_stat, i); @@ -106,7 +118,7 @@ static void pv_send_ipi_mask(const struct cpumask *mask, unsigned int action) if (bitmap) kvm_hypercall3(KVM_HCALL_FUNC_IPI, (unsigned long)bitmap, - (unsigned long)(bitmap >> BITS_PER_LONG), min); + (unsigned long)(bitmap >> BITS_PER_LONG), min); } static irqreturn_t pv_ipi_interrupt(int irq, void *dev) @@ -129,6 +141,11 @@ static irqreturn_t pv_ipi_interrupt(int irq, void *dev) info->ipi_irqs[IPI_CALL_FUNCTION]++; } + if (action & SMP_CLEAR_VECTOR) { + complete_irq_moving(); + info->ipi_irqs[IPI_CLEAR_VECTOR]++; + } + return IRQ_HANDLED; } @@ -136,6 +153,8 @@ static void pv_init_ipi(void) { int r, swi; + /* Init native ipi irq for ACTION_BOOT_CPU */ + native_ops.init_ipi(); swi = get_percpu_irq(INT_SWI0); if (swi < 0) panic("SWI0 IRQ mapping failed\n"); @@ -182,6 +201,7 @@ int __init pv_ipi_init(void) return 0; #ifdef CONFIG_SMP + native_ops = smp_ops; smp_ops.init_ipi = pv_init_ipi; smp_ops.send_ipi_single = pv_send_ipi_single; smp_ops.send_ipi_mask = pv_send_ipi_mask;