diff options
Diffstat (limited to '')
-rw-r--r-- | include/linux/smp.h | 261 |
1 files changed, 261 insertions, 0 deletions
diff --git a/include/linux/smp.h b/include/linux/smp.h new file mode 100644 index 000000000..04f44e0aa --- /dev/null +++ b/include/linux/smp.h @@ -0,0 +1,261 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef __LINUX_SMP_H +#define __LINUX_SMP_H + +/* + * Generic SMP support + * Alan Cox. <alan@redhat.com> + */ + +#include <linux/errno.h> +#include <linux/types.h> +#include <linux/list.h> +#include <linux/cpumask.h> +#include <linux/init.h> +#include <linux/smp_types.h> + +typedef void (*smp_call_func_t)(void *info); +typedef bool (*smp_cond_func_t)(int cpu, void *info); + +/* + * structure shares (partial) layout with struct irq_work + */ +struct __call_single_data { + union { + struct __call_single_node node; + struct { + struct llist_node llist; + unsigned int flags; +#ifdef CONFIG_64BIT + u16 src, dst; +#endif + }; + }; + smp_call_func_t func; + void *info; +}; + +/* Use __aligned() to avoid to use 2 cache lines for 1 csd */ +typedef struct __call_single_data call_single_data_t + __aligned(sizeof(struct __call_single_data)); + +/* + * Enqueue a llist_node on the call_single_queue; be very careful, read + * flush_smp_call_function_queue() in detail. + */ +extern void __smp_call_single_queue(int cpu, struct llist_node *node); + +/* total number of cpus in this system (may exceed NR_CPUS) */ +extern unsigned int total_cpus; + +int smp_call_function_single(int cpuid, smp_call_func_t func, void *info, + int wait); + +/* + * Call a function on all processors + */ +void on_each_cpu(smp_call_func_t func, void *info, int wait); + +/* + * Call a function on processors specified by mask, which might include + * the local one. + */ +void on_each_cpu_mask(const struct cpumask *mask, smp_call_func_t func, + void *info, bool wait); + +/* + * Call a function on each processor for which the supplied function + * cond_func returns a positive value. This may include the local + * processor. + */ +void on_each_cpu_cond(smp_cond_func_t cond_func, smp_call_func_t func, + void *info, bool wait); + +void on_each_cpu_cond_mask(smp_cond_func_t cond_func, smp_call_func_t func, + void *info, bool wait, const struct cpumask *mask); + +int smp_call_function_single_async(int cpu, struct __call_single_data *csd); + +#ifdef CONFIG_SMP + +#include <linux/preempt.h> +#include <linux/kernel.h> +#include <linux/compiler.h> +#include <linux/thread_info.h> +#include <asm/smp.h> + +/* + * main cross-CPU interfaces, handles INIT, TLB flush, STOP, etc. + * (defined in asm header): + */ + +/* + * stops all CPUs but the current one: + */ +extern void smp_send_stop(void); + +/* + * sends a 'reschedule' event to another CPU: + */ +extern void smp_send_reschedule(int cpu); + + +/* + * Prepare machine for booting other CPUs. + */ +extern void smp_prepare_cpus(unsigned int max_cpus); + +/* + * Bring a CPU up + */ +extern int __cpu_up(unsigned int cpunum, struct task_struct *tidle); + +/* + * Final polishing of CPUs + */ +extern void smp_cpus_done(unsigned int max_cpus); + +/* + * Call a function on all other processors + */ +void smp_call_function(smp_call_func_t func, void *info, int wait); +void smp_call_function_many(const struct cpumask *mask, + smp_call_func_t func, void *info, bool wait); + +int smp_call_function_any(const struct cpumask *mask, + smp_call_func_t func, void *info, int wait); + +void kick_all_cpus_sync(void); +void wake_up_all_idle_cpus(void); + +/* + * Generic and arch helpers + */ +void __init call_function_init(void); +void generic_smp_call_function_single_interrupt(void); +#define generic_smp_call_function_interrupt \ + generic_smp_call_function_single_interrupt + +/* + * Mark the boot cpu "online" so that it can call console drivers in + * printk() and can access its per-cpu storage. + */ +void smp_prepare_boot_cpu(void); + +extern unsigned int setup_max_cpus; +extern void __init setup_nr_cpu_ids(void); +extern void __init smp_init(void); + +extern int __boot_cpu_id; + +static inline int get_boot_cpu_id(void) +{ + return __boot_cpu_id; +} + +#else /* !SMP */ + +static inline void smp_send_stop(void) { } + +/* + * These macros fold the SMP functionality into a single CPU system + */ +#define raw_smp_processor_id() 0 +static inline void up_smp_call_function(smp_call_func_t func, void *info) +{ +} +#define smp_call_function(func, info, wait) \ + (up_smp_call_function(func, info)) + +static inline void smp_send_reschedule(int cpu) { } +#define smp_prepare_boot_cpu() do {} while (0) +#define smp_call_function_many(mask, func, info, wait) \ + (up_smp_call_function(func, info)) +static inline void call_function_init(void) { } + +static inline int +smp_call_function_any(const struct cpumask *mask, smp_call_func_t func, + void *info, int wait) +{ + return smp_call_function_single(0, func, info, wait); +} + +static inline void kick_all_cpus_sync(void) { } +static inline void wake_up_all_idle_cpus(void) { } + +#ifdef CONFIG_UP_LATE_INIT +extern void __init up_late_init(void); +static inline void smp_init(void) { up_late_init(); } +#else +static inline void smp_init(void) { } +#endif + +static inline int get_boot_cpu_id(void) +{ + return 0; +} + +#endif /* !SMP */ + +/** + * raw_processor_id() - get the current (unstable) CPU id + * + * For then you know what you are doing and need an unstable + * CPU id. + */ + +/** + * smp_processor_id() - get the current (stable) CPU id + * + * This is the normal accessor to the CPU id and should be used + * whenever possible. + * + * The CPU id is stable when: + * + * - IRQs are disabled; + * - preemption is disabled; + * - the task is CPU affine. + * + * When CONFIG_DEBUG_PREEMPT; we verify these assumption and WARN + * when smp_processor_id() is used when the CPU id is not stable. + */ + +/* + * Allow the architecture to differentiate between a stable and unstable read. + * For example, x86 uses an IRQ-safe asm-volatile read for the unstable but a + * regular asm read for the stable. + */ +#ifndef __smp_processor_id +#define __smp_processor_id(x) raw_smp_processor_id(x) +#endif + +#ifdef CONFIG_DEBUG_PREEMPT + extern unsigned int debug_smp_processor_id(void); +# define smp_processor_id() debug_smp_processor_id() +#else +# define smp_processor_id() __smp_processor_id() +#endif + +#define get_cpu() ({ preempt_disable(); __smp_processor_id(); }) +#define put_cpu() preempt_enable() + +/* + * Callback to arch code if there's nosmp or maxcpus=0 on the + * boot command line: + */ +extern void arch_disable_smp_support(void); + +extern void arch_thaw_secondary_cpus_begin(void); +extern void arch_thaw_secondary_cpus_end(void); + +void smp_setup_processor_id(void); + +int smp_call_on_cpu(unsigned int cpu, int (*func)(void *), void *par, + bool phys); + +/* SMP core functions */ +int smpcfd_prepare_cpu(unsigned int cpu); +int smpcfd_dead_cpu(unsigned int cpu); +int smpcfd_dying_cpu(unsigned int cpu); + +#endif /* __LINUX_SMP_H */ |