1  // SPDX-License-Identifier: GPL-2.0
2  /*
3   * lib/smp_processor_id.c
4   *
5   * DEBUG_PREEMPT variant of smp_processor_id().
6   */
7  #include <linux/export.h>
8  #include <linux/kprobes.h>
9  #include <linux/sched.h>
10  
11  noinstr static
check_preemption_disabled(const char * what1,const char * what2)12  unsigned int check_preemption_disabled(const char *what1, const char *what2)
13  {
14  	int this_cpu = raw_smp_processor_id();
15  
16  	if (likely(preempt_count()))
17  		goto out;
18  
19  	if (irqs_disabled())
20  		goto out;
21  
22  	if (is_percpu_thread())
23  		goto out;
24  
25  #ifdef CONFIG_SMP
26  	if (current->migration_disabled)
27  		goto out;
28  #endif
29  
30  	/*
31  	 * It is valid to assume CPU-locality during early bootup:
32  	 */
33  	if (system_state < SYSTEM_SCHEDULING)
34  		goto out;
35  
36  	/*
37  	 * Avoid recursion:
38  	 */
39  	preempt_disable_notrace();
40  
41  	instrumentation_begin();
42  	if (!printk_ratelimit())
43  		goto out_enable;
44  
45  	printk(KERN_ERR "BUG: using %s%s() in preemptible [%08x] code: %s/%d\n",
46  		what1, what2, preempt_count() - 1, current->comm, current->pid);
47  
48  	printk("caller is %pS\n", __builtin_return_address(0));
49  	dump_stack();
50  
51  out_enable:
52  	instrumentation_end();
53  	preempt_enable_no_resched_notrace();
54  out:
55  	return this_cpu;
56  }
57  
debug_smp_processor_id(void)58  noinstr unsigned int debug_smp_processor_id(void)
59  {
60  	return check_preemption_disabled("smp_processor_id", "");
61  }
62  EXPORT_SYMBOL(debug_smp_processor_id);
63  
__this_cpu_preempt_check(const char * op)64  noinstr void __this_cpu_preempt_check(const char *op)
65  {
66  	check_preemption_disabled("__this_cpu_", op);
67  }
68  EXPORT_SYMBOL(__this_cpu_preempt_check);
69