From dea4eeae17220bae726bdbadc401fa0366721906 Mon Sep 17 00:00:00 2001 From: "eunwoo.nam" Date: Tue, 24 Feb 2026 15:56:49 +0900 Subject: [PATCH] arch: Fix CPU on/off race condition and prevent device hang When up_cpu_die is called via SGI3 but up_cpu_on fails, the system currently returns an error. This causes the scheduler to perceive the CPU as alive when it is actually dead. If up_cpu_off is called again in this state, the CPU receiving SGI3 is in die state, resulting in a deadlock. Therefore, when up_cpu_down fails, up_cpu_on must be called again to reactivate the CPU. Additionally, calling up_cpu_on twice leads to psci_cpu_on being invoked twice, which can cause device hang. To prevent this, psci_affinity_info is now used to check CPU state before calling psci_cpu_on. Signed-off-by: eunwoo.nam --- os/arch/arm/src/amebasmart/amebasmart_smp.c | 33 +++++++++++---------- os/arch/arm/src/armv7-a/arm_cpuoff.c | 4 +++ 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/os/arch/arm/src/amebasmart/amebasmart_smp.c b/os/arch/arm/src/amebasmart/amebasmart_smp.c index 974494da14..2c1f78c05b 100644 --- a/os/arch/arm/src/amebasmart/amebasmart_smp.c +++ b/os/arch/arm/src/amebasmart/amebasmart_smp.c @@ -147,22 +147,25 @@ int vPortSecondaryBoot(int cpu) int state; int count = 10; - err = psci_cpu_on(cpu, (unsigned long)__cpu1_start); - DEBUGASSERT(err >= 0); - - /* await for PSCI to report cpu state */ - do { - state = psci_affinity_info(cpu, 0); - if (state == AFF_STATE_ON) { - break; + /* If psci_cpu_on is called more than once, the CPU may not function properly. */ + if (psci_affinity_info(cpu, 0) == AFF_STATE_OFF) { + err = psci_cpu_on(cpu, (unsigned long)__cpu1_start); + DEBUGASSERT(err >= 0); + + /* await for PSCI to report cpu state */ + do { + state = psci_affinity_info(cpu, 0); + if (state == AFF_STATE_ON) { + break; + } + + DelayUs(50); + } while (count--); + + if (count <= 0) { + smplldbg("Secondary core boot timeout affinfo: %d\n", state); + return -ETIMEDOUT; } - - DelayUs(50); - } while (count--); - - if (count <= 0) { - smplldbg("Secondary core boot timeout affinfo: %d\n", state); - return -ETIMEDOUT; } return OK; diff --git a/os/arch/arm/src/armv7-a/arm_cpuoff.c b/os/arch/arm/src/armv7-a/arm_cpuoff.c index 4920620af7..9762715ba5 100644 --- a/os/arch/arm/src/armv7-a/arm_cpuoff.c +++ b/os/arch/arm/src/armv7-a/arm_cpuoff.c @@ -292,6 +292,10 @@ int up_cpu_off(int cpu) ret = up_cpu_down(cpu); if (ret < 0) { smplldbg("Failed to powerdown secondary core CPU%d\n", cpu); + /* The core has already been powered down. Returning an error here + * could cause a deadlock due to inconsistent CPU state. + * Therefore, turn the CPU back on. */ + (void)up_cpu_on(cpu); return ret; }