Files
linux/arch/riscv/kernel/cpu-hotplug.c
Danil Skrebenkov 3537f1a373 RISC-V: clear hot-unplugged cores from all task mm_cpumasks to avoid rfence errors
[ Upstream commit ae9e9f3d67 ]

openSBI v1.7 adds harts checks for ipi operations. Especially it
adds comparison between hmask passed as an argument from linux
and mask of online harts (from openSBI side). If they don't
fit each other the error occurs.

When cpu is offline, cpu_online_mask is explicitly cleared in
__cpu_disable. However, there is no explicit clearing of
mm_cpumask. mm_cpumask is used for rfence operations that
call openSBI RFENCE extension which uses ipi to remote harts.
If hart is offline there may be error if mask of linux is not
as mask of online harts in openSBI.

this patch adds explicit clearing of mm_cpumask for offline hart.

Signed-off-by: Danil Skrebenkov <danil.skrebenkov@cloudbear.ru>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Link: https://lore.kernel.org/r/20250919132849.31676-1-danil.skrebenkov@cloudbear.ru
[pjw@kernel.org: rewrote subject line for clarity]
Signed-off-by: Paul Walmsley <pjw@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2025-11-24 10:35:46 +01:00

79 lines
1.5 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (C) 2020 Western Digital Corporation or its affiliates.
*/
#include <linux/kernel.h>
#include <linux/mm.h>
#include <linux/sched.h>
#include <linux/err.h>
#include <linux/irq.h>
#include <linux/cpuhotplug.h>
#include <linux/cpu.h>
#include <linux/sched/hotplug.h>
#include <asm/irq.h>
#include <asm/cpu_ops.h>
#include <asm/numa.h>
#include <asm/smp.h>
bool cpu_has_hotplug(unsigned int cpu)
{
if (cpu_ops->cpu_stop)
return true;
return false;
}
/*
* __cpu_disable runs on the processor to be shutdown.
*/
int __cpu_disable(void)
{
unsigned int cpu = smp_processor_id();
if (!cpu_ops->cpu_stop)
return -EOPNOTSUPP;
remove_cpu_topology(cpu);
numa_remove_cpu(cpu);
set_cpu_online(cpu, false);
riscv_ipi_disable();
irq_migrate_all_off_this_cpu();
return 0;
}
#ifdef CONFIG_HOTPLUG_CPU
/*
* Called on the thread which is asking for a CPU to be shutdown, if the
* CPU reported dead to the hotplug core.
*/
void arch_cpuhp_cleanup_dead_cpu(unsigned int cpu)
{
int ret = 0;
pr_notice("CPU%u: off\n", cpu);
clear_tasks_mm_cpumask(cpu);
/* Verify from the firmware if the cpu is really stopped*/
if (cpu_ops->cpu_is_stopped)
ret = cpu_ops->cpu_is_stopped(cpu);
if (ret)
pr_warn("CPU%u may not have stopped: %d\n", cpu, ret);
}
/*
* Called from the idle thread for the CPU which has been shutdown.
*/
void __noreturn arch_cpu_idle_dead(void)
{
idle_task_exit();
cpuhp_ap_report_dead();
cpu_ops->cpu_stop();
/* It should never reach here */
BUG();
}
#endif