18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * lib/smp_processor_id.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * DEBUG_PREEMPT variant of smp_processor_id(). 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci#include <linux/export.h> 88c2ecf20Sopenharmony_ci#include <linux/kprobes.h> 98c2ecf20Sopenharmony_ci#include <linux/sched.h> 108c2ecf20Sopenharmony_ci 118c2ecf20Sopenharmony_cinoinstr static 128c2ecf20Sopenharmony_ciunsigned int check_preemption_disabled(const char *what1, const char *what2) 138c2ecf20Sopenharmony_ci{ 148c2ecf20Sopenharmony_ci int this_cpu = raw_smp_processor_id(); 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci if (likely(preempt_count())) 178c2ecf20Sopenharmony_ci goto out; 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci if (irqs_disabled()) 208c2ecf20Sopenharmony_ci goto out; 218c2ecf20Sopenharmony_ci 228c2ecf20Sopenharmony_ci /* 238c2ecf20Sopenharmony_ci * Kernel threads bound to a single CPU can safely use 248c2ecf20Sopenharmony_ci * smp_processor_id(): 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci if (current->nr_cpus_allowed == 1) 278c2ecf20Sopenharmony_ci goto out; 288c2ecf20Sopenharmony_ci 298c2ecf20Sopenharmony_ci /* 308c2ecf20Sopenharmony_ci * It is valid to assume CPU-locality during early bootup: 318c2ecf20Sopenharmony_ci */ 328c2ecf20Sopenharmony_ci if (system_state < SYSTEM_SCHEDULING) 338c2ecf20Sopenharmony_ci goto out; 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci /* 368c2ecf20Sopenharmony_ci * Avoid recursion: 378c2ecf20Sopenharmony_ci */ 388c2ecf20Sopenharmony_ci preempt_disable_notrace(); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci instrumentation_begin(); 418c2ecf20Sopenharmony_ci if (!printk_ratelimit()) 428c2ecf20Sopenharmony_ci goto out_enable; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci printk(KERN_ERR "BUG: using %s%s() in preemptible [%08x] code: %s/%d\n", 458c2ecf20Sopenharmony_ci what1, what2, preempt_count() - 1, current->comm, current->pid); 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci printk("caller is %pS\n", __builtin_return_address(0)); 488c2ecf20Sopenharmony_ci dump_stack(); 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_ciout_enable: 518c2ecf20Sopenharmony_ci instrumentation_end(); 528c2ecf20Sopenharmony_ci preempt_enable_no_resched_notrace(); 538c2ecf20Sopenharmony_ciout: 548c2ecf20Sopenharmony_ci return this_cpu; 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_cinoinstr unsigned int debug_smp_processor_id(void) 588c2ecf20Sopenharmony_ci{ 598c2ecf20Sopenharmony_ci return check_preemption_disabled("smp_processor_id", ""); 608c2ecf20Sopenharmony_ci} 618c2ecf20Sopenharmony_ciEXPORT_SYMBOL(debug_smp_processor_id); 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_cinoinstr void __this_cpu_preempt_check(const char *op) 648c2ecf20Sopenharmony_ci{ 658c2ecf20Sopenharmony_ci check_preemption_disabled("__this_cpu_", op); 668c2ecf20Sopenharmony_ci} 678c2ecf20Sopenharmony_ciEXPORT_SYMBOL(__this_cpu_preempt_check); 68