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)) { 27*5abb065dSBorislav Petkov WARN(1, "notifier callback %ps already registered", 28*5abb065dSBorislav Petkov n->notifier_call); 29*5abb065dSBorislav 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 * 138*5abb065dSBorislav 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 207fe9d4f57SAlexey Dobriyan /* 208fe9d4f57SAlexey Dobriyan * Blocking notifier chain routines. All access to the chain is 209fe9d4f57SAlexey Dobriyan * synchronized by an rwsem. 210fe9d4f57SAlexey Dobriyan */ 211fe9d4f57SAlexey Dobriyan 212fe9d4f57SAlexey Dobriyan /** 213fe9d4f57SAlexey Dobriyan * blocking_notifier_chain_register - Add notifier to a blocking notifier chain 214fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 215fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 216fe9d4f57SAlexey Dobriyan * 217fe9d4f57SAlexey Dobriyan * Adds a notifier to a blocking notifier chain. 218fe9d4f57SAlexey Dobriyan * Must be called in process context. 219fe9d4f57SAlexey Dobriyan * 220*5abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 221fe9d4f57SAlexey Dobriyan */ 222fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_register(struct blocking_notifier_head *nh, 223fe9d4f57SAlexey Dobriyan struct notifier_block *n) 224fe9d4f57SAlexey Dobriyan { 225fe9d4f57SAlexey Dobriyan int ret; 226fe9d4f57SAlexey Dobriyan 227fe9d4f57SAlexey Dobriyan /* 228fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 229fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 230fe9d4f57SAlexey Dobriyan * such times we must not call down_write(). 231fe9d4f57SAlexey Dobriyan */ 232fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 233fe9d4f57SAlexey Dobriyan return notifier_chain_register(&nh->head, n); 234fe9d4f57SAlexey Dobriyan 235fe9d4f57SAlexey Dobriyan down_write(&nh->rwsem); 236fe9d4f57SAlexey Dobriyan ret = notifier_chain_register(&nh->head, n); 237fe9d4f57SAlexey Dobriyan up_write(&nh->rwsem); 238fe9d4f57SAlexey Dobriyan return ret; 239fe9d4f57SAlexey Dobriyan } 240fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_register); 241fe9d4f57SAlexey Dobriyan 242fe9d4f57SAlexey Dobriyan /** 243fe9d4f57SAlexey Dobriyan * blocking_notifier_chain_unregister - Remove notifier from a blocking notifier chain 244fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 245fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 246fe9d4f57SAlexey Dobriyan * 247fe9d4f57SAlexey Dobriyan * Removes a notifier from a blocking notifier chain. 248fe9d4f57SAlexey Dobriyan * Must be called from process context. 249fe9d4f57SAlexey Dobriyan * 250fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 251fe9d4f57SAlexey Dobriyan */ 252fe9d4f57SAlexey Dobriyan int blocking_notifier_chain_unregister(struct blocking_notifier_head *nh, 253fe9d4f57SAlexey Dobriyan struct notifier_block *n) 254fe9d4f57SAlexey Dobriyan { 255fe9d4f57SAlexey Dobriyan int ret; 256fe9d4f57SAlexey Dobriyan 257fe9d4f57SAlexey Dobriyan /* 258fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 259fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 260fe9d4f57SAlexey Dobriyan * such times we must not call down_write(). 261fe9d4f57SAlexey Dobriyan */ 262fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 263fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 264fe9d4f57SAlexey Dobriyan 265fe9d4f57SAlexey Dobriyan down_write(&nh->rwsem); 266fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 267fe9d4f57SAlexey Dobriyan up_write(&nh->rwsem); 268fe9d4f57SAlexey Dobriyan return ret; 269fe9d4f57SAlexey Dobriyan } 270fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_chain_unregister); 271fe9d4f57SAlexey Dobriyan 27270d93298SPeter Zijlstra int blocking_notifier_call_chain_robust(struct blocking_notifier_head *nh, 27370d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, void *v) 27470d93298SPeter Zijlstra { 27570d93298SPeter Zijlstra int ret = NOTIFY_DONE; 27670d93298SPeter Zijlstra 27770d93298SPeter Zijlstra /* 27870d93298SPeter Zijlstra * We check the head outside the lock, but if this access is 27970d93298SPeter Zijlstra * racy then it does not matter what the result of the test 28070d93298SPeter Zijlstra * is, we re-check the list after having taken the lock anyway: 28170d93298SPeter Zijlstra */ 28270d93298SPeter Zijlstra if (rcu_access_pointer(nh->head)) { 28370d93298SPeter Zijlstra down_read(&nh->rwsem); 28470d93298SPeter Zijlstra ret = notifier_call_chain_robust(&nh->head, val_up, val_down, v); 28570d93298SPeter Zijlstra up_read(&nh->rwsem); 28670d93298SPeter Zijlstra } 28770d93298SPeter Zijlstra return ret; 28870d93298SPeter Zijlstra } 28970d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(blocking_notifier_call_chain_robust); 29070d93298SPeter Zijlstra 291fe9d4f57SAlexey Dobriyan /** 29270d93298SPeter Zijlstra * blocking_notifier_call_chain - Call functions in a blocking notifier chain 293fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the blocking notifier chain 294fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 295fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 296fe9d4f57SAlexey Dobriyan * 297fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 298fe9d4f57SAlexey Dobriyan * run in a process context, so they are allowed to block. 299fe9d4f57SAlexey Dobriyan * 300fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 301fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then blocking_notifier_call_chain() 302fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 303fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 304fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 305fe9d4f57SAlexey Dobriyan * of the last notifier function called. 306fe9d4f57SAlexey Dobriyan */ 30770d93298SPeter Zijlstra int blocking_notifier_call_chain(struct blocking_notifier_head *nh, 30870d93298SPeter Zijlstra unsigned long val, void *v) 309fe9d4f57SAlexey Dobriyan { 310fe9d4f57SAlexey Dobriyan int ret = NOTIFY_DONE; 311fe9d4f57SAlexey Dobriyan 312fe9d4f57SAlexey Dobriyan /* 313fe9d4f57SAlexey Dobriyan * We check the head outside the lock, but if this access is 314fe9d4f57SAlexey Dobriyan * racy then it does not matter what the result of the test 315fe9d4f57SAlexey Dobriyan * is, we re-check the list after having taken the lock anyway: 316fe9d4f57SAlexey Dobriyan */ 3178857563bSPaul E. McKenney if (rcu_access_pointer(nh->head)) { 318fe9d4f57SAlexey Dobriyan down_read(&nh->rwsem); 31970d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 320fe9d4f57SAlexey Dobriyan up_read(&nh->rwsem); 321fe9d4f57SAlexey Dobriyan } 322fe9d4f57SAlexey Dobriyan return ret; 323fe9d4f57SAlexey Dobriyan } 324fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(blocking_notifier_call_chain); 325fe9d4f57SAlexey Dobriyan 326fe9d4f57SAlexey Dobriyan /* 327fe9d4f57SAlexey Dobriyan * Raw notifier chain routines. There is no protection; 328fe9d4f57SAlexey Dobriyan * the caller must provide it. Use at your own risk! 329fe9d4f57SAlexey Dobriyan */ 330fe9d4f57SAlexey Dobriyan 331fe9d4f57SAlexey Dobriyan /** 332fe9d4f57SAlexey Dobriyan * raw_notifier_chain_register - Add notifier to a raw notifier chain 333fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 334fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 335fe9d4f57SAlexey Dobriyan * 336fe9d4f57SAlexey Dobriyan * Adds a notifier to a raw notifier chain. 337fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 338fe9d4f57SAlexey Dobriyan * 339*5abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 340fe9d4f57SAlexey Dobriyan */ 341fe9d4f57SAlexey Dobriyan int raw_notifier_chain_register(struct raw_notifier_head *nh, 342fe9d4f57SAlexey Dobriyan struct notifier_block *n) 343fe9d4f57SAlexey Dobriyan { 344fe9d4f57SAlexey Dobriyan return notifier_chain_register(&nh->head, n); 345fe9d4f57SAlexey Dobriyan } 346fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_register); 347fe9d4f57SAlexey Dobriyan 348fe9d4f57SAlexey Dobriyan /** 349fe9d4f57SAlexey Dobriyan * raw_notifier_chain_unregister - Remove notifier from a raw notifier chain 350fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 351fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 352fe9d4f57SAlexey Dobriyan * 353fe9d4f57SAlexey Dobriyan * Removes a notifier from a raw notifier chain. 354fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 355fe9d4f57SAlexey Dobriyan * 356fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 357fe9d4f57SAlexey Dobriyan */ 358fe9d4f57SAlexey Dobriyan int raw_notifier_chain_unregister(struct raw_notifier_head *nh, 359fe9d4f57SAlexey Dobriyan struct notifier_block *n) 360fe9d4f57SAlexey Dobriyan { 361fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 362fe9d4f57SAlexey Dobriyan } 363fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_chain_unregister); 364fe9d4f57SAlexey Dobriyan 36570d93298SPeter Zijlstra int raw_notifier_call_chain_robust(struct raw_notifier_head *nh, 36670d93298SPeter Zijlstra unsigned long val_up, unsigned long val_down, void *v) 36770d93298SPeter Zijlstra { 36870d93298SPeter Zijlstra return notifier_call_chain_robust(&nh->head, val_up, val_down, v); 36970d93298SPeter Zijlstra } 37070d93298SPeter Zijlstra EXPORT_SYMBOL_GPL(raw_notifier_call_chain_robust); 37170d93298SPeter Zijlstra 372fe9d4f57SAlexey Dobriyan /** 37370d93298SPeter Zijlstra * raw_notifier_call_chain - Call functions in a raw notifier chain 374fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the raw notifier chain 375fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 376fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 377fe9d4f57SAlexey Dobriyan * 378fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 379fe9d4f57SAlexey Dobriyan * run in an undefined context. 380fe9d4f57SAlexey Dobriyan * All locking must be provided by the caller. 381fe9d4f57SAlexey Dobriyan * 382fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 383fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then raw_notifier_call_chain() 384fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 385fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 386fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 387fe9d4f57SAlexey Dobriyan * of the last notifier function called. 388fe9d4f57SAlexey Dobriyan */ 389fe9d4f57SAlexey Dobriyan int raw_notifier_call_chain(struct raw_notifier_head *nh, 390fe9d4f57SAlexey Dobriyan unsigned long val, void *v) 391fe9d4f57SAlexey Dobriyan { 39270d93298SPeter Zijlstra return notifier_call_chain(&nh->head, val, v, -1, NULL); 393fe9d4f57SAlexey Dobriyan } 394fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(raw_notifier_call_chain); 395fe9d4f57SAlexey Dobriyan 39683fe27eaSPranith Kumar #ifdef CONFIG_SRCU 397fe9d4f57SAlexey Dobriyan /* 398fe9d4f57SAlexey Dobriyan * SRCU notifier chain routines. Registration and unregistration 399fe9d4f57SAlexey Dobriyan * use a mutex, and call_chain is synchronized by SRCU (no locks). 400fe9d4f57SAlexey Dobriyan */ 401fe9d4f57SAlexey Dobriyan 402fe9d4f57SAlexey Dobriyan /** 403fe9d4f57SAlexey Dobriyan * srcu_notifier_chain_register - Add notifier to an SRCU notifier chain 404fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 405fe9d4f57SAlexey Dobriyan * @n: New entry in notifier chain 406fe9d4f57SAlexey Dobriyan * 407fe9d4f57SAlexey Dobriyan * Adds a notifier to an SRCU notifier chain. 408fe9d4f57SAlexey Dobriyan * Must be called in process context. 409fe9d4f57SAlexey Dobriyan * 410*5abb065dSBorislav Petkov * Returns 0 on success, %-EEXIST on error. 411fe9d4f57SAlexey Dobriyan */ 412fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_register(struct srcu_notifier_head *nh, 413fe9d4f57SAlexey Dobriyan struct notifier_block *n) 414fe9d4f57SAlexey Dobriyan { 415fe9d4f57SAlexey Dobriyan int ret; 416fe9d4f57SAlexey Dobriyan 417fe9d4f57SAlexey Dobriyan /* 418fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 419fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 420fe9d4f57SAlexey Dobriyan * such times we must not call mutex_lock(). 421fe9d4f57SAlexey Dobriyan */ 422fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 423fe9d4f57SAlexey Dobriyan return notifier_chain_register(&nh->head, n); 424fe9d4f57SAlexey Dobriyan 425fe9d4f57SAlexey Dobriyan mutex_lock(&nh->mutex); 426fe9d4f57SAlexey Dobriyan ret = notifier_chain_register(&nh->head, n); 427fe9d4f57SAlexey Dobriyan mutex_unlock(&nh->mutex); 428fe9d4f57SAlexey Dobriyan return ret; 429fe9d4f57SAlexey Dobriyan } 430fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_register); 431fe9d4f57SAlexey Dobriyan 432fe9d4f57SAlexey Dobriyan /** 433fe9d4f57SAlexey Dobriyan * srcu_notifier_chain_unregister - Remove notifier from an SRCU notifier chain 434fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 435fe9d4f57SAlexey Dobriyan * @n: Entry to remove from notifier chain 436fe9d4f57SAlexey Dobriyan * 437fe9d4f57SAlexey Dobriyan * Removes a notifier from an SRCU notifier chain. 438fe9d4f57SAlexey Dobriyan * Must be called from process context. 439fe9d4f57SAlexey Dobriyan * 440fe9d4f57SAlexey Dobriyan * Returns zero on success or %-ENOENT on failure. 441fe9d4f57SAlexey Dobriyan */ 442fe9d4f57SAlexey Dobriyan int srcu_notifier_chain_unregister(struct srcu_notifier_head *nh, 443fe9d4f57SAlexey Dobriyan struct notifier_block *n) 444fe9d4f57SAlexey Dobriyan { 445fe9d4f57SAlexey Dobriyan int ret; 446fe9d4f57SAlexey Dobriyan 447fe9d4f57SAlexey Dobriyan /* 448fe9d4f57SAlexey Dobriyan * This code gets used during boot-up, when task switching is 449fe9d4f57SAlexey Dobriyan * not yet working and interrupts must remain disabled. At 450fe9d4f57SAlexey Dobriyan * such times we must not call mutex_lock(). 451fe9d4f57SAlexey Dobriyan */ 452fe9d4f57SAlexey Dobriyan if (unlikely(system_state == SYSTEM_BOOTING)) 453fe9d4f57SAlexey Dobriyan return notifier_chain_unregister(&nh->head, n); 454fe9d4f57SAlexey Dobriyan 455fe9d4f57SAlexey Dobriyan mutex_lock(&nh->mutex); 456fe9d4f57SAlexey Dobriyan ret = notifier_chain_unregister(&nh->head, n); 457fe9d4f57SAlexey Dobriyan mutex_unlock(&nh->mutex); 458fe9d4f57SAlexey Dobriyan synchronize_srcu(&nh->srcu); 459fe9d4f57SAlexey Dobriyan return ret; 460fe9d4f57SAlexey Dobriyan } 461fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_chain_unregister); 462fe9d4f57SAlexey Dobriyan 463fe9d4f57SAlexey Dobriyan /** 46470d93298SPeter Zijlstra * srcu_notifier_call_chain - Call functions in an SRCU notifier chain 465fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the SRCU notifier chain 466fe9d4f57SAlexey Dobriyan * @val: Value passed unmodified to notifier function 467fe9d4f57SAlexey Dobriyan * @v: Pointer passed unmodified to notifier function 468fe9d4f57SAlexey Dobriyan * 469fe9d4f57SAlexey Dobriyan * Calls each function in a notifier chain in turn. The functions 470fe9d4f57SAlexey Dobriyan * run in a process context, so they are allowed to block. 471fe9d4f57SAlexey Dobriyan * 472fe9d4f57SAlexey Dobriyan * If the return value of the notifier can be and'ed 473fe9d4f57SAlexey Dobriyan * with %NOTIFY_STOP_MASK then srcu_notifier_call_chain() 474fe9d4f57SAlexey Dobriyan * will return immediately, with the return value of 475fe9d4f57SAlexey Dobriyan * the notifier function which halted execution. 476fe9d4f57SAlexey Dobriyan * Otherwise the return value is the return value 477fe9d4f57SAlexey Dobriyan * of the last notifier function called. 478fe9d4f57SAlexey Dobriyan */ 47970d93298SPeter Zijlstra int srcu_notifier_call_chain(struct srcu_notifier_head *nh, 48070d93298SPeter Zijlstra unsigned long val, void *v) 481fe9d4f57SAlexey Dobriyan { 482fe9d4f57SAlexey Dobriyan int ret; 483fe9d4f57SAlexey Dobriyan int idx; 484fe9d4f57SAlexey Dobriyan 485fe9d4f57SAlexey Dobriyan idx = srcu_read_lock(&nh->srcu); 48670d93298SPeter Zijlstra ret = notifier_call_chain(&nh->head, val, v, -1, NULL); 487fe9d4f57SAlexey Dobriyan srcu_read_unlock(&nh->srcu, idx); 488fe9d4f57SAlexey Dobriyan return ret; 489fe9d4f57SAlexey Dobriyan } 490fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_notifier_call_chain); 491fe9d4f57SAlexey Dobriyan 492fe9d4f57SAlexey Dobriyan /** 493fe9d4f57SAlexey Dobriyan * srcu_init_notifier_head - Initialize an SRCU notifier head 494fe9d4f57SAlexey Dobriyan * @nh: Pointer to head of the srcu notifier chain 495fe9d4f57SAlexey Dobriyan * 496fe9d4f57SAlexey Dobriyan * Unlike other sorts of notifier heads, SRCU notifier heads require 497fe9d4f57SAlexey Dobriyan * dynamic initialization. Be sure to call this routine before 498fe9d4f57SAlexey Dobriyan * calling any of the other SRCU notifier routines for this head. 499fe9d4f57SAlexey Dobriyan * 500fe9d4f57SAlexey Dobriyan * If an SRCU notifier head is deallocated, it must first be cleaned 501fe9d4f57SAlexey Dobriyan * up by calling srcu_cleanup_notifier_head(). Otherwise the head's 502fe9d4f57SAlexey Dobriyan * per-cpu data (used by the SRCU mechanism) will leak. 503fe9d4f57SAlexey Dobriyan */ 504fe9d4f57SAlexey Dobriyan void srcu_init_notifier_head(struct srcu_notifier_head *nh) 505fe9d4f57SAlexey Dobriyan { 506fe9d4f57SAlexey Dobriyan mutex_init(&nh->mutex); 507fe9d4f57SAlexey Dobriyan if (init_srcu_struct(&nh->srcu) < 0) 508fe9d4f57SAlexey Dobriyan BUG(); 509fe9d4f57SAlexey Dobriyan nh->head = NULL; 510fe9d4f57SAlexey Dobriyan } 511fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(srcu_init_notifier_head); 512fe9d4f57SAlexey Dobriyan 51383fe27eaSPranith Kumar #endif /* CONFIG_SRCU */ 51483fe27eaSPranith Kumar 515fe9d4f57SAlexey Dobriyan static ATOMIC_NOTIFIER_HEAD(die_chain); 516fe9d4f57SAlexey Dobriyan 517b40a2cb6SMasami Hiramatsu int notrace notify_die(enum die_val val, const char *str, 518fe9d4f57SAlexey Dobriyan struct pt_regs *regs, long err, int trap, int sig) 519fe9d4f57SAlexey Dobriyan { 520fe9d4f57SAlexey Dobriyan struct die_args args = { 521fe9d4f57SAlexey Dobriyan .regs = regs, 522fe9d4f57SAlexey Dobriyan .str = str, 523fe9d4f57SAlexey Dobriyan .err = err, 524fe9d4f57SAlexey Dobriyan .trapnr = trap, 525fe9d4f57SAlexey Dobriyan .signr = sig, 526fe9d4f57SAlexey Dobriyan 527fe9d4f57SAlexey Dobriyan }; 5285778077dSLinus Torvalds RCU_LOCKDEP_WARN(!rcu_is_watching(), 529e727c7d7SAndy Lutomirski "notify_die called but RCU thinks we're quiescent"); 530fe9d4f57SAlexey Dobriyan return atomic_notifier_call_chain(&die_chain, val, &args); 531fe9d4f57SAlexey Dobriyan } 532b40a2cb6SMasami Hiramatsu NOKPROBE_SYMBOL(notify_die); 533fe9d4f57SAlexey Dobriyan 534fe9d4f57SAlexey Dobriyan int register_die_notifier(struct notifier_block *nb) 535fe9d4f57SAlexey Dobriyan { 536fe9d4f57SAlexey Dobriyan return atomic_notifier_chain_register(&die_chain, nb); 537fe9d4f57SAlexey Dobriyan } 538fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(register_die_notifier); 539fe9d4f57SAlexey Dobriyan 540fe9d4f57SAlexey Dobriyan int unregister_die_notifier(struct notifier_block *nb) 541fe9d4f57SAlexey Dobriyan { 542fe9d4f57SAlexey Dobriyan return atomic_notifier_chain_unregister(&die_chain, nb); 543fe9d4f57SAlexey Dobriyan } 544fe9d4f57SAlexey Dobriyan EXPORT_SYMBOL_GPL(unregister_die_notifier); 545