All of lore.kernel.org
 help / color / mirror / Atom feed
From: Atish Patra <atishp@atishpatra.org>
To: Anup Patel <anup@brainfault.org>
Cc: Atish Patra <atish.patra@wdc.com>,
	Albert Ou <aou@eecs.berkeley.edu>,
	Jason Cooper <jason@lakedaemon.net>,
	Marc Zyngier <maz@kernel.org>,
	Daniel Lezcano <daniel.lezcano@linaro.org>,
	Heiko Carstens <heiko.carstens@de.ibm.com>,
	"linux-kernel@vger.kernel.org List"
	<linux-kernel@vger.kernel.org>,
	Mike Rapoport <rppt@linux.ibm.com>,
	Vincent Chen <vincent.chen@sifive.com>,
	Mao Han <han_mao@c-sky.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Paul Walmsley <paul.walmsley@sifive.com>,
	Michael Ellerman <mpe@ellerman.id.au>,
	Marek Szyprowski <m.szyprowski@samsung.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	linux-riscv <linux-riscv@lists.infradead.org>,
	Borislav Petkov <bp@suse.de>,
	Thomas Gleixner <tglx@linutronix.de>,
	Allison Randal <allison@lohutok.net>,
	Kees Cook <keescook@chromium.org>
Subject: Re: [PATCH v8 07/11] RISC-V: Add cpu_ops and modify default booting method
Date: Wed, 12 Feb 2020 10:57:37 -0800	[thread overview]
Message-ID: <CAOnJCUJtsQF64QxV=e+=g0aRur0wEXbiMDU96g1QH7pAThoeqA@mail.gmail.com> (raw)
In-Reply-To: <CAAhSdy3RVpbum-O_ercZJkiEjDYPT-zrEHvYvMUQqE8+P82ihA@mail.gmail.com>

On Tue, Feb 11, 2020 at 8:28 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Wed, Feb 12, 2020 at 7:21 AM Atish Patra <atish.patra@wdc.com> wrote:
> >
> > Currently, all non-booting harts start booting after the booting hart
> > updates the per-hart stack pointer. This is done in a way that, it's
> > difficult to implement any other booting method without breaking the
> > backward compatibility.
> >
> > Define a cpu_ops method that allows to introduce other booting methods
> > in future. Modify the current booting method to be compatible with
> > cpu_ops.
> >
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > ---
> >  arch/riscv/include/asm/cpu_ops.h     | 34 ++++++++++++++++++
> >  arch/riscv/kernel/Makefile           |  2 ++
> >  arch/riscv/kernel/cpu_ops.c          | 40 +++++++++++++++++++++
> >  arch/riscv/kernel/cpu_ops_spinwait.c | 42 ++++++++++++++++++++++
> >  arch/riscv/kernel/smpboot.c          | 54 +++++++++++++++++-----------
> >  5 files changed, 151 insertions(+), 21 deletions(-)
> >  create mode 100644 arch/riscv/include/asm/cpu_ops.h
> >  create mode 100644 arch/riscv/kernel/cpu_ops.c
> >  create mode 100644 arch/riscv/kernel/cpu_ops_spinwait.c
> >
> > diff --git a/arch/riscv/include/asm/cpu_ops.h b/arch/riscv/include/asm/cpu_ops.h
> > new file mode 100644
> > index 000000000000..7db276284009
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/cpu_ops.h
> > @@ -0,0 +1,34 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (c) 2019 Western Digital Corporation or its affiliates.
> > + * Based on arch/arm64/include/asm/cpu_ops.h
> > + */
> > +#ifndef __ASM_CPU_OPS_H
> > +#define __ASM_CPU_OPS_H
> > +
> > +#include <linux/init.h>
> > +#include <linux/sched.h>
> > +#include <linux/threads.h>
> > +
> > +/**
> > + * struct cpu_operations - Callback operations for hotplugging CPUs.
> > + *
> > + * @name:              Name of the boot protocol.
> > + * @cpu_prepare:       Early one-time preparation step for a cpu. If there
> > + *                     is a mechanism for doing so, tests whether it is
> > + *                     possible to boot the given HART.
> > + * @cpu_start:         Boots a cpu into the kernel.
> > + */
> > +struct cpu_operations {
> > +       const char      *name;
> > +       int             (*cpu_prepare)(unsigned int cpu);
> > +       int             (*cpu_start)(unsigned int cpu,
> > +                                    struct task_struct *tidle);
> > +};
> > +
> > +extern const struct cpu_operations *cpu_ops[NR_CPUS];
> > +int __init cpu_set_ops(int cpu);
>
> This function is more like probing for appropriate cpu_ops. Also,
> I think we don't need to return anything from cpu_set_ops().
>

Correct. I will change it to void but I think set_ops is a better name
as we are actually
setting the right type of ops to cpu_ops.

> Maybe rename it to "void cpu_probe_ops(int cpu)" ?
>
> > +void cpu_update_secondary_bootdata(unsigned int cpuid,
> > +                                  struct task_struct *tidle);
> > +
> > +#endif /* ifndef __ASM_CPU_OPS_H */
> > diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> > index f40205cb9a22..f81a6ff88005 100644
> > --- a/arch/riscv/kernel/Makefile
> > +++ b/arch/riscv/kernel/Makefile
> > @@ -32,6 +32,8 @@ obj-$(CONFIG_RISCV_M_MODE)    += clint.o
> >  obj-$(CONFIG_FPU)              += fpu.o
> >  obj-$(CONFIG_SMP)              += smpboot.o
> >  obj-$(CONFIG_SMP)              += smp.o
> > +obj-$(CONFIG_SMP)              += cpu_ops.o
> > +obj-$(CONFIG_SMP)              += cpu_ops_spinwait.o
> >  obj-$(CONFIG_MODULES)          += module.o
> >  obj-$(CONFIG_MODULE_SECTIONS)  += module-sections.o
> >
> > diff --git a/arch/riscv/kernel/cpu_ops.c b/arch/riscv/kernel/cpu_ops.c
> > new file mode 100644
> > index 000000000000..1085def3735a
> > --- /dev/null
> > +++ b/arch/riscv/kernel/cpu_ops.c
> > @@ -0,0 +1,40 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> > + */
> > +
> > +#include <linux/errno.h>
> > +#include <linux/mm.h>
> > +#include <linux/of.h>
> > +#include <linux/string.h>
> > +#include <linux/sched.h>
> > +#include <linux/sched/task_stack.h>
> > +#include <asm/cpu_ops.h>
> > +#include <asm/sbi.h>
> > +#include <asm/smp.h>
> > +
> > +const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
> > +
> > +void *__cpu_up_stack_pointer[NR_CPUS];
> > +void *__cpu_up_task_pointer[NR_CPUS];
> > +
> > +extern const struct cpu_operations cpu_ops_spinwait;
> > +
> > +void cpu_update_secondary_bootdata(unsigned int cpuid,
> > +                                  struct task_struct *tidle)
> > +{
> > +       int hartid = cpuid_to_hartid_map(cpuid);
> > +
> > +       /* Make sure tidle is updated */
> > +       smp_mb();
> > +       WRITE_ONCE(__cpu_up_stack_pointer[hartid],
> > +                 task_stack_page(tidle) + THREAD_SIZE);
> > +       WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
> > +}
> > +
> > +int __init cpu_set_ops(int cpuid)
>
> Maybe rename it to "void cpu_probe_ops(int cpu)" ?
>
> > +{
> > +       cpu_ops[cpuid] = &cpu_ops_spinwait;
> > +
> > +       return 0;
> > +}
> > diff --git a/arch/riscv/kernel/cpu_ops_spinwait.c b/arch/riscv/kernel/cpu_ops_spinwait.c
> > new file mode 100644
> > index 000000000000..f828e660294e
> > --- /dev/null
> > +++ b/arch/riscv/kernel/cpu_ops_spinwait.c
> > @@ -0,0 +1,42 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> > + */
> > +
> > +#include <linux/errno.h>
> > +#include <linux/of.h>
> > +#include <linux/string.h>
> > +#include <asm/cpu_ops.h>
> > +#include <asm/sbi.h>
> > +#include <asm/smp.h>
> > +
> > +const struct cpu_operations cpu_ops_spinwait;
> > +
> > +static int spinwait_cpu_prepare(unsigned int cpuid)
> > +{
> > +       if (!cpu_ops_spinwait.cpu_start) {
> > +               pr_err("cpu start method not defined for CPU [%d]\n", cpuid);
> > +               return -ENODEV;
> > +       }
> > +       return 0;
> > +}
> > +
> > +static int spinwait_cpu_start(unsigned int cpuid, struct task_struct *tidle)
> > +{
> > +       /*
> > +        * In this protocol, all cpus boot on their own accord.  _start
> > +        * selects the first cpu to boot the kernel and causes the remainder
> > +        * of the cpus to spin in a loop waiting for their stack pointer to be
> > +        * setup by that main cpu.  Writing to bootdata (i.e __cpu_up_stack_pointer) signals to
> > +        * the spinning cpus that they can continue the boot process.
> > +        */
> > +       cpu_update_secondary_bootdata(cpuid, tidle);
> > +
> > +       return 0;
> > +}
> > +
> > +const struct cpu_operations cpu_ops_spinwait = {
> > +       .name           = "spinwait",
> > +       .cpu_prepare    = spinwait_cpu_prepare,
> > +       .cpu_start      = spinwait_cpu_start,
> > +};
> > diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
> > index 8bc01f0ca73b..2ee41c779a16 100644
> > --- a/arch/riscv/kernel/smpboot.c
> > +++ b/arch/riscv/kernel/smpboot.c
> > @@ -25,6 +25,7 @@
> >  #include <linux/sched/task_stack.h>
> >  #include <linux/sched/mm.h>
> >  #include <asm/clint.h>
> > +#include <asm/cpu_ops.h>
> >  #include <asm/irq.h>
> >  #include <asm/mmu_context.h>
> >  #include <asm/tlbflush.h>
> > @@ -34,8 +35,6 @@
> >
> >  #include "head.h"
> >
> > -void *__cpu_up_stack_pointer[NR_CPUS];
> > -void *__cpu_up_task_pointer[NR_CPUS];
> >  static DECLARE_COMPLETION(cpu_running);
> >
> >  void __init smp_prepare_boot_cpu(void)
> > @@ -46,6 +45,7 @@ void __init smp_prepare_boot_cpu(void)
> >  void __init smp_prepare_cpus(unsigned int max_cpus)
> >  {
> >         int cpuid;
> > +       int ret;
> >
> >         /* This covers non-smp usecase mandated by "nosmp" option */
> >         if (max_cpus == 0)
> > @@ -54,6 +54,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
> >         for_each_possible_cpu(cpuid) {
> >                 if (cpuid == smp_processor_id())
> >                         continue;
> > +               if (cpu_ops[cpuid]->cpu_prepare) {
> > +                       ret = cpu_ops[cpuid]->cpu_prepare(cpuid);
> > +                       if (ret)
> > +                               continue;
> > +               }
> >                 set_cpu_present(cpuid, true);
> >         }
> >  }
> > @@ -65,6 +70,8 @@ void __init setup_smp(void)
> >         bool found_boot_cpu = false;
> >         int cpuid = 1;
> >
> > +       cpu_set_ops(0);
> > +
> >         for_each_of_cpu_node(dn) {
> >                 hart = riscv_of_processor_hartid(dn);
> >                 if (hart < 0)
> > @@ -92,36 +99,41 @@ void __init setup_smp(void)
> >                         cpuid, nr_cpu_ids);
> >
> >         for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) {
> > -               if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID)
> > +               if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) {
> > +                       if (cpu_set_ops(cpuid)) {
> > +                               cpuid_to_hartid_map(cpuid) = INVALID_HARTID;
> > +                               continue;
> > +                       }
> >                         set_cpu_possible(cpuid, true);
> > +               }
> >         }
> >  }
> >
> > +int start_secondary_cpu(int cpu, struct task_struct *tidle)
>
> Make this function static.
>

sure.

> > +{
> > +       if (cpu_ops[cpu]->cpu_start)
> > +               return cpu_ops[cpu]->cpu_start(cpu, tidle);
> > +
> > +       return -EOPNOTSUPP;
> > +}
> > +
> >  int __cpu_up(unsigned int cpu, struct task_struct *tidle)
> >  {
> >         int ret = 0;
> > -       int hartid = cpuid_to_hartid_map(cpu);
> >         tidle->thread_info.cpu = cpu;
> >
> > -       /*
> > -        * On RISC-V systems, all harts boot on their own accord.  Our _start
> > -        * selects the first hart to boot the kernel and causes the remainder
> > -        * of the harts to spin in a loop waiting for their stack pointer to be
> > -        * setup by that main hart.  Writing __cpu_up_stack_pointer signals to
> > -        * the spinning harts that they can continue the boot process.
> > -        */
> > -       smp_mb();
> > -       WRITE_ONCE(__cpu_up_stack_pointer[hartid],
> > -                 task_stack_page(tidle) + THREAD_SIZE);
> > -       WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
> > -
> > -       lockdep_assert_held(&cpu_running);
> > -       wait_for_completion_timeout(&cpu_running,
> > +       ret = start_secondary_cpu(cpu, tidle);
> > +       if (!ret) {
> > +               lockdep_assert_held(&cpu_running);
> > +               wait_for_completion_timeout(&cpu_running,
> >                                             msecs_to_jiffies(1000));
> >
> > -       if (!cpu_online(cpu)) {
> > -               pr_crit("CPU%u: failed to come online\n", cpu);
> > -               ret = -EIO;
> > +               if (!cpu_online(cpu)) {
> > +                       pr_crit("CPU%u: failed to come online\n", cpu);
> > +                       ret = -EIO;
> > +               }
> > +       } else {
> > +               pr_crit("CPU%u: failed to start\n", cpu);
> >         }
> >
> >         return ret;
> > --
> > 2.24.0
> >
>
> Apart from minor comments above, looks good to me.
>
> Reviewed-by: Anup Patel <anup@brainfault.org>
>
> Regards,
> Anup
>


-- 
Regards,
Atish

WARNING: multiple messages have this Message-ID (diff)
From: Atish Patra <atishp@atishpatra.org>
To: Anup Patel <anup@brainfault.org>
Cc: Albert Ou <aou@eecs.berkeley.edu>,
	Jason Cooper <jason@lakedaemon.net>,
	Kees Cook <keescook@chromium.org>,
	Vincent Chen <vincent.chen@sifive.com>,
	Michael Ellerman <mpe@ellerman.id.au>,
	Marc Zyngier <maz@kernel.org>,
	Daniel Lezcano <daniel.lezcano@linaro.org>,
	Heiko Carstens <heiko.carstens@de.ibm.com>,
	"linux-kernel@vger.kernel.org List"
	<linux-kernel@vger.kernel.org>,
	Mike Rapoport <rppt@linux.ibm.com>,
	Atish Patra <atish.patra@wdc.com>,
	Geert Uytterhoeven <geert@linux-m68k.org>,
	"Eric W. Biederman" <ebiederm@xmission.com>,
	Allison Randal <allison@lohutok.net>,
	Paul Walmsley <paul.walmsley@sifive.com>,
	Palmer Dabbelt <palmer@dabbelt.com>,
	linux-riscv <linux-riscv@lists.infradead.org>,
	Borislav Petkov <bp@suse.de>,
	Thomas Gleixner <tglx@linutronix.de>, Mao Han <han_mao@c-sky.com>,
	Marek Szyprowski <m.szyprowski@samsung.com>
Subject: Re: [PATCH v8 07/11] RISC-V: Add cpu_ops and modify default booting method
Date: Wed, 12 Feb 2020 10:57:37 -0800	[thread overview]
Message-ID: <CAOnJCUJtsQF64QxV=e+=g0aRur0wEXbiMDU96g1QH7pAThoeqA@mail.gmail.com> (raw)
In-Reply-To: <CAAhSdy3RVpbum-O_ercZJkiEjDYPT-zrEHvYvMUQqE8+P82ihA@mail.gmail.com>

On Tue, Feb 11, 2020 at 8:28 PM Anup Patel <anup@brainfault.org> wrote:
>
> On Wed, Feb 12, 2020 at 7:21 AM Atish Patra <atish.patra@wdc.com> wrote:
> >
> > Currently, all non-booting harts start booting after the booting hart
> > updates the per-hart stack pointer. This is done in a way that, it's
> > difficult to implement any other booting method without breaking the
> > backward compatibility.
> >
> > Define a cpu_ops method that allows to introduce other booting methods
> > in future. Modify the current booting method to be compatible with
> > cpu_ops.
> >
> > Signed-off-by: Atish Patra <atish.patra@wdc.com>
> > ---
> >  arch/riscv/include/asm/cpu_ops.h     | 34 ++++++++++++++++++
> >  arch/riscv/kernel/Makefile           |  2 ++
> >  arch/riscv/kernel/cpu_ops.c          | 40 +++++++++++++++++++++
> >  arch/riscv/kernel/cpu_ops_spinwait.c | 42 ++++++++++++++++++++++
> >  arch/riscv/kernel/smpboot.c          | 54 +++++++++++++++++-----------
> >  5 files changed, 151 insertions(+), 21 deletions(-)
> >  create mode 100644 arch/riscv/include/asm/cpu_ops.h
> >  create mode 100644 arch/riscv/kernel/cpu_ops.c
> >  create mode 100644 arch/riscv/kernel/cpu_ops_spinwait.c
> >
> > diff --git a/arch/riscv/include/asm/cpu_ops.h b/arch/riscv/include/asm/cpu_ops.h
> > new file mode 100644
> > index 000000000000..7db276284009
> > --- /dev/null
> > +++ b/arch/riscv/include/asm/cpu_ops.h
> > @@ -0,0 +1,34 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/*
> > + * Copyright (c) 2019 Western Digital Corporation or its affiliates.
> > + * Based on arch/arm64/include/asm/cpu_ops.h
> > + */
> > +#ifndef __ASM_CPU_OPS_H
> > +#define __ASM_CPU_OPS_H
> > +
> > +#include <linux/init.h>
> > +#include <linux/sched.h>
> > +#include <linux/threads.h>
> > +
> > +/**
> > + * struct cpu_operations - Callback operations for hotplugging CPUs.
> > + *
> > + * @name:              Name of the boot protocol.
> > + * @cpu_prepare:       Early one-time preparation step for a cpu. If there
> > + *                     is a mechanism for doing so, tests whether it is
> > + *                     possible to boot the given HART.
> > + * @cpu_start:         Boots a cpu into the kernel.
> > + */
> > +struct cpu_operations {
> > +       const char      *name;
> > +       int             (*cpu_prepare)(unsigned int cpu);
> > +       int             (*cpu_start)(unsigned int cpu,
> > +                                    struct task_struct *tidle);
> > +};
> > +
> > +extern const struct cpu_operations *cpu_ops[NR_CPUS];
> > +int __init cpu_set_ops(int cpu);
>
> This function is more like probing for appropriate cpu_ops. Also,
> I think we don't need to return anything from cpu_set_ops().
>

Correct. I will change it to void but I think set_ops is a better name
as we are actually
setting the right type of ops to cpu_ops.

> Maybe rename it to "void cpu_probe_ops(int cpu)" ?
>
> > +void cpu_update_secondary_bootdata(unsigned int cpuid,
> > +                                  struct task_struct *tidle);
> > +
> > +#endif /* ifndef __ASM_CPU_OPS_H */
> > diff --git a/arch/riscv/kernel/Makefile b/arch/riscv/kernel/Makefile
> > index f40205cb9a22..f81a6ff88005 100644
> > --- a/arch/riscv/kernel/Makefile
> > +++ b/arch/riscv/kernel/Makefile
> > @@ -32,6 +32,8 @@ obj-$(CONFIG_RISCV_M_MODE)    += clint.o
> >  obj-$(CONFIG_FPU)              += fpu.o
> >  obj-$(CONFIG_SMP)              += smpboot.o
> >  obj-$(CONFIG_SMP)              += smp.o
> > +obj-$(CONFIG_SMP)              += cpu_ops.o
> > +obj-$(CONFIG_SMP)              += cpu_ops_spinwait.o
> >  obj-$(CONFIG_MODULES)          += module.o
> >  obj-$(CONFIG_MODULE_SECTIONS)  += module-sections.o
> >
> > diff --git a/arch/riscv/kernel/cpu_ops.c b/arch/riscv/kernel/cpu_ops.c
> > new file mode 100644
> > index 000000000000..1085def3735a
> > --- /dev/null
> > +++ b/arch/riscv/kernel/cpu_ops.c
> > @@ -0,0 +1,40 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> > + */
> > +
> > +#include <linux/errno.h>
> > +#include <linux/mm.h>
> > +#include <linux/of.h>
> > +#include <linux/string.h>
> > +#include <linux/sched.h>
> > +#include <linux/sched/task_stack.h>
> > +#include <asm/cpu_ops.h>
> > +#include <asm/sbi.h>
> > +#include <asm/smp.h>
> > +
> > +const struct cpu_operations *cpu_ops[NR_CPUS] __ro_after_init;
> > +
> > +void *__cpu_up_stack_pointer[NR_CPUS];
> > +void *__cpu_up_task_pointer[NR_CPUS];
> > +
> > +extern const struct cpu_operations cpu_ops_spinwait;
> > +
> > +void cpu_update_secondary_bootdata(unsigned int cpuid,
> > +                                  struct task_struct *tidle)
> > +{
> > +       int hartid = cpuid_to_hartid_map(cpuid);
> > +
> > +       /* Make sure tidle is updated */
> > +       smp_mb();
> > +       WRITE_ONCE(__cpu_up_stack_pointer[hartid],
> > +                 task_stack_page(tidle) + THREAD_SIZE);
> > +       WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
> > +}
> > +
> > +int __init cpu_set_ops(int cpuid)
>
> Maybe rename it to "void cpu_probe_ops(int cpu)" ?
>
> > +{
> > +       cpu_ops[cpuid] = &cpu_ops_spinwait;
> > +
> > +       return 0;
> > +}
> > diff --git a/arch/riscv/kernel/cpu_ops_spinwait.c b/arch/riscv/kernel/cpu_ops_spinwait.c
> > new file mode 100644
> > index 000000000000..f828e660294e
> > --- /dev/null
> > +++ b/arch/riscv/kernel/cpu_ops_spinwait.c
> > @@ -0,0 +1,42 @@
> > +// SPDX-License-Identifier: GPL-2.0-only
> > +/*
> > + * Copyright (c) 2020 Western Digital Corporation or its affiliates.
> > + */
> > +
> > +#include <linux/errno.h>
> > +#include <linux/of.h>
> > +#include <linux/string.h>
> > +#include <asm/cpu_ops.h>
> > +#include <asm/sbi.h>
> > +#include <asm/smp.h>
> > +
> > +const struct cpu_operations cpu_ops_spinwait;
> > +
> > +static int spinwait_cpu_prepare(unsigned int cpuid)
> > +{
> > +       if (!cpu_ops_spinwait.cpu_start) {
> > +               pr_err("cpu start method not defined for CPU [%d]\n", cpuid);
> > +               return -ENODEV;
> > +       }
> > +       return 0;
> > +}
> > +
> > +static int spinwait_cpu_start(unsigned int cpuid, struct task_struct *tidle)
> > +{
> > +       /*
> > +        * In this protocol, all cpus boot on their own accord.  _start
> > +        * selects the first cpu to boot the kernel and causes the remainder
> > +        * of the cpus to spin in a loop waiting for their stack pointer to be
> > +        * setup by that main cpu.  Writing to bootdata (i.e __cpu_up_stack_pointer) signals to
> > +        * the spinning cpus that they can continue the boot process.
> > +        */
> > +       cpu_update_secondary_bootdata(cpuid, tidle);
> > +
> > +       return 0;
> > +}
> > +
> > +const struct cpu_operations cpu_ops_spinwait = {
> > +       .name           = "spinwait",
> > +       .cpu_prepare    = spinwait_cpu_prepare,
> > +       .cpu_start      = spinwait_cpu_start,
> > +};
> > diff --git a/arch/riscv/kernel/smpboot.c b/arch/riscv/kernel/smpboot.c
> > index 8bc01f0ca73b..2ee41c779a16 100644
> > --- a/arch/riscv/kernel/smpboot.c
> > +++ b/arch/riscv/kernel/smpboot.c
> > @@ -25,6 +25,7 @@
> >  #include <linux/sched/task_stack.h>
> >  #include <linux/sched/mm.h>
> >  #include <asm/clint.h>
> > +#include <asm/cpu_ops.h>
> >  #include <asm/irq.h>
> >  #include <asm/mmu_context.h>
> >  #include <asm/tlbflush.h>
> > @@ -34,8 +35,6 @@
> >
> >  #include "head.h"
> >
> > -void *__cpu_up_stack_pointer[NR_CPUS];
> > -void *__cpu_up_task_pointer[NR_CPUS];
> >  static DECLARE_COMPLETION(cpu_running);
> >
> >  void __init smp_prepare_boot_cpu(void)
> > @@ -46,6 +45,7 @@ void __init smp_prepare_boot_cpu(void)
> >  void __init smp_prepare_cpus(unsigned int max_cpus)
> >  {
> >         int cpuid;
> > +       int ret;
> >
> >         /* This covers non-smp usecase mandated by "nosmp" option */
> >         if (max_cpus == 0)
> > @@ -54,6 +54,11 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
> >         for_each_possible_cpu(cpuid) {
> >                 if (cpuid == smp_processor_id())
> >                         continue;
> > +               if (cpu_ops[cpuid]->cpu_prepare) {
> > +                       ret = cpu_ops[cpuid]->cpu_prepare(cpuid);
> > +                       if (ret)
> > +                               continue;
> > +               }
> >                 set_cpu_present(cpuid, true);
> >         }
> >  }
> > @@ -65,6 +70,8 @@ void __init setup_smp(void)
> >         bool found_boot_cpu = false;
> >         int cpuid = 1;
> >
> > +       cpu_set_ops(0);
> > +
> >         for_each_of_cpu_node(dn) {
> >                 hart = riscv_of_processor_hartid(dn);
> >                 if (hart < 0)
> > @@ -92,36 +99,41 @@ void __init setup_smp(void)
> >                         cpuid, nr_cpu_ids);
> >
> >         for (cpuid = 1; cpuid < nr_cpu_ids; cpuid++) {
> > -               if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID)
> > +               if (cpuid_to_hartid_map(cpuid) != INVALID_HARTID) {
> > +                       if (cpu_set_ops(cpuid)) {
> > +                               cpuid_to_hartid_map(cpuid) = INVALID_HARTID;
> > +                               continue;
> > +                       }
> >                         set_cpu_possible(cpuid, true);
> > +               }
> >         }
> >  }
> >
> > +int start_secondary_cpu(int cpu, struct task_struct *tidle)
>
> Make this function static.
>

sure.

> > +{
> > +       if (cpu_ops[cpu]->cpu_start)
> > +               return cpu_ops[cpu]->cpu_start(cpu, tidle);
> > +
> > +       return -EOPNOTSUPP;
> > +}
> > +
> >  int __cpu_up(unsigned int cpu, struct task_struct *tidle)
> >  {
> >         int ret = 0;
> > -       int hartid = cpuid_to_hartid_map(cpu);
> >         tidle->thread_info.cpu = cpu;
> >
> > -       /*
> > -        * On RISC-V systems, all harts boot on their own accord.  Our _start
> > -        * selects the first hart to boot the kernel and causes the remainder
> > -        * of the harts to spin in a loop waiting for their stack pointer to be
> > -        * setup by that main hart.  Writing __cpu_up_stack_pointer signals to
> > -        * the spinning harts that they can continue the boot process.
> > -        */
> > -       smp_mb();
> > -       WRITE_ONCE(__cpu_up_stack_pointer[hartid],
> > -                 task_stack_page(tidle) + THREAD_SIZE);
> > -       WRITE_ONCE(__cpu_up_task_pointer[hartid], tidle);
> > -
> > -       lockdep_assert_held(&cpu_running);
> > -       wait_for_completion_timeout(&cpu_running,
> > +       ret = start_secondary_cpu(cpu, tidle);
> > +       if (!ret) {
> > +               lockdep_assert_held(&cpu_running);
> > +               wait_for_completion_timeout(&cpu_running,
> >                                             msecs_to_jiffies(1000));
> >
> > -       if (!cpu_online(cpu)) {
> > -               pr_crit("CPU%u: failed to come online\n", cpu);
> > -               ret = -EIO;
> > +               if (!cpu_online(cpu)) {
> > +                       pr_crit("CPU%u: failed to come online\n", cpu);
> > +                       ret = -EIO;
> > +               }
> > +       } else {
> > +               pr_crit("CPU%u: failed to start\n", cpu);
> >         }
> >
> >         return ret;
> > --
> > 2.24.0
> >
>
> Apart from minor comments above, looks good to me.
>
> Reviewed-by: Anup Patel <anup@brainfault.org>
>
> Regards,
> Anup
>


-- 
Regards,
Atish


  reply	other threads:[~2020-02-12 18:57 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-12  1:48 [PATCH v8 00/11] Add support for SBI v0.2 and CPU hotplug Atish Patra
2020-02-12  1:48 ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 01/11] RISC-V: Mark existing SBI as 0.1 SBI Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 02/11] RISC-V: Add basic support for SBI v0.2 Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 03/11] RISC-V: Add SBI v0.2 extension definitions Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 04/11] RISC-V: Introduce a new config for SBI v0.1 Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 05/11] RISC-V: Implement new SBI v0.2 extensions Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 06/11] RISC-V: Move relocate and few other functions out of __init Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  4:18   ` Anup Patel
2020-02-12  4:18     ` Anup Patel
2020-02-12 18:58     ` Atish Patra
2020-02-12 18:58       ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 07/11] RISC-V: Add cpu_ops and modify default booting method Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  4:28   ` Anup Patel
2020-02-12  4:28     ` Anup Patel
2020-02-12 18:57     ` Atish Patra [this message]
2020-02-12 18:57       ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 08/11] RISC-V: Add SBI HSM extension Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  4:53   ` Anup Patel
2020-02-12  4:53     ` Anup Patel
2020-02-12 19:54     ` Atish Patra
2020-02-12 19:54       ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 09/11] RISC-V: Add supported for ordered booting method using HSM Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  4:57   ` Anup Patel
2020-02-12  4:57     ` Anup Patel
2020-02-12  1:48 ` [PATCH v8 10/11] irqchip/sifive-plic: Initialize the plic handler when cpu comes online Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  5:10   ` Anup Patel
2020-02-12  5:10     ` Anup Patel
2020-02-13 11:01   ` Thomas Gleixner
2020-02-13 11:01     ` Thomas Gleixner
2020-02-13 19:01     ` Atish Patra
2020-02-13 19:01       ` Atish Patra
2020-02-12  1:48 ` [PATCH v8 11/11] RISC-V: Support cpu hotplug Atish Patra
2020-02-12  1:48   ` Atish Patra
2020-02-12  5:13   ` Anup Patel
2020-02-12  5:13     ` Anup Patel
2020-02-19 21:48 ` [PATCH v8 00/11] Add support for SBI v0.2 and CPU hotplug Palmer Dabbelt
2020-02-19 21:48   ` Palmer Dabbelt
2020-02-20  1:16   ` Atish Patra
2020-02-20  1:16     ` Atish Patra

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to='CAOnJCUJtsQF64QxV=e+=g0aRur0wEXbiMDU96g1QH7pAThoeqA@mail.gmail.com' \
    --to=atishp@atishpatra.org \
    --cc=allison@lohutok.net \
    --cc=anup@brainfault.org \
    --cc=aou@eecs.berkeley.edu \
    --cc=atish.patra@wdc.com \
    --cc=bp@suse.de \
    --cc=daniel.lezcano@linaro.org \
    --cc=ebiederm@xmission.com \
    --cc=geert@linux-m68k.org \
    --cc=han_mao@c-sky.com \
    --cc=heiko.carstens@de.ibm.com \
    --cc=jason@lakedaemon.net \
    --cc=keescook@chromium.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-riscv@lists.infradead.org \
    --cc=m.szyprowski@samsung.com \
    --cc=maz@kernel.org \
    --cc=mpe@ellerman.id.au \
    --cc=palmer@dabbelt.com \
    --cc=paul.walmsley@sifive.com \
    --cc=rppt@linux.ibm.com \
    --cc=tglx@linutronix.de \
    --cc=vincent.chen@sifive.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.