[PATCH v2] riscv: smp: set CPU 0 possible in setup_smp()

Paul Sherman shermanpauldylan at gmail.com
Tue Jul 14 21:51:31 PDT 2026


Vivian, Paul,

Thank you for the precise analysis. You are correct for mainline,
boot_cpu_init() calls set_cpu_possible(0, true) before setup_smp().

The hang was observed on a development tree based on Linux 7.0-rc2
with substantial percpu/SLUB allocator changes layered on top for
large NUMA geometry (4 nodes, 128GB). In that context I instrumented
rcu_init_one() and rcutree_prepare_cpu() via SBI ecall probes
(no JTAG/denugger available on this hardware) and observed:

  Za ffffffff81035000    <- per_cpu_ptr(&rcu_data, 0) in rcu_init_one
  Zn 0000000000000000    <- mynode was NULL at write time

  rdp ffffffff81035000   <- same address at rcutree_prepare_cpu
  mynode = NULL          <- confirmed NULL dereference

The for_each_possible_cpu loop in rcu_init_one was skipping CPU 0
because cpu_possible_mask had not yet been populated at that point
in my tree's initialization order. The additional allocator changes
may have altered the timing.

I am rebasing onto 7.2-rc3. If the condition cannot be reproduced
there, please feel free to drop the patch.

The probe methodology above uses M-mode SBI ecalls as a poor man's
logic analyzer; happy to share the infrastructure if useful.

Paul Sherman

On Tue, Jul 14, 2026 at 9:01 PM Vivian Wang <wangruikang at iscas.ac.cn> wrote:
>
> On 7/15/26 09:41, Paul Walmsley wrote:
>
> > On Tue, 14 Jul 2026, Paul Sherman wrote:
> >
> >> setup_smp() calls set_cpu_possible() for CPUs 1..nr_cpu_ids-1 but
> >> never for CPU 0 (the boot CPU). x86 handles this via
> >> init_cpu_possible(cpumask_of(0)); RISC-V has no equivalent.
> >>
> >> Without CPU 0 in cpu_possible_mask, rcu_init_one()'s
> >> for_each_possible_cpu() loop skips it, leaving rdp->mynode=NULL.
> >> rcutree_prepare_cpu() then dereferences NULL and hangs.
> >>
> >> Exposed on Sophgo SG2042 (64-hart, 4-NUMA) with Linux 7.2-rc3.
> >>
> >> Fixes: a4166aec1130 ("riscv: Deduplicate code in setup_smp()")
> >> Signed-off-by: Paul Sherman <shermanpauldylan at gmail.com>
> > Thanks, queued for v7.2-rc.
>
> I hope it's not too late to object, but I don't see how this could
> happen. This is what happens in start_kernel():
>
>     assembly boot code
>     -> start_kernel()
>        -> boot_cpu_init();
>           -> int cpu = smp_processor_id();
>              /* cpu = 0 because INIT_THREAD_INFO(tsk) leaves it out */
>
>              /* Mark the boot cpu "present", "online" etc for SMP and UP case */
>              set_cpu_online(cpu, true);
>              set_cpu_active(cpu, true);
>              set_cpu_present(cpu, true);
>              set_cpu_possible(cpu, true); /* <---- HERE */
>        -> ...
>        -> setup_arch(&command_line);
>           -> setup_smp()
>              -> for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++)
>                         if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID)
>                                 set_cpu_possible(cpuid, true);
>
> So CPU 0 is already in cpu_possible_mask. This is also what I see by
> adding prints to setup_smp().
>
> * Paul Sherman: How did you reproduce this? Is your boot CPU not cpu 0
> (note: not the same as hart 0)?
>
> Vivian "dramforever" Wang
>



More information about the linux-riscv mailing list