1  /* SPDX-License-Identifier: GPL-2.0-only */
2  /*
3   * Copyright (C) 2012 ARM Ltd.
4   */
5  #ifndef __ASM_SMP_H
6  #define __ASM_SMP_H
7  
8  #include <linux/const.h>
9  
10  /* Values for secondary_data.status */
11  #define CPU_STUCK_REASON_SHIFT		(8)
12  #define CPU_BOOT_STATUS_MASK		((UL(1) << CPU_STUCK_REASON_SHIFT) - 1)
13  
14  #define CPU_MMU_OFF			(-1)
15  #define CPU_BOOT_SUCCESS		(0)
16  /* The cpu invoked ops->cpu_die, synchronise it with cpu_kill */
17  #define CPU_KILL_ME			(1)
18  /* The cpu couldn't die gracefully and is looping in the kernel */
19  #define CPU_STUCK_IN_KERNEL		(2)
20  /* Fatal system error detected by secondary CPU, crash the system */
21  #define CPU_PANIC_KERNEL		(3)
22  
23  #define CPU_STUCK_REASON_52_BIT_VA	(UL(1) << CPU_STUCK_REASON_SHIFT)
24  #define CPU_STUCK_REASON_NO_GRAN	(UL(2) << CPU_STUCK_REASON_SHIFT)
25  
26  #ifndef __ASSEMBLY__
27  
28  #include <linux/threads.h>
29  #include <linux/cpumask.h>
30  #include <linux/thread_info.h>
31  
32  #define raw_smp_processor_id() (current_thread_info()->cpu)
33  
34  /*
35   * Logical CPU mapping.
36   */
37  extern u64 __cpu_logical_map[NR_CPUS];
38  extern u64 cpu_logical_map(unsigned int cpu);
39  
set_cpu_logical_map(unsigned int cpu,u64 hwid)40  static inline void set_cpu_logical_map(unsigned int cpu, u64 hwid)
41  {
42  	__cpu_logical_map[cpu] = hwid;
43  }
44  
45  struct seq_file;
46  
47  /*
48   * Discover the set of possible CPUs and determine their
49   * SMP operations.
50   */
51  extern void smp_init_cpus(void);
52  
53  /*
54   * Register IPI interrupts with the arch SMP code
55   */
56  extern void set_smp_ipi_range(int ipi_base, int nr_ipi);
57  
58  /*
59   * Called from the secondary holding pen, this is the secondary CPU entry point.
60   */
61  asmlinkage void secondary_start_kernel(void);
62  
63  /*
64   * Initial data for bringing up a secondary CPU.
65   * @status - Result passed back from the secondary CPU to
66   *           indicate failure.
67   */
68  struct secondary_data {
69  	struct task_struct *task;
70  	long status;
71  };
72  
73  extern struct secondary_data secondary_data;
74  extern long __early_cpu_boot_status;
75  extern void secondary_entry(void);
76  
77  extern void arch_send_call_function_single_ipi(int cpu);
78  extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
79  
80  #ifdef CONFIG_ARM64_ACPI_PARKING_PROTOCOL
81  extern void arch_send_wakeup_ipi(unsigned int cpu);
82  #else
arch_send_wakeup_ipi(unsigned int cpu)83  static inline void arch_send_wakeup_ipi(unsigned int cpu)
84  {
85  	BUILD_BUG();
86  }
87  #endif
88  
89  extern int __cpu_disable(void);
90  
__cpu_die(unsigned int cpu)91  static inline void __cpu_die(unsigned int cpu) { }
92  extern void __noreturn cpu_die(void);
93  extern void __noreturn cpu_die_early(void);
94  
cpu_park_loop(void)95  static inline void __noreturn cpu_park_loop(void)
96  {
97  	for (;;) {
98  		wfe();
99  		wfi();
100  	}
101  }
102  
update_cpu_boot_status(int val)103  static inline void update_cpu_boot_status(int val)
104  {
105  	WRITE_ONCE(secondary_data.status, val);
106  	/* Ensure the visibility of the status update */
107  	dsb(ishst);
108  }
109  
110  /*
111   * The calling secondary CPU has detected serious configuration mismatch,
112   * which calls for a kernel panic. Update the boot status and park the calling
113   * CPU.
114   */
cpu_panic_kernel(void)115  static inline void __noreturn cpu_panic_kernel(void)
116  {
117  	update_cpu_boot_status(CPU_PANIC_KERNEL);
118  	cpu_park_loop();
119  }
120  
121  /*
122   * If a secondary CPU enters the kernel but fails to come online,
123   * (e.g. due to mismatched features), and cannot exit the kernel,
124   * we increment cpus_stuck_in_kernel and leave the CPU in a
125   * quiesecent loop within the kernel text. The memory containing
126   * this loop must not be re-used for anything else as the 'stuck'
127   * core is executing it.
128   *
129   * This function is used to inhibit features like kexec and hibernate.
130   */
131  bool cpus_are_stuck_in_kernel(void);
132  
133  extern void crash_smp_send_stop(void);
134  extern bool smp_crash_stop_failed(void);
135  
136  #endif /* ifndef __ASSEMBLY__ */
137  
138  #endif /* ifndef __ASM_SMP_H */
139