Skip to content

Commit 6ce031e

Browse files
bibo-maochenhuacai
authored andcommitted
LoongArch: Fix AP booting issue in VM mode
Native IPI is used for AP booting, because it is the booting interface between OS and BIOS firmware. The paravirt IPI is only used inside OS, and native IPI is necessary to boot AP. When booting AP, we write the kernel entry address in the HW mailbox of AP and send IPI interrupt to it. AP executes idle instruction and waits for interrupts or SW events, then clears IPI interrupt and jumps to the kernel entry from HW mailbox. Between writing HW mailbox and sending IPI, AP can be woken up by SW events and jumps to the kernel entry, so ACTION_BOOT_CPU IPI interrupt will keep pending during AP booting. And native IPI interrupt handler needs be registered so that it can clear pending native IPI, else there will be endless interrupts during AP booting stage. Here native IPI interrupt is initialized even if paravirt IPI is used. Cc: [email protected] Fixes: 74c16b2 ("LoongArch: KVM: Add PV IPI support on guest side") Signed-off-by: Bibo Mao <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent 139d42c commit 6ce031e

File tree

1 file changed

+15
-0
lines changed

1 file changed

+15
-0
lines changed

arch/loongarch/kernel/paravirt.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,11 +51,18 @@ static u64 paravt_steal_clock(int cpu)
5151
}
5252

5353
#ifdef CONFIG_SMP
54+
static struct smp_ops native_ops;
55+
5456
static void pv_send_ipi_single(int cpu, unsigned int action)
5557
{
5658
int min, old;
5759
irq_cpustat_t *info = &per_cpu(irq_stat, cpu);
5860

61+
if (unlikely(action == ACTION_BOOT_CPU)) {
62+
native_ops.send_ipi_single(cpu, action);
63+
return;
64+
}
65+
5966
old = atomic_fetch_or(BIT(action), &info->message);
6067
if (old)
6168
return;
@@ -75,6 +82,11 @@ static void pv_send_ipi_mask(const struct cpumask *mask, unsigned int action)
7582
if (cpumask_empty(mask))
7683
return;
7784

85+
if (unlikely(action == ACTION_BOOT_CPU)) {
86+
native_ops.send_ipi_mask(mask, action);
87+
return;
88+
}
89+
7890
action = BIT(action);
7991
for_each_cpu(i, mask) {
8092
info = &per_cpu(irq_stat, i);
@@ -147,6 +159,8 @@ static void pv_init_ipi(void)
147159
{
148160
int r, swi;
149161

162+
/* Init native ipi irq for ACTION_BOOT_CPU */
163+
native_ops.init_ipi();
150164
swi = get_percpu_irq(INT_SWI0);
151165
if (swi < 0)
152166
panic("SWI0 IRQ mapping failed\n");
@@ -193,6 +207,7 @@ int __init pv_ipi_init(void)
193207
return 0;
194208

195209
#ifdef CONFIG_SMP
210+
native_ops = mp_ops;
196211
mp_ops.init_ipi = pv_init_ipi;
197212
mp_ops.send_ipi_single = pv_send_ipi_single;
198213
mp_ops.send_ipi_mask = pv_send_ipi_mask;

0 commit comments

Comments
 (0)