Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/riscv/kernel/cpu_ops_spinwait.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0-only
2
/*
3
* Copyright (c) 2020 Western Digital Corporation or its affiliates.
4
*/
5
6
#include <linux/errno.h>
7
#include <linux/of.h>
8
#include <linux/string.h>
9
#include <linux/sched/task_stack.h>
10
#include <asm/cpu_ops.h>
11
#include <asm/sbi.h>
12
#include <asm/smp.h>
13
14
#include "head.h"
15
16
const struct cpu_operations cpu_ops_spinwait;
17
void *__cpu_spinwait_stack_pointer[NR_CPUS] __section(".data");
18
void *__cpu_spinwait_task_pointer[NR_CPUS] __section(".data");
19
20
static void cpu_update_secondary_bootdata(unsigned int cpuid,
21
struct task_struct *tidle)
22
{
23
unsigned long hartid = cpuid_to_hartid_map(cpuid);
24
25
/*
26
* The hartid must be less than NR_CPUS to avoid out-of-bound access
27
* errors for __cpu_spinwait_stack/task_pointer. That is not always possible
28
* for platforms with discontiguous hartid numbering scheme. That's why
29
* spinwait booting is not the recommended approach for any platforms
30
* booting Linux in S-mode and can be disabled in the future.
31
*/
32
if (hartid == INVALID_HARTID || hartid >= (unsigned long) NR_CPUS)
33
return;
34
35
/* Make sure tidle is updated */
36
smp_mb();
37
WRITE_ONCE(__cpu_spinwait_stack_pointer[hartid], task_pt_regs(tidle));
38
WRITE_ONCE(__cpu_spinwait_task_pointer[hartid], tidle);
39
}
40
41
static int spinwait_cpu_start(unsigned int cpuid, struct task_struct *tidle)
42
{
43
/*
44
* In this protocol, all cpus boot on their own accord. _start
45
* selects the first cpu to boot the kernel and causes the remainder
46
* of the cpus to spin in a loop waiting for their stack pointer to be
47
* setup by that main cpu. Writing to bootdata
48
* (i.e __cpu_spinwait_stack_pointer) signals to the spinning cpus that they
49
* can continue the boot process.
50
*/
51
cpu_update_secondary_bootdata(cpuid, tidle);
52
53
return 0;
54
}
55
56
const struct cpu_operations cpu_ops_spinwait = {
57
.cpu_start = spinwait_cpu_start,
58
};
59
60