1*457c8996SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only 27c68af6eSAvi Kivity 37c68af6eSAvi Kivity #include <linux/user-return-notifier.h> 47c68af6eSAvi Kivity #include <linux/percpu.h> 57c68af6eSAvi Kivity #include <linux/sched.h> 69984de1aSPaul Gortmaker #include <linux/export.h> 77c68af6eSAvi Kivity 87c68af6eSAvi Kivity static DEFINE_PER_CPU(struct hlist_head, return_notifier_list); 97c68af6eSAvi Kivity 107c68af6eSAvi Kivity /* 117c68af6eSAvi Kivity * Request a notification when the current cpu returns to userspace. Must be 127c68af6eSAvi Kivity * called in atomic context. The notifier will also be called in atomic 137c68af6eSAvi Kivity * context. 147c68af6eSAvi Kivity */ user_return_notifier_register(struct user_return_notifier * urn)157c68af6eSAvi Kivityvoid user_return_notifier_register(struct user_return_notifier *urn) 167c68af6eSAvi Kivity { 177c68af6eSAvi Kivity set_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY); 184a32fea9SChristoph Lameter hlist_add_head(&urn->link, this_cpu_ptr(&return_notifier_list)); 197c68af6eSAvi Kivity } 207c68af6eSAvi Kivity EXPORT_SYMBOL_GPL(user_return_notifier_register); 217c68af6eSAvi Kivity 227c68af6eSAvi Kivity /* 237c68af6eSAvi Kivity * Removes a registered user return notifier. Must be called from atomic 2425985edcSLucas De Marchi * context, and from the same cpu registration occurred in. 257c68af6eSAvi Kivity */ user_return_notifier_unregister(struct user_return_notifier * urn)267c68af6eSAvi Kivityvoid user_return_notifier_unregister(struct user_return_notifier *urn) 277c68af6eSAvi Kivity { 287c68af6eSAvi Kivity hlist_del(&urn->link); 294a32fea9SChristoph Lameter if (hlist_empty(this_cpu_ptr(&return_notifier_list))) 307c68af6eSAvi Kivity clear_tsk_thread_flag(current, TIF_USER_RETURN_NOTIFY); 317c68af6eSAvi Kivity } 327c68af6eSAvi Kivity EXPORT_SYMBOL_GPL(user_return_notifier_unregister); 337c68af6eSAvi Kivity 347c68af6eSAvi Kivity /* Calls registered user return notifiers */ fire_user_return_notifiers(void)357c68af6eSAvi Kivityvoid fire_user_return_notifiers(void) 367c68af6eSAvi Kivity { 377c68af6eSAvi Kivity struct user_return_notifier *urn; 38b67bfe0dSSasha Levin struct hlist_node *tmp2; 397c68af6eSAvi Kivity struct hlist_head *head; 407c68af6eSAvi Kivity 417c68af6eSAvi Kivity head = &get_cpu_var(return_notifier_list); 42b67bfe0dSSasha Levin hlist_for_each_entry_safe(urn, tmp2, head, link) 437c68af6eSAvi Kivity urn->on_user_return(urn); 443c912b6eSStephen Rothwell put_cpu_var(return_notifier_list); 457c68af6eSAvi Kivity } 46