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, 23*c82f898dSDmitry Osipenko struct notifier_block *n, 24*c82f898dSDmitry Osipenko bool unique_priority) 25fe9d4f57SAlexey Dobriyan { 26fe9d4f57SAlexey Dobriyan while ((*nl) != NULL) { 271a50cb80SXiaoming Ni if (unlikely((*nl) == n)) { 285abb065dSBorislav Petkov WARN(1, "notifier callback %ps already registered", 295abb065dSBorislav Petkov n->notifier_call); 305abb065dSBorislav Petkov return -EEXIST; 311a50cb80SXiaoming Ni } 32fe9d4f57SAlexey Dobriyan if (n->priority > (*nl)->priority) 33fe9d4f57SAlexey Dobriyan break; 34*c82f898dSDmitry Osipenko if (n->priority == (*nl)->priority && unique_priority) 35*c82f898dSDmitry Osipenko return -EBUSY; 36fe9d4f57SAlexey Dobriyan nl = &((*nl)->next); 37fe9d4f57SAlexey Dobriyan } 38fe9d4f57SAlexey Dobriyan n->next = *nl; 39fe9d4f57SAlexey Dobriyan rcu_assign_pointer(*nl, n); 40fe9d4f57SAlexey Dobriyan return 0; 41fe9d4f57SAlexey Dobriyan } 42fe9d4f57SAlexey Dobriyan 43fe9d4f57SAlexey Dobriyan static int notifier_chain_unregister(struct notifier_block **nl, 44fe9d4f57SAlexey Dobriyan struct notifier_block *n) 45fe9d4f57SAlexey Dobriyan { 46fe9d4f57SAlexey Dobriyan while ((*nl) != NULL) { 47fe9d4f57SAlexey Dobriyan if ((*nl) == n) { 48fe9d4f57SAlexey Dobriyan rcu_assign_pointer(*nl, n->next); 49fe9d4f57SAlexey Dobriyan return 0; 50fe9d4f57SAlexey Dobriyan } 51fe9d4f57SAlexey Dobriyan nl = &((*nl)->next); 52fe9d4f57SAlexey Dobriyan } 53fe9d4f57SAlexey Dobriyan return -ENOENT; 54fe9d4f57SAlexey Dobriyan } 55fe9d4f57SAlexey Dobriyan 56fe9d4f57SAlexey Dobriyan /** 57fe9d4f57SAlexey Dobriyan * notifier_call_chain - Informs the registered notifiers about an event. 58fe9d4f57SAlexey Dobriyan * @nl: Pointer to head of the blocking notifier chain 59fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 60fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 61fe9d4f57SAlexey Dobriyan * @nr_to_call: Number of notifier functions to be called. Don't care 62fe9d4f57SAlexey Dobriyan * value of this parameter is -1. 63fe9d4f57SAlexey Dobriyan * @nr_calls: Records the number of notifications sent. Don't care 64fe9d4f57SAlexey Dobriyan * value of this field is NULL. 65fe9d4f57SAlexey Dobriyan * @returns: notifier_call_chain returns the value returned by the 66fe9d4f57SAlexey Dobriyan * last notifier function called. 67fe9d4f57SAlexey Dobriyan */ 68b40a2cb6SMasami Hiramatsu static int notifier_call_chain(struct notifier_block **nl, 69fe9d4f57SAlexey Dobriyan unsigned long val, void *v, 70fe9d4f57SAlexey Dobriyan int nr_to_call, int *nr_calls) 71fe9d4f57SAlexey Dobriyan { 72fe9d4f57SAlexey Dobriyan int ret = NOTIFY_DONE; 73fe9d4f57SAlexey Dobriyan struct notifier_block *nb, *next_nb; 74fe9d4f57SAlexey Dobriyan 75d11c563dSPaul E. McKenney nb = rcu_dereference_raw(*nl); 76fe9d4f57SAlexey Dobriyan 77fe9d4f57SAlexey Dobriyan while (nb && nr_to_call) { 78d11c563dSPaul E. McKenney next_nb = rcu_dereference_raw(nb->next); 791b2439dbSArjan van de Ven 801b2439dbSArjan van de Ven #ifdef CONFIG_DEBUG_NOTIFIERS 81ab7476cfSArjan van de Ven if (unlikely(!func_ptr_is_kernel_text(nb->notifier_call))) { 821b2439dbSArjan van de Ven WARN(1, "Invalid notifier called!"); 831b2439dbSArjan van de Ven nb = next_nb; 841b2439dbSArjan van de Ven continue; 851b2439dbSArjan van de Ven } 861b2439dbSArjan van de Ven #endif 87fe9d4f57SAlexey Dobriyan ret = nb->notifier_call(nb, val, v); 88fe9d4f57SAlexey Dobriyan 89fe9d4f57SAlexey Dobriyan if (nr_calls) 90fe9d4f57SAlexey Dobriyan (*nr_calls)++; 91fe9d4f57SAlexey Dobriyan 923e6dadedSViresh Kumar if (ret & NOTIFY_STOP_MASK) 93fe9d4f57SAlexey Dobriyan break; 94fe9d4f57SAlexey Dobriyan nb = next_nb; 95fe9d4f57SAlexey Dobriyan nr_to_call--; 96fe9d4f57SAlexey Dobriyan } 97fe9d4f57SAlexey Dobriyan return ret; 98fe9d4f57SAlexey Dobriyan } 99b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notifier_call_chain); 100fe9d4f57SAlexey Dobriyan 10170d93298SPeter Zijlstra /** 10270d93298SPeter Zijlstra * notifier_call_chain_robust - Inform the registered notifiers about an event 10370d93298SPeter Zijlstra * and rollback on error. 10470d93298SPeter Zijlstra * @nl: Pointer to head of the blocking notifier chain 10570d93298SPeter Zijlstra * @val_up: Value passed unmodified to the notifier function 10670d93298SPeter Zijlstra * @val_down: Value passed unmodified to the notifier function when recovering 10770d93298SPeter Zijlstra * from an error on @val_up 10870d93298SPeter Zijlstra * @v Pointer passed unmodified to the notifier function 10970d93298SPeter Zijlstra * 11070d93298SPeter Zijlstra * NOTE: It is important the @nl chain doesn't change between the two 11170d93298SPeter Zijlstra * invocations of notifier_call_chain() such that we visit the 11270d93298SPeter Zijlstra * exact same notifier callbacks; this rules out any RCU usage. 11370d93298SPeter Zijlstra * 11470d93298SPeter Zijlstra * Returns: the return value of the @val_up call. 11570d93298SPeter Zijlstra */ 11670d93298SPeter Zijlstra static int notifier_call_chain_robust(struct notifier_block **nl, 11770d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, 11870d93298SPeter Zijlstra void *v) 11970d93298SPeter Zijlstra { 12070d93298SPeter Zijlstra int ret, nr = 0; 12170d93298SPeter Zijlstra 12270d93298SPeter Zijlstra ret = notifier_call_chain(nl, val_up, v, -1, &nr); 12370d93298SPeter Zijlstra if (ret & NOTIFY_STOP_MASK) 12470d93298SPeter Zijlstra notifier_call_chain(nl, val_down, v, nr-1, NULL); 12570d93298SPeter Zijlstra 12670d93298SPeter Zijlstra return ret; 12770d93298SPeter Zijlstra } 12870d93298SPeter Zijlstra 129fe9d4f57SAlexey Dobriyan /* 130fe9d4f57SAlexey Dobriyan * Atomic notifier chain routines. Registration and unregistration 131fe9d4f57SAlexey Dobriyan * use a spinlock, and call_chain is synchronized by RCU (no locks). 132fe9d4f57SAlexey Dobriyan */ 133fe9d4f57SAlexey Dobriyan 134fe9d4f57SAlexey Dobriyan /** 135fe9d4f57SAlexey Dobriyan * atomic_notifier_chain_register - Add notifier to an atomic notifier chain 136fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the atomic notifier chain 137fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 138fe9d4f57SAlexey Dobriyan * 139fe9d4f57SAlexey Dobriyan * Adds a notifier to an atomic notifier chain. 140fe9d4f57SAlexey Dobriyan * 1415abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 142fe9d4f57SAlexey Dobriyan */ 143fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_register(struct atomic_notifier_head *nh, 144fe9d4f57SAlexey Dobriyan struct notifier_block *n) 145fe9d4f57SAlexey Dobriyan { 146fe9d4f57SAlexey Dobriyan unsigned long flags; 147fe9d4f57SAlexey Dobriyan int ret; 148fe9d4f57SAlexey Dobriyan 149fe9d4f57SAlexey Dobriyan spin_lock_irqsave(&nh->lock, flags); 150*c82f898dSDmitry Osipenko ret = notifier_chain_register(&nh->head, n, false); 151fe9d4f57SAlexey Dobriyan spin_unlock_irqrestore(&nh->lock, flags); 152fe9d4f57SAlexey Dobriyan return ret; 153fe9d4f57SAlexey Dobriyan } 154fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_register); 155fe9d4f57SAlexey Dobriyan 156fe9d4f57SAlexey Dobriyan /** 157*c82f898dSDmitry Osipenko * atomic_notifier_chain_register_unique_prio - Add notifier to an atomic notifier chain 158*c82f898dSDmitry Osipenko * @nh: Pointer to head of the atomic notifier chain 159*c82f898dSDmitry Osipenko * @n: New entry in notifier chain 160*c82f898dSDmitry Osipenko * 161*c82f898dSDmitry Osipenko * Adds a notifier to an atomic notifier chain if there is no other 162*c82f898dSDmitry Osipenko * notifier registered using the same priority. 163*c82f898dSDmitry Osipenko * 164*c82f898dSDmitry Osipenko * Returns 0 on success, %-EEXIST or %-EBUSY on error. 165*c82f898dSDmitry Osipenko */ 166*c82f898dSDmitry Osipenko int atomic_notifier_chain_register_unique_prio(struct atomic_notifier_head *nh, 167*c82f898dSDmitry Osipenko struct notifier_block *n) 168*c82f898dSDmitry Osipenko { 169*c82f898dSDmitry Osipenko unsigned long flags; 170*c82f898dSDmitry Osipenko int ret; 171*c82f898dSDmitry Osipenko 172*c82f898dSDmitry Osipenko spin_lock_irqsave(&nh->lock, flags); 173*c82f898dSDmitry Osipenko ret = notifier_chain_register(&nh->head, n, true); 174*c82f898dSDmitry Osipenko spin_unlock_irqrestore(&nh->lock, flags); 175*c82f898dSDmitry Osipenko return ret; 176*c82f898dSDmitry Osipenko } 177*c82f898dSDmitry Osipenko EXPORT_SYMBOL_GPL(atomic_notifier_chain_register_unique_prio); 178*c82f898dSDmitry Osipenko 179*c82f898dSDmitry Osipenko /** 180fe9d4f57SAlexey Dobriyan * atomic_notifier_chain_unregister - Remove notifier from an atomic notifier chain 181fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the atomic notifier chain 182fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 183fe9d4f57SAlexey Dobriyan * 184fe9d4f57SAlexey Dobriyan * Removes a notifier from an atomic notifier chain. 185fe9d4f57SAlexey Dobriyan * 186fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 187fe9d4f57SAlexey Dobriyan */ 188fe9d4f57SAlexey Dobriyan int atomic_notifier_chain_unregister(struct atomic_notifier_head *nh, 189fe9d4f57SAlexey Dobriyan struct notifier_block *n) 190fe9d4f57SAlexey Dobriyan { 191fe9d4f57SAlexey Dobriyan unsigned long flags; 192fe9d4f57SAlexey Dobriyan int ret; 193fe9d4f57SAlexey Dobriyan 194fe9d4f57SAlexey Dobriyan spin_lock_irqsave(&nh->lock, flags); 195fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 196fe9d4f57SAlexey Dobriyan spin_unlock_irqrestore(&nh->lock, flags); 197fe9d4f57SAlexey Dobriyan synchronize_rcu(); 198fe9d4f57SAlexey Dobriyan return ret; 199fe9d4f57SAlexey Dobriyan } 200fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_chain_unregister); 201fe9d4f57SAlexey Dobriyan 202fe9d4f57SAlexey Dobriyan /** 20370d93298SPeter Zijlstra * atomic_notifier_call_chain - Call functions in an atomic notifier chain 204fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the atomic notifier chain 205fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 206fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 207fe9d4f57SAlexey Dobriyan * 208fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 209fe9d4f57SAlexey Dobriyan * run in an atomic context, so they must not block. 210fe9d4f57SAlexey Dobriyan * This routine uses RCU to synchronize with changes to the chain. 211fe9d4f57SAlexey Dobriyan * 212fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 213fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then atomic_notifier_call_chain() 214fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 215fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 216fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 217fe9d4f57SAlexey Dobriyan * of the last notifier function called. 218fe9d4f57SAlexey Dobriyan */ 21970d93298SPeter Zijlstra int atomic_notifier_call_chain(struct atomic_notifier_head *nh, 22070d93298SPeter Zijlstra unsigned long val, void *v) 221fe9d4f57SAlexey Dobriyan { 222fe9d4f57SAlexey Dobriyan int ret; 223fe9d4f57SAlexey Dobriyan 224fe9d4f57SAlexey Dobriyan rcu_read_lock(); 22570d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 226fe9d4f57SAlexey Dobriyan rcu_read_unlock(); 227fe9d4f57SAlexey Dobriyan 22870d93298SPeter Zijlstra return ret; 229fe9d4f57SAlexey Dobriyan } 230fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(atomic_notifier_call_chain); 231b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(atomic_notifier_call_chain); 232fe9d4f57SAlexey Dobriyan 23313dfd97aSDmitry Osipenko /** 23413dfd97aSDmitry Osipenko * atomic_notifier_call_chain_is_empty - Check whether notifier chain is empty 23513dfd97aSDmitry Osipenko * @nh: Pointer to head of the atomic notifier chain 23613dfd97aSDmitry Osipenko * 23713dfd97aSDmitry Osipenko * Checks whether notifier chain is empty. 23813dfd97aSDmitry Osipenko * 23913dfd97aSDmitry Osipenko * Returns true is notifier chain is empty, false otherwise. 24013dfd97aSDmitry Osipenko */ 24113dfd97aSDmitry Osipenko bool atomic_notifier_call_chain_is_empty(struct atomic_notifier_head *nh) 24213dfd97aSDmitry Osipenko { 24313dfd97aSDmitry Osipenko return !rcu_access_pointer(nh->head); 24413dfd97aSDmitry Osipenko } 24513dfd97aSDmitry Osipenko 246fe9d4f57SAlexey Dobriyan /* 247fe9d4f57SAlexey Dobriyan * Blocking notifier chain routines. All access to the chain is 248fe9d4f57SAlexey Dobriyan * synchronized by an rwsem. 249fe9d4f57SAlexey Dobriyan */ 250fe9d4f57SAlexey Dobriyan 251*c82f898dSDmitry Osipenko static int __blocking_notifier_chain_register(struct blocking_notifier_head *nh, 252*c82f898dSDmitry Osipenko struct notifier_block *n, 253*c82f898dSDmitry Osipenko bool unique_priority) 254*c82f898dSDmitry Osipenko { 255*c82f898dSDmitry Osipenko int ret; 256*c82f898dSDmitry Osipenko 257*c82f898dSDmitry Osipenko /* 258*c82f898dSDmitry Osipenko * This code gets used during boot-up, when task switching is 259*c82f898dSDmitry Osipenko * not yet working and interrupts must remain disabled. At 260*c82f898dSDmitry Osipenko * such times we must not call down_write(). 261*c82f898dSDmitry Osipenko */ 262*c82f898dSDmitry Osipenko if (unlikely(system_state == SYSTEM_BOOTING)) 263*c82f898dSDmitry Osipenko return notifier_chain_register(&nh->head, n, unique_priority); 264*c82f898dSDmitry Osipenko 265*c82f898dSDmitry Osipenko down_write(&nh->rwsem); 266*c82f898dSDmitry Osipenko ret = notifier_chain_register(&nh->head, n, unique_priority); 267*c82f898dSDmitry Osipenko up_write(&nh->rwsem); 268*c82f898dSDmitry Osipenko return ret; 269*c82f898dSDmitry Osipenko } 270*c82f898dSDmitry Osipenko 271fe9d4f57SAlexey Dobriyan /** 272fe9d4f57SAlexey Dobriyan * blocking_notifier_chain_register - Add notifier to a blocking notifier chain 273fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 274fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 275fe9d4f57SAlexey Dobriyan * 276fe9d4f57SAlexey Dobriyan * Adds a notifier to a blocking notifier chain. 277fe9d4f57SAlexey Dobriyan * Must be called in process context. 278fe9d4f57SAlexey Dobriyan * 2795abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 280fe9d4f57SAlexey Dobriyan */ 281fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh, 282fe9d4f57SAlexey Dobriyan struct notifier_block *n) 283fe9d4f57SAlexey Dobriyan { 284*c82f898dSDmitry Osipenko return __blocking_notifier_chain_register(nh, n, false); 285fe9d4f57SAlexey Dobriyan } 286fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); 287fe9d4f57SAlexey Dobriyan 288fe9d4f57SAlexey Dobriyan /** 289*c82f898dSDmitry Osipenko * blocking_notifier_chain_register_unique_prio - Add notifier to a blocking notifier chain 290*c82f898dSDmitry Osipenko * @nh: Pointer to head of the blocking notifier chain 291*c82f898dSDmitry Osipenko * @n: New entry in notifier chain 292*c82f898dSDmitry Osipenko * 293*c82f898dSDmitry Osipenko * Adds a notifier to an blocking notifier chain if there is no other 294*c82f898dSDmitry Osipenko * notifier registered using the same priority. 295*c82f898dSDmitry Osipenko * 296*c82f898dSDmitry Osipenko * Returns 0 on success, %-EEXIST or %-EBUSY on error. 297*c82f898dSDmitry Osipenko */ 298*c82f898dSDmitry Osipenko int blocking_notifier_chain_register_unique_prio(struct blocking_notifier_head *nh, 299*c82f898dSDmitry Osipenko struct notifier_block *n) 300*c82f898dSDmitry Osipenko { 301*c82f898dSDmitry Osipenko return __blocking_notifier_chain_register(nh, n, true); 302*c82f898dSDmitry Osipenko } 303*c82f898dSDmitry Osipenko EXPORT_SYMBOL_GPL(blocking_notifier_chain_register_unique_prio); 304*c82f898dSDmitry Osipenko 305*c82f898dSDmitry Osipenko /** 306fe9d4f57SAlexey Dobriyan * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain 307fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 308fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 309fe9d4f57SAlexey Dobriyan * 310fe9d4f57SAlexey Dobriyan * Removes a notifier from a blocking notifier chain. 311fe9d4f57SAlexey Dobriyan * Must be called from process context. 312fe9d4f57SAlexey Dobriyan * 313fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 314fe9d4f57SAlexey Dobriyan */ 315fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, 316fe9d4f57SAlexey Dobriyan struct notifier_block *n) 317fe9d4f57SAlexey Dobriyan { 318fe9d4f57SAlexey Dobriyan int ret; 319fe9d4f57SAlexey Dobriyan 320fe9d4f57SAlexey Dobriyan /* 321fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 322fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 323fe9d4f57SAlexey Dobriyan * such times we must not call down_write(). 324fe9d4f57SAlexey Dobriyan */ 325fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 326fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 327fe9d4f57SAlexey Dobriyan 328fe9d4f57SAlexey Dobriyan down_write(&nh->rwsem); 329fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 330fe9d4f57SAlexey Dobriyan up_write(&nh->rwsem); 331fe9d4f57SAlexey Dobriyan return ret; 332fe9d4f57SAlexey Dobriyan } 333fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister); 334fe9d4f57SAlexey Dobriyan 33570d93298SPeter Zijlstra int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh, 33670d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, void *v) 33770d93298SPeter Zijlstra { 33870d93298SPeter Zijlstra int ret = NOTIFY_DONE; 33970d93298SPeter Zijlstra 34070d93298SPeter Zijlstra /* 34170d93298SPeter Zijlstra * We check the head outside the lock, but if this access is 34270d93298SPeter Zijlstra * racy then it does not matter what the result of the test 34370d93298SPeter Zijlstra * is, we re-check the list after having taken the lock anyway: 34470d93298SPeter Zijlstra */ 34570d93298SPeter Zijlstra if (rcu_access_pointer(nh->head)) { 34670d93298SPeter Zijlstra down_read(&nh->rwsem); 34770d93298SPeter Zijlstra ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v); 34870d93298SPeter Zijlstra up_read(&nh->rwsem); 34970d93298SPeter Zijlstra } 35070d93298SPeter Zijlstra return ret; 35170d93298SPeter Zijlstra } 35270d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust); 35370d93298SPeter Zijlstra 354fe9d4f57SAlexey Dobriyan /** 35570d93298SPeter Zijlstra * blocking_notifier_call_chain - Call functions in a blocking notifier chain 356fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 357fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 358fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 359fe9d4f57SAlexey Dobriyan * 360fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 361fe9d4f57SAlexey Dobriyan * run in a process context, so they are allowed to block. 362fe9d4f57SAlexey Dobriyan * 363fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 364fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain() 365fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 366fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 367fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 368fe9d4f57SAlexey Dobriyan * of the last notifier function called. 369fe9d4f57SAlexey Dobriyan */ 37070d93298SPeter Zijlstra int blocking_notifier_call_chain(struct blocking_notifier_head *nh, 37170d93298SPeter Zijlstra unsigned long val, void *v) 372fe9d4f57SAlexey Dobriyan { 373fe9d4f57SAlexey Dobriyan int ret = NOTIFY_DONE; 374fe9d4f57SAlexey Dobriyan 375fe9d4f57SAlexey Dobriyan /* 376fe9d4f57SAlexey Dobriyan * We check the head outside the lock, but if this access is 377fe9d4f57SAlexey Dobriyan * racy then it does not matter what the result of the test 378fe9d4f57SAlexey Dobriyan * is, we re-check the list after having taken the lock anyway: 379fe9d4f57SAlexey Dobriyan */ 3808857563bSPaul E. McKenney if (rcu_access_pointer(nh->head)) { 381fe9d4f57SAlexey Dobriyan down_read(&nh->rwsem); 38270d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 383fe9d4f57SAlexey Dobriyan up_read(&nh->rwsem); 384fe9d4f57SAlexey Dobriyan } 385fe9d4f57SAlexey Dobriyan return ret; 386fe9d4f57SAlexey Dobriyan } 387fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); 388fe9d4f57SAlexey Dobriyan 389fe9d4f57SAlexey Dobriyan /* 390fe9d4f57SAlexey Dobriyan * Raw notifier chain routines. There is no protection; 391fe9d4f57SAlexey Dobriyan * the caller must provide it. Use at your own risk! 392fe9d4f57SAlexey Dobriyan */ 393fe9d4f57SAlexey Dobriyan 394fe9d4f57SAlexey Dobriyan /** 395fe9d4f57SAlexey Dobriyan * raw_notifier_chain_register - Add notifier to a raw notifier chain 396fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 397fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 398fe9d4f57SAlexey Dobriyan * 399fe9d4f57SAlexey Dobriyan * Adds a notifier to a raw notifier chain. 400fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 401fe9d4f57SAlexey Dobriyan * 4025abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 403fe9d4f57SAlexey Dobriyan */ 404fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh, 405fe9d4f57SAlexey Dobriyan struct notifier_block *n) 406fe9d4f57SAlexey Dobriyan { 407*c82f898dSDmitry Osipenko return notifier_chain_register(&nh->head, n, false); 408fe9d4f57SAlexey Dobriyan } 409fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register); 410fe9d4f57SAlexey Dobriyan 411fe9d4f57SAlexey Dobriyan /** 412fe9d4f57SAlexey Dobriyan * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain 413fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 414fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 415fe9d4f57SAlexey Dobriyan * 416fe9d4f57SAlexey Dobriyan * Removes a notifier from a raw notifier chain. 417fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 418fe9d4f57SAlexey Dobriyan * 419fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 420fe9d4f57SAlexey Dobriyan */ 421fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh, 422fe9d4f57SAlexey Dobriyan struct notifier_block *n) 423fe9d4f57SAlexey Dobriyan { 424fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 425fe9d4f57SAlexey Dobriyan } 426fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister); 427fe9d4f57SAlexey Dobriyan 42870d93298SPeter Zijlstra int raw_notifier_call_chain_robust(struct raw_notifier_head *nh, 42970d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, void *v) 43070d93298SPeter Zijlstra { 43170d93298SPeter Zijlstra return notifier_call_chain_robust(&nh->head, val_up, val_down, v); 43270d93298SPeter Zijlstra } 43370d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust); 43470d93298SPeter Zijlstra 435fe9d4f57SAlexey Dobriyan /** 43670d93298SPeter Zijlstra * raw_notifier_call_chain - Call functions in a raw notifier chain 437fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 438fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 439fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 440fe9d4f57SAlexey Dobriyan * 441fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 442fe9d4f57SAlexey Dobriyan * run in an undefined context. 443fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 444fe9d4f57SAlexey Dobriyan * 445fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 446fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then raw_notifier_call_chain() 447fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 448fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 449fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 450fe9d4f57SAlexey Dobriyan * of the last notifier function called. 451fe9d4f57SAlexey Dobriyan */ 452fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh, 453fe9d4f57SAlexey Dobriyan unsigned long val, void *v) 454fe9d4f57SAlexey Dobriyan { 45570d93298SPeter Zijlstra return notifier_call_chain(&nh->head, val, v, -1, NULL); 456fe9d4f57SAlexey Dobriyan } 457fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain); 458fe9d4f57SAlexey Dobriyan 45983fe27eaSPranith Kumar #ifdef CONFIG_SRCU 460fe9d4f57SAlexey Dobriyan /* 461fe9d4f57SAlexey Dobriyan * SRCU notifier chain routines. Registration and unregistration 462fe9d4f57SAlexey Dobriyan * use a mutex, and call_chain is synchronized by SRCU (no locks). 463fe9d4f57SAlexey Dobriyan */ 464fe9d4f57SAlexey Dobriyan 465fe9d4f57SAlexey Dobriyan /** 466fe9d4f57SAlexey Dobriyan * srcu_notifier_chain_register - Add notifier to an SRCU notifier chain 467fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 468fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 469fe9d4f57SAlexey Dobriyan * 470fe9d4f57SAlexey Dobriyan * Adds a notifier to an SRCU notifier chain. 471fe9d4f57SAlexey Dobriyan * Must be called in process context. 472fe9d4f57SAlexey Dobriyan * 4735abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 474fe9d4f57SAlexey Dobriyan */ 475fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh, 476fe9d4f57SAlexey Dobriyan struct notifier_block *n) 477fe9d4f57SAlexey Dobriyan { 478fe9d4f57SAlexey Dobriyan int ret; 479fe9d4f57SAlexey Dobriyan 480fe9d4f57SAlexey Dobriyan /* 481fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 482fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 483fe9d4f57SAlexey Dobriyan * such times we must not call mutex_lock(). 484fe9d4f57SAlexey Dobriyan */ 485fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 486*c82f898dSDmitry Osipenko return notifier_chain_register(&nh->head, n, false); 487fe9d4f57SAlexey Dobriyan 488fe9d4f57SAlexey Dobriyan mutex_lock(&nh->mutex); 489*c82f898dSDmitry Osipenko ret = notifier_chain_register(&nh->head, n, false); 490fe9d4f57SAlexey Dobriyan mutex_unlock(&nh->mutex); 491fe9d4f57SAlexey Dobriyan return ret; 492fe9d4f57SAlexey Dobriyan } 493fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register); 494fe9d4f57SAlexey Dobriyan 495fe9d4f57SAlexey Dobriyan /** 496fe9d4f57SAlexey Dobriyan * srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain 497fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 498fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 499fe9d4f57SAlexey Dobriyan * 500fe9d4f57SAlexey Dobriyan * Removes a notifier from an SRCU notifier chain. 501fe9d4f57SAlexey Dobriyan * Must be called from process context. 502fe9d4f57SAlexey Dobriyan * 503fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 504fe9d4f57SAlexey Dobriyan */ 505fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, 506fe9d4f57SAlexey Dobriyan struct notifier_block *n) 507fe9d4f57SAlexey Dobriyan { 508fe9d4f57SAlexey Dobriyan int ret; 509fe9d4f57SAlexey Dobriyan 510fe9d4f57SAlexey Dobriyan /* 511fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 512fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 513fe9d4f57SAlexey Dobriyan * such times we must not call mutex_lock(). 514fe9d4f57SAlexey Dobriyan */ 515fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 516fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 517fe9d4f57SAlexey Dobriyan 518fe9d4f57SAlexey Dobriyan mutex_lock(&nh->mutex); 519fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 520fe9d4f57SAlexey Dobriyan mutex_unlock(&nh->mutex); 521fe9d4f57SAlexey Dobriyan synchronize_srcu(&nh->srcu); 522fe9d4f57SAlexey Dobriyan return ret; 523fe9d4f57SAlexey Dobriyan } 524fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister); 525fe9d4f57SAlexey Dobriyan 526fe9d4f57SAlexey Dobriyan /** 52770d93298SPeter Zijlstra * srcu_notifier_call_chain - Call functions in an SRCU notifier chain 528fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 529fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 530fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 531fe9d4f57SAlexey Dobriyan * 532fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 533fe9d4f57SAlexey Dobriyan * run in a process context, so they are allowed to block. 534fe9d4f57SAlexey Dobriyan * 535fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 536fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then srcu_notifier_call_chain() 537fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 538fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 539fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 540fe9d4f57SAlexey Dobriyan * of the last notifier function called. 541fe9d4f57SAlexey Dobriyan */ 54270d93298SPeter Zijlstra int srcu_notifier_call_chain(struct srcu_notifier_head *nh, 54370d93298SPeter Zijlstra unsigned long val, void *v) 544fe9d4f57SAlexey Dobriyan { 545fe9d4f57SAlexey Dobriyan int ret; 546fe9d4f57SAlexey Dobriyan int idx; 547fe9d4f57SAlexey Dobriyan 548fe9d4f57SAlexey Dobriyan idx = srcu_read_lock(&nh->srcu); 54970d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 550fe9d4f57SAlexey Dobriyan srcu_read_unlock(&nh->srcu, idx); 551fe9d4f57SAlexey Dobriyan return ret; 552fe9d4f57SAlexey Dobriyan } 553fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain); 554fe9d4f57SAlexey Dobriyan 555fe9d4f57SAlexey Dobriyan /** 556fe9d4f57SAlexey Dobriyan * srcu_init_notifier_head - Initialize an SRCU notifier head 557fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the srcu notifier chain 558fe9d4f57SAlexey Dobriyan * 559fe9d4f57SAlexey Dobriyan * Unlike other sorts of notifier heads, SRCU notifier heads require 560fe9d4f57SAlexey Dobriyan * dynamic initialization. Be sure to call this routine before 561fe9d4f57SAlexey Dobriyan * calling any of the other SRCU notifier routines for this head. 562fe9d4f57SAlexey Dobriyan * 563fe9d4f57SAlexey Dobriyan * If an SRCU notifier head is deallocated, it must first be cleaned 564fe9d4f57SAlexey Dobriyan * up by calling srcu_cleanup_notifier_head(). Otherwise the head's 565fe9d4f57SAlexey Dobriyan * per-cpu data (used by the SRCU mechanism) will leak. 566fe9d4f57SAlexey Dobriyan */ 567fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh) 568fe9d4f57SAlexey Dobriyan { 569fe9d4f57SAlexey Dobriyan mutex_init(&nh->mutex); 570fe9d4f57SAlexey Dobriyan if (init_srcu_struct(&nh->srcu) < 0) 571fe9d4f57SAlexey Dobriyan BUG(); 572fe9d4f57SAlexey Dobriyan nh->head = NULL; 573fe9d4f57SAlexey Dobriyan } 574fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head); 575fe9d4f57SAlexey Dobriyan 57683fe27eaSPranith Kumar #endif /* CONFIG_SRCU */ 57783fe27eaSPranith Kumar 578fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain); 579fe9d4f57SAlexey Dobriyan 580b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str, 581fe9d4f57SAlexey Dobriyan struct pt_regs *regs, long err, int trap, int sig) 582fe9d4f57SAlexey Dobriyan { 583fe9d4f57SAlexey Dobriyan struct die_args args = { 584fe9d4f57SAlexey Dobriyan .regs = regs, 585fe9d4f57SAlexey Dobriyan .str = str, 586fe9d4f57SAlexey Dobriyan .err = err, 587fe9d4f57SAlexey Dobriyan .trapnr = trap, 588fe9d4f57SAlexey Dobriyan .signr = sig, 589fe9d4f57SAlexey Dobriyan 590fe9d4f57SAlexey Dobriyan }; 5915778077dSLinus Torvalds RCU_LOCKDEP_WARN(!rcu_is_watching(), 592e727c7d7SAndy Lutomirski "notify_die called but RCU thinks we're quiescent"); 593fe9d4f57SAlexey Dobriyan return atomic_notifier_call_chain(&die_chain, val, &args); 594fe9d4f57SAlexey Dobriyan } 595b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die); 596fe9d4f57SAlexey Dobriyan 597fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb) 598fe9d4f57SAlexey Dobriyan { 599fe9d4f57SAlexey Dobriyan return atomic_notifier_chain_register(&die_chain, nb); 600fe9d4f57SAlexey Dobriyan } 601fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier); 602fe9d4f57SAlexey Dobriyan 603fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb) 604fe9d4f57SAlexey Dobriyan { 605fe9d4f57SAlexey Dobriyan return atomic_notifier_chain_unregister(&die_chain, nb); 606fe9d4f57SAlexey Dobriyan } 607fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier); 608