mirror of
https://github.com/AuxXxilium/linux_dsm_epyc7002.git
synced 2024-12-24 08:25:39 +07:00
3384b043ea
This patch fixes the IPI(inner processor interrupt) missing issue. It failed because it used hartid_mask to iterate for_each_cpu(), however the cpu_mask and hartid_mask may not be always the same. It will never send the IPI to hartid 4 because it will be skipped in for_each_cpu loop in my case. We can reproduce this case in Qemu sifive_u machine by this command. qemu-system-riscv64 -nographic -smp 5 -m 1G -M sifive_u -kernel \ arch/riscv/boot/loader It will hang in csd_lock_wait(csd) because the csd_unlock(csd) is not called. It is not called because hartid 4 doesn't receive the IPI to release this lock. The caller hart doesn't send the IPI to hartid 4 is because of hartid 4 is skipped in for_each_cpu(). It will be skipped is because "(cpu) < nr_cpu_ids" is not true. The hartid is 4 and nr_cpu_ids is 4. Therefore it should use cpumask in for_each_cpu() instead of hartid_mask. /* Send a message to all CPUs in the map */ arch_send_call_function_ipi_mask(cfd->cpumask_ipi); if (wait) { for_each_cpu(cpu, cfd->cpumask) { call_single_data_t *csd; csd = per_cpu_ptr(cfd->csd, cpu); csd_lock_wait(csd); } } for ((cpu) = -1; \ (cpu) = cpumask_next((cpu), (mask)), \ (cpu) < nr_cpu_ids;) It could boot to login console after this patch applied. Fixes: b2d36b5668f6 ("riscv: provide native clint access for M-mode") Signed-off-by: Greentime Hu <greentime.hu@sifive.com> Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com> Signed-off-by: Palmer Dabbelt <palmerdabbelt@google.com>
40 lines
983 B
C
40 lines
983 B
C
/* SPDX-License-Identifier: GPL-2.0 */
|
|
#ifndef _ASM_RISCV_CLINT_H
|
|
#define _ASM_RISCV_CLINT_H 1
|
|
|
|
#include <linux/io.h>
|
|
#include <linux/smp.h>
|
|
|
|
#ifdef CONFIG_RISCV_M_MODE
|
|
extern u32 __iomem *clint_ipi_base;
|
|
|
|
void clint_init_boot_cpu(void);
|
|
|
|
static inline void clint_send_ipi_single(unsigned long hartid)
|
|
{
|
|
writel(1, clint_ipi_base + hartid);
|
|
}
|
|
|
|
static inline void clint_send_ipi_mask(const struct cpumask *mask)
|
|
{
|
|
int cpu;
|
|
|
|
for_each_cpu(cpu, mask)
|
|
clint_send_ipi_single(cpuid_to_hartid_map(cpu));
|
|
}
|
|
|
|
static inline void clint_clear_ipi(unsigned long hartid)
|
|
{
|
|
writel(0, clint_ipi_base + hartid);
|
|
}
|
|
#else /* CONFIG_RISCV_M_MODE */
|
|
#define clint_init_boot_cpu() do { } while (0)
|
|
|
|
/* stubs to for code is only reachable under IS_ENABLED(CONFIG_RISCV_M_MODE): */
|
|
void clint_send_ipi_single(unsigned long hartid);
|
|
void clint_send_ipi_mask(const struct cpumask *hartid_mask);
|
|
void clint_clear_ipi(unsigned long hartid);
|
|
#endif /* CONFIG_RISCV_M_MODE */
|
|
|
|
#endif /* _ASM_RISCV_CLINT_H */
|