privcmd.c (c005e2f62f8421b13b9a31adb9db7281f1a19e68) privcmd.c (e997b357b13a7d95de31681fc54fcc34235fa527)
1// SPDX-License-Identifier: GPL-2.0-only
2/******************************************************************************
3 * privcmd.c
4 *
5 * Interface to privileged domain-0 commands.
6 *
7 * Copyright (c) 2002-2004, K A Fraser, B Dragovic
8 */
9
10#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
11
12#include <linux/eventfd.h>
13#include <linux/file.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/mutex.h>
17#include <linux/poll.h>
18#include <linux/sched.h>
19#include <linux/slab.h>
1// SPDX-License-Identifier: GPL-2.0-only
2/******************************************************************************
3 * privcmd.c
4 *
5 * Interface to privileged domain-0 commands.
6 *
7 * Copyright (c) 2002-2004, K A Fraser, B Dragovic
8 */
9
10#define pr_fmt(fmt) "xen:" KBUILD_MODNAME ": " fmt
11
12#include <linux/eventfd.h>
13#include <linux/file.h>
14#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/mutex.h>
17#include <linux/poll.h>
18#include <linux/sched.h>
19#include <linux/slab.h>
20#include <linux/srcu.h>
20#include <linux/string.h>
21#include <linux/workqueue.h>
22#include <linux/errno.h>
23#include <linux/mm.h>
24#include <linux/mman.h>
25#include <linux/uaccess.h>
26#include <linux/swap.h>
27#include <linux/highmem.h>

--- 809 unchanged lines hidden (view full) ---

837
838 return rc;
839}
840
841#ifdef CONFIG_XEN_PRIVCMD_IRQFD
842/* Irqfd support */
843static struct workqueue_struct *irqfd_cleanup_wq;
844static DEFINE_SPINLOCK(irqfds_lock);
21#include <linux/string.h>
22#include <linux/workqueue.h>
23#include <linux/errno.h>
24#include <linux/mm.h>
25#include <linux/mman.h>
26#include <linux/uaccess.h>
27#include <linux/swap.h>
28#include <linux/highmem.h>

--- 809 unchanged lines hidden (view full) ---

838
839 return rc;
840}
841
842#ifdef CONFIG_XEN_PRIVCMD_IRQFD
843/* Irqfd support */
844static struct workqueue_struct *irqfd_cleanup_wq;
845static DEFINE_SPINLOCK(irqfds_lock);
846DEFINE_STATIC_SRCU(irqfds_srcu);
845static LIST_HEAD(irqfds_list);
846
847struct privcmd_kernel_irqfd {
848 struct xen_dm_op_buf xbufs;
849 domid_t dom;
850 bool error;
851 struct eventfd_ctx *eventfd;
852 struct work_struct shutdown;

--- 11 unchanged lines hidden (view full) ---

864}
865
866static void irqfd_shutdown(struct work_struct *work)
867{
868 struct privcmd_kernel_irqfd *kirqfd =
869 container_of(work, struct privcmd_kernel_irqfd, shutdown);
870 u64 cnt;
871
847static LIST_HEAD(irqfds_list);
848
849struct privcmd_kernel_irqfd {
850 struct xen_dm_op_buf xbufs;
851 domid_t dom;
852 bool error;
853 struct eventfd_ctx *eventfd;
854 struct work_struct shutdown;

--- 11 unchanged lines hidden (view full) ---

866}
867
868static void irqfd_shutdown(struct work_struct *work)
869{
870 struct privcmd_kernel_irqfd *kirqfd =
871 container_of(work, struct privcmd_kernel_irqfd, shutdown);
872 u64 cnt;
873
874 /* Make sure irqfd has been initialized in assign path */
875 synchronize_srcu(&irqfds_srcu);
876
872 eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt);
873 eventfd_ctx_put(kirqfd->eventfd);
874 kfree(kirqfd);
875}
876
877static void irqfd_inject(struct privcmd_kernel_irqfd *kirqfd)
878{
879 u64 cnt;

--- 46 unchanged lines hidden (view full) ---

926
927static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
928{
929 struct privcmd_kernel_irqfd *kirqfd, *tmp;
930 unsigned long flags;
931 __poll_t events;
932 struct fd f;
933 void *dm_op;
877 eventfd_ctx_remove_wait_queue(kirqfd->eventfd, &kirqfd->wait, &cnt);
878 eventfd_ctx_put(kirqfd->eventfd);
879 kfree(kirqfd);
880}
881
882static void irqfd_inject(struct privcmd_kernel_irqfd *kirqfd)
883{
884 u64 cnt;

--- 46 unchanged lines hidden (view full) ---

931
932static int privcmd_irqfd_assign(struct privcmd_irqfd *irqfd)
933{
934 struct privcmd_kernel_irqfd *kirqfd, *tmp;
935 unsigned long flags;
936 __poll_t events;
937 struct fd f;
938 void *dm_op;
934 int ret;
939 int ret, idx;
935
936 kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
937 if (!kirqfd)
938 return -ENOMEM;
939 dm_op = kirqfd + 1;
940
941 if (copy_from_user(dm_op, u64_to_user_ptr(irqfd->dm_op), irqfd->size)) {
942 ret = -EFAULT;

--- 29 unchanged lines hidden (view full) ---

972 list_for_each_entry(tmp, &irqfds_list, list) {
973 if (kirqfd->eventfd == tmp->eventfd) {
974 ret = -EBUSY;
975 spin_unlock_irqrestore(&irqfds_lock, flags);
976 goto error_eventfd;
977 }
978 }
979
940
941 kirqfd = kzalloc(sizeof(*kirqfd) + irqfd->size, GFP_KERNEL);
942 if (!kirqfd)
943 return -ENOMEM;
944 dm_op = kirqfd + 1;
945
946 if (copy_from_user(dm_op, u64_to_user_ptr(irqfd->dm_op), irqfd->size)) {
947 ret = -EFAULT;

--- 29 unchanged lines hidden (view full) ---

977 list_for_each_entry(tmp, &irqfds_list, list) {
978 if (kirqfd->eventfd == tmp->eventfd) {
979 ret = -EBUSY;
980 spin_unlock_irqrestore(&irqfds_lock, flags);
981 goto error_eventfd;
982 }
983 }
984
985 idx = srcu_read_lock(&irqfds_srcu);
980 list_add_tail(&kirqfd->list, &irqfds_list);
981 spin_unlock_irqrestore(&irqfds_lock, flags);
982
983 /*
984 * Check if there was an event already pending on the eventfd before we
985 * registered, and trigger it as if we didn't miss it.
986 */
987 events = vfs_poll(f.file, &kirqfd->pt);
988 if (events & EPOLLIN)
989 irqfd_inject(kirqfd);
990
986 list_add_tail(&kirqfd->list, &irqfds_list);
987 spin_unlock_irqrestore(&irqfds_lock, flags);
988
989 /*
990 * Check if there was an event already pending on the eventfd before we
991 * registered, and trigger it as if we didn't miss it.
992 */
993 events = vfs_poll(f.file, &kirqfd->pt);
994 if (events & EPOLLIN)
995 irqfd_inject(kirqfd);
996
997 srcu_read_unlock(&irqfds_srcu, idx);
998
991 /*
992 * Do not drop the file until the kirqfd is fully initialized, otherwise
993 * we might race against the EPOLLHUP.
994 */
995 fdput(f);
996 return 0;
997
998error_eventfd:

--- 294 unchanged lines hidden ---
999 /*
1000 * Do not drop the file until the kirqfd is fully initialized, otherwise
1001 * we might race against the EPOLLHUP.
1002 */
1003 fdput(f);
1004 return 0;
1005
1006error_eventfd:

--- 294 unchanged lines hidden ---