1457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 2fe9d4f57SAlexey Dobriyan #include <linux/kdebug.h> 3fe9d4f57SAlexey Dobriyan #include <linux/kprobes.h> 49984de1aSPaul Gortmaker #include <linux/export.h> 5fe9d4f57SAlexey Dobriyan #include <linux/notifier.h> 6fe9d4f57SAlexey Dobriyan #include <linux/rcupdate.h> 7fe9d4f57SAlexey Dobriyan #include <linux/vmalloc.h> 8c166f23cSAdrian Bunk #include <linux/reboot.h> 9fe9d4f57SAlexey Dobriyan 10fe9d4f57SAlexey Dobriyan /* 11fe9d4f57SAlexey Dobriyan * Notifier list for kernel code which wants to be called 12fe9d4f57SAlexey Dobriyan * at shutdown. This is used to stop any idling DMA operations 13fe9d4f57SAlexey Dobriyan * and the like. 14fe9d4f57SAlexey Dobriyan */ 15fe9d4f57SAlexey Dobriyan BLOCKING_NOTIFIER_HEAD(reboot_notifier_list); 16fe9d4f57SAlexey Dobriyan 17fe9d4f57SAlexey Dobriyan /* 18fe9d4f57SAlexey Dobriyan * Notifier chain core routines. The exported routines below 19fe9d4f57SAlexey Dobriyan * are layered on top of these, with appropriate locking added. 20fe9d4f57SAlexey Dobriyan */ 21fe9d4f57SAlexey Dobriyan 22fe9d4f57SAlexey Dobriyan static int notifier_chain_register(struct notifier_block **nl, 23fe9d4f57SAlexey Dobriyan struct notifier_block *n) 24fe9d4f57SAlexey Dobriyan { 25fe9d4f57SAlexey Dobriyan while ((*nl) != NULL) { 261a50cb80SXiaoming Ni if (unlikely((*nl) == n)) { 275abb065dSBorislav Petkov WARN(1, "notifier callback %ps already registered", 285abb065dSBorislav Petkov n->notifier_call); 295abb065dSBorislav Petkov return -EEXIST; 301a50cb80SXiaoming Ni } 31fe9d4f57SAlexey Dobriyan if (n->priority > (*nl)->priority) 32fe9d4f57SAlexey Dobriyan break; 33fe9d4f57SAlexey Dobriyan nl = &((*nl)->next); 34fe9d4f57SAlexey Dobriyan } 35fe9d4f57SAlexey Dobriyan n->next = *nl; 36fe9d4f57SAlexey Dobriyan rcu_assign_pointer(*nl, n); 37fe9d4f57SAlexey Dobriyan return 0; 38fe9d4f57SAlexey Dobriyan } 39fe9d4f57SAlexey Dobriyan 40fe9d4f57SAlexey Dobriyan static int notifier_chain_unregister(struct notifier_block **nl, 41fe9d4f57SAlexey Dobriyan struct notifier_block *n) 42fe9d4f57SAlexey Dobriyan { 43fe9d4f57SAlexey Dobriyan while ((*nl) != NULL) { 44fe9d4f57SAlexey Dobriyan if ((*nl) == n) { 45fe9d4f57SAlexey Dobriyan rcu_assign_pointer(*nl, n->next); 46fe9d4f57SAlexey Dobriyan return 0; 47fe9d4f57SAlexey Dobriyan } 48fe9d4f57SAlexey Dobriyan nl = &((*nl)->next); 49fe9d4f57SAlexey Dobriyan } 50fe9d4f57SAlexey Dobriyan return -ENOENT; 51fe9d4f57SAlexey Dobriyan } 52fe9d4f57SAlexey Dobriyan 53fe9d4f57SAlexey Dobriyan /** 54fe9d4f57SAlexey Dobriyan * notifier_call_chain - Informs the registered notifiers about an event. 55fe9d4f57SAlexey Dobriyan * @nl: Pointer to head of the blocking notifier chain 56fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 57fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 58fe9d4f57SAlexey Dobriyan * @nr_to_call: Number of notifier functions to be called. Don't care 59fe9d4f57SAlexey Dobriyan * value of this parameter is -1. 60fe9d4f57SAlexey Dobriyan * @nr_calls: Records the number of notifications sent. Don't care 61fe9d4f57SAlexey Dobriyan * value of this field is NULL. 62fe9d4f57SAlexey Dobriyan * @returns: notifier_call_chain returns the value returned by the 63fe9d4f57SAlexey Dobriyan * last notifier function called. 64fe9d4f57SAlexey Dobriyan */ 65b40a2cb6SMasami Hiramatsu static int notifier_call_chain(struct notifier_block **nl, 66fe9d4f57SAlexey Dobriyan unsigned long val, void *v, 67fe9d4f57SAlexey Dobriyan int nr_to_call, int *nr_calls) 68fe9d4f57SAlexey Dobriyan { 69fe9d4f57SAlexey Dobriyan int ret = NOTIFY_DONE; 70fe9d4f57SAlexey Dobriyan struct notifier_block *nb, *next_nb; 71fe9d4f57SAlexey Dobriyan 72d11c563dSPaul E. McKenney nb = rcu_dereference_raw(*nl); 73fe9d4f57SAlexey Dobriyan 74fe9d4f57SAlexey Dobriyan while (nb && nr_to_call) { 75d11c563dSPaul E. McKenney next_nb = rcu_dereference_raw(nb->next); 761b2439dbSArjan van de Ven 771b2439dbSArjan van de Ven #ifdef CONFIG_DEBUG_NOTIFIERS 78ab7476cfSArjan van de Ven if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) { 791b2439dbSArjan van de Ven WARN(1, "Invalid notifier called!"); 801b2439dbSArjan van de Ven nb = next_nb; 811b2439dbSArjan van de Ven continue; 821b2439dbSArjan van de Ven } 831b2439dbSArjan van de Ven #endif 84fe9d4f57SAlexey Dobriyan ret = nb->notifier_call(nb, val, v); 85fe9d4f57SAlexey Dobriyan 86fe9d4f57SAlexey Dobriyan if (nr_calls) 87fe9d4f57SAlexey Dobriyan (*nr_calls)++; 88fe9d4f57SAlexey Dobriyan 893e6dadedSViresh Kumar if (ret & NOTIFY_STOP_MASK) 90fe9d4f57SAlexey Dobriyan break; 91fe9d4f57SAlexey Dobriyan nb = next_nb; 92fe9d4f57SAlexey Dobriyan nr_to_call--; 93fe9d4f57SAlexey Dobriyan } 94fe9d4f57SAlexey Dobriyan return ret; 95fe9d4f57SAlexey Dobriyan } 96b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notifier_call_chain); 97fe9d4f57SAlexey Dobriyan 9870d93298SPeter Zijlstra /** 9970d93298SPeter Zijlstra * notifier_call_chain_robust - Inform the registered notifiers about an event 10070d93298SPeter Zijlstra * and rollback on error. 10170d93298SPeter Zijlstra * @nl: Pointer to head of the blocking notifier chain 10270d93298SPeter Zijlstra * @val_up: Value passed unmodified to the notifier function 10370d93298SPeter Zijlstra * @val_down: Value passed unmodified to the notifier function when recovering 10470d93298SPeter Zijlstra * from an error on @val_up 10570d93298SPeter Zijlstra * @v Pointer passed unmodified to the notifier function 10670d93298SPeter Zijlstra * 10770d93298SPeter Zijlstra * NOTE: It is important the @nl chain doesn't change between the two 10870d93298SPeter Zijlstra * invocations of notifier_call_chain() such that we visit the 10970d93298SPeter Zijlstra * exact same notifier callbacks; this rules out any RCU usage. 11070d93298SPeter Zijlstra * 11170d93298SPeter Zijlstra * Returns: the return value of the @val_up call. 11270d93298SPeter Zijlstra */ 11370d93298SPeter Zijlstra static int notifier_call_chain_robust(struct notifier_block **nl, 11470d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, 11570d93298SPeter Zijlstra void *v) 11670d93298SPeter Zijlstra { 11770d93298SPeter Zijlstra int ret, nr = 0; 11870d93298SPeter Zijlstra 11970d93298SPeter Zijlstra ret = notifier_call_chain(nl, val_up, v, -1, &nr); 12070d93298SPeter Zijlstra if (ret & NOTIFY_STOP_MASK) 12170d93298SPeter Zijlstra notifier_call_chain(nl, val_down, v, nr-1, NULL); 12270d93298SPeter Zijlstra 12370d93298SPeter Zijlstra return ret; 12470d93298SPeter Zijlstra } 12570d93298SPeter Zijlstra 126fe9d4f57SAlexey Dobriyan /* 127fe9d4f57SAlexey Dobriyan * Atomic notifier chain routines. Registration and unregistration 128fe9d4f57SAlexey Dobriyan * use a spinlock, and call_chain is synchronized by RCU (no locks). 129fe9d4f57SAlexey Dobriyan */ 130fe9d4f57SAlexey Dobriyan 131fe9d4f57SAlexey Dobriyan /** 132fe9d4f57SAlexey Dobriyan * atomic_notifier_chain_register - Add notifier to an atomic notifier chain 133fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the atomic notifier chain 134fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 135fe9d4f57SAlexey Dobriyan * 136fe9d4f57SAlexey Dobriyan * Adds a notifier to an atomic notifier chain. 137fe9d4f57SAlexey Dobriyan * 1385abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 139fe9d4f57SAlexey Dobriyan */ 140fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_register(struct atomic_notifier_head *nh, 141fe9d4f57SAlexey Dobriyan struct notifier_block *n) 142fe9d4f57SAlexey Dobriyan { 143fe9d4f57SAlexey Dobriyan unsigned long flags; 144fe9d4f57SAlexey Dobriyan int ret; 145fe9d4f57SAlexey Dobriyan 146fe9d4f57SAlexey Dobriyan spin_lock_irqsave(&nh->lock, flags); 147fe9d4f57SAlexey Dobriyan ret = notifier_chain_register(&nh->head, n); 148fe9d4f57SAlexey Dobriyan spin_unlock_irqrestore(&nh->lock, flags); 149fe9d4f57SAlexey Dobriyan return ret; 150fe9d4f57SAlexey Dobriyan } 151fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_register); 152fe9d4f57SAlexey Dobriyan 153fe9d4f57SAlexey Dobriyan /** 154fe9d4f57SAlexey Dobriyan * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain 155fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the atomic notifier chain 156fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 157fe9d4f57SAlexey Dobriyan * 158fe9d4f57SAlexey Dobriyan * Removes a notifier from an atomic notifier chain. 159fe9d4f57SAlexey Dobriyan * 160fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 161fe9d4f57SAlexey Dobriyan */ 162fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, 163fe9d4f57SAlexey Dobriyan struct notifier_block *n) 164fe9d4f57SAlexey Dobriyan { 165fe9d4f57SAlexey Dobriyan unsigned long flags; 166fe9d4f57SAlexey Dobriyan int ret; 167fe9d4f57SAlexey Dobriyan 168fe9d4f57SAlexey Dobriyan spin_lock_irqsave(&nh->lock, flags); 169fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 170fe9d4f57SAlexey Dobriyan spin_unlock_irqrestore(&nh->lock, flags); 171fe9d4f57SAlexey Dobriyan synchronize_rcu(); 172fe9d4f57SAlexey Dobriyan return ret; 173fe9d4f57SAlexey Dobriyan } 174fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister); 175fe9d4f57SAlexey Dobriyan 176fe9d4f57SAlexey Dobriyan /** 17770d93298SPeter Zijlstra * atomic_notifier_call_chain - Call functions in an atomic notifier chain 178fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the atomic notifier chain 179fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 180fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 181fe9d4f57SAlexey Dobriyan * 182fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 183fe9d4f57SAlexey Dobriyan * run in an atomic context, so they must not block. 184fe9d4f57SAlexey Dobriyan * This routine uses RCU to synchronize with changes to the chain. 185fe9d4f57SAlexey Dobriyan * 186fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 187fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain() 188fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 189fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 190fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 191fe9d4f57SAlexey Dobriyan * of the last notifier function called. 192fe9d4f57SAlexey Dobriyan */ 19370d93298SPeter Zijlstra int atomic_notifier_call_chain(struct atomic_notifier_head *nh, 19470d93298SPeter Zijlstra unsigned long val, void *v) 195fe9d4f57SAlexey Dobriyan { 196fe9d4f57SAlexey Dobriyan int ret; 197fe9d4f57SAlexey Dobriyan 198fe9d4f57SAlexey Dobriyan rcu_read_lock(); 19970d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 200fe9d4f57SAlexey Dobriyan rcu_read_unlock(); 201fe9d4f57SAlexey Dobriyan 20270d93298SPeter Zijlstra return ret; 203fe9d4f57SAlexey Dobriyan } 204fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_call_chain); 205b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(atomic_notifier_call_chain); 206fe9d4f57SAlexey Dobriyan 207*13dfd97aSDmitry Osipenko /** 208*13dfd97aSDmitry Osipenko * atomic_notifier_call_chain_is_empty - Check whether notifier chain is empty 209*13dfd97aSDmitry Osipenko * @nh: Pointer to head of the atomic notifier chain 210*13dfd97aSDmitry Osipenko * 211*13dfd97aSDmitry Osipenko * Checks whether notifier chain is empty. 212*13dfd97aSDmitry Osipenko * 213*13dfd97aSDmitry Osipenko * Returns true is notifier chain is empty, false otherwise. 214*13dfd97aSDmitry Osipenko */ 215*13dfd97aSDmitry Osipenko bool atomic_notifier_call_chain_is_empty(struct atomic_notifier_head *nh) 216*13dfd97aSDmitry Osipenko { 217*13dfd97aSDmitry Osipenko return !rcu_access_pointer(nh->head); 218*13dfd97aSDmitry Osipenko } 219*13dfd97aSDmitry Osipenko 220fe9d4f57SAlexey Dobriyan /* 221fe9d4f57SAlexey Dobriyan * Blocking notifier chain routines. All access to the chain is 222fe9d4f57SAlexey Dobriyan * synchronized by an rwsem. 223fe9d4f57SAlexey Dobriyan */ 224fe9d4f57SAlexey Dobriyan 225fe9d4f57SAlexey Dobriyan /** 226fe9d4f57SAlexey Dobriyan * blocking_notifier_chain_register - Add notifier to a blocking notifier chain 227fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 228fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 229fe9d4f57SAlexey Dobriyan * 230fe9d4f57SAlexey Dobriyan * Adds a notifier to a blocking notifier chain. 231fe9d4f57SAlexey Dobriyan * Must be called in process context. 232fe9d4f57SAlexey Dobriyan * 2335abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 234fe9d4f57SAlexey Dobriyan */ 235fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh, 236fe9d4f57SAlexey Dobriyan struct notifier_block *n) 237fe9d4f57SAlexey Dobriyan { 238fe9d4f57SAlexey Dobriyan int ret; 239fe9d4f57SAlexey Dobriyan 240fe9d4f57SAlexey Dobriyan /* 241fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 242fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 243fe9d4f57SAlexey Dobriyan * such times we must not call down_write(). 244fe9d4f57SAlexey Dobriyan */ 245fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 246fe9d4f57SAlexey Dobriyan return notifier_chain_register(&nh->head, n); 247fe9d4f57SAlexey Dobriyan 248fe9d4f57SAlexey Dobriyan down_write(&nh->rwsem); 249fe9d4f57SAlexey Dobriyan ret = notifier_chain_register(&nh->head, n); 250fe9d4f57SAlexey Dobriyan up_write(&nh->rwsem); 251fe9d4f57SAlexey Dobriyan return ret; 252fe9d4f57SAlexey Dobriyan } 253fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); 254fe9d4f57SAlexey Dobriyan 255fe9d4f57SAlexey Dobriyan /** 256fe9d4f57SAlexey Dobriyan * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain 257fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 258fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 259fe9d4f57SAlexey Dobriyan * 260fe9d4f57SAlexey Dobriyan * Removes a notifier from a blocking notifier chain. 261fe9d4f57SAlexey Dobriyan * Must be called from process context. 262fe9d4f57SAlexey Dobriyan * 263fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 264fe9d4f57SAlexey Dobriyan */ 265fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, 266fe9d4f57SAlexey Dobriyan struct notifier_block *n) 267fe9d4f57SAlexey Dobriyan { 268fe9d4f57SAlexey Dobriyan int ret; 269fe9d4f57SAlexey Dobriyan 270fe9d4f57SAlexey Dobriyan /* 271fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 272fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 273fe9d4f57SAlexey Dobriyan * such times we must not call down_write(). 274fe9d4f57SAlexey Dobriyan */ 275fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 276fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 277fe9d4f57SAlexey Dobriyan 278fe9d4f57SAlexey Dobriyan down_write(&nh->rwsem); 279fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 280fe9d4f57SAlexey Dobriyan up_write(&nh->rwsem); 281fe9d4f57SAlexey Dobriyan return ret; 282fe9d4f57SAlexey Dobriyan } 283fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister); 284fe9d4f57SAlexey Dobriyan 28570d93298SPeter Zijlstra int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh, 28670d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, void *v) 28770d93298SPeter Zijlstra { 28870d93298SPeter Zijlstra int ret = NOTIFY_DONE; 28970d93298SPeter Zijlstra 29070d93298SPeter Zijlstra /* 29170d93298SPeter Zijlstra * We check the head outside the lock, but if this access is 29270d93298SPeter Zijlstra * racy then it does not matter what the result of the test 29370d93298SPeter Zijlstra * is, we re-check the list after having taken the lock anyway: 29470d93298SPeter Zijlstra */ 29570d93298SPeter Zijlstra if (rcu_access_pointer(nh->head)) { 29670d93298SPeter Zijlstra down_read(&nh->rwsem); 29770d93298SPeter Zijlstra ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v); 29870d93298SPeter Zijlstra up_read(&nh->rwsem); 29970d93298SPeter Zijlstra } 30070d93298SPeter Zijlstra return ret; 30170d93298SPeter Zijlstra } 30270d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust); 30370d93298SPeter Zijlstra 304fe9d4f57SAlexey Dobriyan /** 30570d93298SPeter Zijlstra * blocking_notifier_call_chain - Call functions in a blocking notifier chain 306fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 307fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 308fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 309fe9d4f57SAlexey Dobriyan * 310fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 311fe9d4f57SAlexey Dobriyan * run in a process context, so they are allowed to block. 312fe9d4f57SAlexey Dobriyan * 313fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 314fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain() 315fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 316fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 317fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 318fe9d4f57SAlexey Dobriyan * of the last notifier function called. 319fe9d4f57SAlexey Dobriyan */ 32070d93298SPeter Zijlstra int blocking_notifier_call_chain(struct blocking_notifier_head *nh, 32170d93298SPeter Zijlstra unsigned long val, void *v) 322fe9d4f57SAlexey Dobriyan { 323fe9d4f57SAlexey Dobriyan int ret = NOTIFY_DONE; 324fe9d4f57SAlexey Dobriyan 325fe9d4f57SAlexey Dobriyan /* 326fe9d4f57SAlexey Dobriyan * We check the head outside the lock, but if this access is 327fe9d4f57SAlexey Dobriyan * racy then it does not matter what the result of the test 328fe9d4f57SAlexey Dobriyan * is, we re-check the list after having taken the lock anyway: 329fe9d4f57SAlexey Dobriyan */ 3308857563bSPaul E. McKenney if (rcu_access_pointer(nh->head)) { 331fe9d4f57SAlexey Dobriyan down_read(&nh->rwsem); 33270d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 333fe9d4f57SAlexey Dobriyan up_read(&nh->rwsem); 334fe9d4f57SAlexey Dobriyan } 335fe9d4f57SAlexey Dobriyan return ret; 336fe9d4f57SAlexey Dobriyan } 337fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); 338fe9d4f57SAlexey Dobriyan 339fe9d4f57SAlexey Dobriyan /* 340fe9d4f57SAlexey Dobriyan * Raw notifier chain routines. There is no protection; 341fe9d4f57SAlexey Dobriyan * the caller must provide it. Use at your own risk! 342fe9d4f57SAlexey Dobriyan */ 343fe9d4f57SAlexey Dobriyan 344fe9d4f57SAlexey Dobriyan /** 345fe9d4f57SAlexey Dobriyan * raw_notifier_chain_register - Add notifier to a raw notifier chain 346fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 347fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 348fe9d4f57SAlexey Dobriyan * 349fe9d4f57SAlexey Dobriyan * Adds a notifier to a raw notifier chain. 350fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 351fe9d4f57SAlexey Dobriyan * 3525abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 353fe9d4f57SAlexey Dobriyan */ 354fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh, 355fe9d4f57SAlexey Dobriyan struct notifier_block *n) 356fe9d4f57SAlexey Dobriyan { 357fe9d4f57SAlexey Dobriyan return notifier_chain_register(&nh->head, n); 358fe9d4f57SAlexey Dobriyan } 359fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register); 360fe9d4f57SAlexey Dobriyan 361fe9d4f57SAlexey Dobriyan /** 362fe9d4f57SAlexey Dobriyan * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain 363fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 364fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 365fe9d4f57SAlexey Dobriyan * 366fe9d4f57SAlexey Dobriyan * Removes a notifier from a raw notifier chain. 367fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 368fe9d4f57SAlexey Dobriyan * 369fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 370fe9d4f57SAlexey Dobriyan */ 371fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh, 372fe9d4f57SAlexey Dobriyan struct notifier_block *n) 373fe9d4f57SAlexey Dobriyan { 374fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 375fe9d4f57SAlexey Dobriyan } 376fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister); 377fe9d4f57SAlexey Dobriyan 37870d93298SPeter Zijlstra int raw_notifier_call_chain_robust(struct raw_notifier_head *nh, 37970d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, void *v) 38070d93298SPeter Zijlstra { 38170d93298SPeter Zijlstra return notifier_call_chain_robust(&nh->head, val_up, val_down, v); 38270d93298SPeter Zijlstra } 38370d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust); 38470d93298SPeter Zijlstra 385fe9d4f57SAlexey Dobriyan /** 38670d93298SPeter Zijlstra * raw_notifier_call_chain - Call functions in a raw notifier chain 387fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 388fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 389fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 390fe9d4f57SAlexey Dobriyan * 391fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 392fe9d4f57SAlexey Dobriyan * run in an undefined context. 393fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 394fe9d4f57SAlexey Dobriyan * 395fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 396fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then raw_notifier_call_chain() 397fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 398fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 399fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 400fe9d4f57SAlexey Dobriyan * of the last notifier function called. 401fe9d4f57SAlexey Dobriyan */ 402fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh, 403fe9d4f57SAlexey Dobriyan unsigned long val, void *v) 404fe9d4f57SAlexey Dobriyan { 40570d93298SPeter Zijlstra return notifier_call_chain(&nh->head, val, v, -1, NULL); 406fe9d4f57SAlexey Dobriyan } 407fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain); 408fe9d4f57SAlexey Dobriyan 40983fe27eaSPranith Kumar #ifdef CONFIG_SRCU 410fe9d4f57SAlexey Dobriyan /* 411fe9d4f57SAlexey Dobriyan * SRCU notifier chain routines. Registration and unregistration 412fe9d4f57SAlexey Dobriyan * use a mutex, and call_chain is synchronized by SRCU (no locks). 413fe9d4f57SAlexey Dobriyan */ 414fe9d4f57SAlexey Dobriyan 415fe9d4f57SAlexey Dobriyan /** 416fe9d4f57SAlexey Dobriyan * srcu_notifier_chain_register - Add notifier to an SRCU notifier chain 417fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 418fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 419fe9d4f57SAlexey Dobriyan * 420fe9d4f57SAlexey Dobriyan * Adds a notifier to an SRCU notifier chain. 421fe9d4f57SAlexey Dobriyan * Must be called in process context. 422fe9d4f57SAlexey Dobriyan * 4235abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 424fe9d4f57SAlexey Dobriyan */ 425fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh, 426fe9d4f57SAlexey Dobriyan struct notifier_block *n) 427fe9d4f57SAlexey Dobriyan { 428fe9d4f57SAlexey Dobriyan int ret; 429fe9d4f57SAlexey Dobriyan 430fe9d4f57SAlexey Dobriyan /* 431fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 432fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 433fe9d4f57SAlexey Dobriyan * such times we must not call mutex_lock(). 434fe9d4f57SAlexey Dobriyan */ 435fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 436fe9d4f57SAlexey Dobriyan return notifier_chain_register(&nh->head, n); 437fe9d4f57SAlexey Dobriyan 438fe9d4f57SAlexey Dobriyan mutex_lock(&nh->mutex); 439fe9d4f57SAlexey Dobriyan ret = notifier_chain_register(&nh->head, n); 440fe9d4f57SAlexey Dobriyan mutex_unlock(&nh->mutex); 441fe9d4f57SAlexey Dobriyan return ret; 442fe9d4f57SAlexey Dobriyan } 443fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register); 444fe9d4f57SAlexey Dobriyan 445fe9d4f57SAlexey Dobriyan /** 446fe9d4f57SAlexey Dobriyan * srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain 447fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 448fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 449fe9d4f57SAlexey Dobriyan * 450fe9d4f57SAlexey Dobriyan * Removes a notifier from an SRCU notifier chain. 451fe9d4f57SAlexey Dobriyan * Must be called from process context. 452fe9d4f57SAlexey Dobriyan * 453fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 454fe9d4f57SAlexey Dobriyan */ 455fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, 456fe9d4f57SAlexey Dobriyan struct notifier_block *n) 457fe9d4f57SAlexey Dobriyan { 458fe9d4f57SAlexey Dobriyan int ret; 459fe9d4f57SAlexey Dobriyan 460fe9d4f57SAlexey Dobriyan /* 461fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 462fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 463fe9d4f57SAlexey Dobriyan * such times we must not call mutex_lock(). 464fe9d4f57SAlexey Dobriyan */ 465fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 466fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 467fe9d4f57SAlexey Dobriyan 468fe9d4f57SAlexey Dobriyan mutex_lock(&nh->mutex); 469fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 470fe9d4f57SAlexey Dobriyan mutex_unlock(&nh->mutex); 471fe9d4f57SAlexey Dobriyan synchronize_srcu(&nh->srcu); 472fe9d4f57SAlexey Dobriyan return ret; 473fe9d4f57SAlexey Dobriyan } 474fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister); 475fe9d4f57SAlexey Dobriyan 476fe9d4f57SAlexey Dobriyan /** 47770d93298SPeter Zijlstra * srcu_notifier_call_chain - Call functions in an SRCU notifier chain 478fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 479fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 480fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 481fe9d4f57SAlexey Dobriyan * 482fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 483fe9d4f57SAlexey Dobriyan * run in a process context, so they are allowed to block. 484fe9d4f57SAlexey Dobriyan * 485fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 486fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then srcu_notifier_call_chain() 487fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 488fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 489fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 490fe9d4f57SAlexey Dobriyan * of the last notifier function called. 491fe9d4f57SAlexey Dobriyan */ 49270d93298SPeter Zijlstra int srcu_notifier_call_chain(struct srcu_notifier_head *nh, 49370d93298SPeter Zijlstra unsigned long val, void *v) 494fe9d4f57SAlexey Dobriyan { 495fe9d4f57SAlexey Dobriyan int ret; 496fe9d4f57SAlexey Dobriyan int idx; 497fe9d4f57SAlexey Dobriyan 498fe9d4f57SAlexey Dobriyan idx = srcu_read_lock(&nh->srcu); 49970d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 500fe9d4f57SAlexey Dobriyan srcu_read_unlock(&nh->srcu, idx); 501fe9d4f57SAlexey Dobriyan return ret; 502fe9d4f57SAlexey Dobriyan } 503fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain); 504fe9d4f57SAlexey Dobriyan 505fe9d4f57SAlexey Dobriyan /** 506fe9d4f57SAlexey Dobriyan * srcu_init_notifier_head - Initialize an SRCU notifier head 507fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the srcu notifier chain 508fe9d4f57SAlexey Dobriyan * 509fe9d4f57SAlexey Dobriyan * Unlike other sorts of notifier heads, SRCU notifier heads require 510fe9d4f57SAlexey Dobriyan * dynamic initialization. Be sure to call this routine before 511fe9d4f57SAlexey Dobriyan * calling any of the other SRCU notifier routines for this head. 512fe9d4f57SAlexey Dobriyan * 513fe9d4f57SAlexey Dobriyan * If an SRCU notifier head is deallocated, it must first be cleaned 514fe9d4f57SAlexey Dobriyan * up by calling srcu_cleanup_notifier_head(). Otherwise the head's 515fe9d4f57SAlexey Dobriyan * per-cpu data (used by the SRCU mechanism) will leak. 516fe9d4f57SAlexey Dobriyan */ 517fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh) 518fe9d4f57SAlexey Dobriyan { 519fe9d4f57SAlexey Dobriyan mutex_init(&nh->mutex); 520fe9d4f57SAlexey Dobriyan if (init_srcu_struct(&nh->srcu) < 0) 521fe9d4f57SAlexey Dobriyan BUG(); 522fe9d4f57SAlexey Dobriyan nh->head = NULL; 523fe9d4f57SAlexey Dobriyan } 524fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head); 525fe9d4f57SAlexey Dobriyan 52683fe27eaSPranith Kumar #endif /* CONFIG_SRCU */ 52783fe27eaSPranith Kumar 528fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain); 529fe9d4f57SAlexey Dobriyan 530b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str, 531fe9d4f57SAlexey Dobriyan struct pt_regs *regs, long err, int trap, int sig) 532fe9d4f57SAlexey Dobriyan { 533fe9d4f57SAlexey Dobriyan struct die_args args = { 534fe9d4f57SAlexey Dobriyan .regs = regs, 535fe9d4f57SAlexey Dobriyan .str = str, 536fe9d4f57SAlexey Dobriyan .err = err, 537fe9d4f57SAlexey Dobriyan .trapnr = trap, 538fe9d4f57SAlexey Dobriyan .signr = sig, 539fe9d4f57SAlexey Dobriyan 540fe9d4f57SAlexey Dobriyan }; 5415778077dSLinus Torvalds RCU_LOCKDEP_WARN(!rcu_is_watching(), 542e727c7d7SAndy Lutomirski "notify_die called but RCU thinks we're quiescent"); 543fe9d4f57SAlexey Dobriyan return atomic_notifier_call_chain(&die_chain, val, &args); 544fe9d4f57SAlexey Dobriyan } 545b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die); 546fe9d4f57SAlexey Dobriyan 547fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb) 548fe9d4f57SAlexey Dobriyan { 549fe9d4f57SAlexey Dobriyan return atomic_notifier_chain_register(&die_chain, nb); 550fe9d4f57SAlexey Dobriyan } 551fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier); 552fe9d4f57SAlexey Dobriyan 553fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb) 554fe9d4f57SAlexey Dobriyan { 555fe9d4f57SAlexey Dobriyan return atomic_notifier_chain_unregister(&die_chain, nb); 556fe9d4f57SAlexey Dobriyan } 557fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier); 558