cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

watch_queue.h (3915B)


      1// SPDX-License-Identifier: GPL-2.0
      2/* User-mappable watch queue
      3 *
      4 * Copyright (C) 2020 Red Hat, Inc. All Rights Reserved.
      5 * Written by David Howells (dhowells@redhat.com)
      6 *
      7 * See Documentation/watch_queue.rst
      8 */
      9
     10#ifndef _LINUX_WATCH_QUEUE_H
     11#define _LINUX_WATCH_QUEUE_H
     12
     13#include <uapi/linux/watch_queue.h>
     14#include <linux/kref.h>
     15#include <linux/rcupdate.h>
     16
     17#ifdef CONFIG_WATCH_QUEUE
     18
     19struct cred;
     20
     21struct watch_type_filter {
     22	enum watch_notification_type type;
     23	__u32		subtype_filter[1];	/* Bitmask of subtypes to filter on */
     24	__u32		info_filter;		/* Filter on watch_notification::info */
     25	__u32		info_mask;		/* Mask of relevant bits in info_filter */
     26};
     27
     28struct watch_filter {
     29	union {
     30		struct rcu_head	rcu;
     31		/* Bitmask of accepted types */
     32		DECLARE_BITMAP(type_filter, WATCH_TYPE__NR);
     33	};
     34	u32			nr_filters;	/* Number of filters */
     35	struct watch_type_filter filters[];
     36};
     37
     38struct watch_queue {
     39	struct rcu_head		rcu;
     40	struct watch_filter __rcu *filter;
     41	struct pipe_inode_info	*pipe;		/* The pipe we're using as a buffer */
     42	struct hlist_head	watches;	/* Contributory watches */
     43	struct page		**notes;	/* Preallocated notifications */
     44	unsigned long		*notes_bitmap;	/* Allocation bitmap for notes */
     45	struct kref		usage;		/* Object usage count */
     46	spinlock_t		lock;
     47	unsigned int		nr_notes;	/* Number of notes */
     48	unsigned int		nr_pages;	/* Number of pages in notes[] */
     49	bool			defunct;	/* T when queues closed */
     50};
     51
     52/*
     53 * Representation of a watch on an object.
     54 */
     55struct watch {
     56	union {
     57		struct rcu_head	rcu;
     58		u32		info_id;	/* ID to be OR'd in to info field */
     59	};
     60	struct watch_queue __rcu *queue;	/* Queue to post events to */
     61	struct hlist_node	queue_node;	/* Link in queue->watches */
     62	struct watch_list __rcu	*watch_list;
     63	struct hlist_node	list_node;	/* Link in watch_list->watchers */
     64	const struct cred	*cred;		/* Creds of the owner of the watch */
     65	void			*private;	/* Private data for the watched object */
     66	u64			id;		/* Internal identifier */
     67	struct kref		usage;		/* Object usage count */
     68};
     69
     70/*
     71 * List of watches on an object.
     72 */
     73struct watch_list {
     74	struct rcu_head		rcu;
     75	struct hlist_head	watchers;
     76	void (*release_watch)(struct watch *);
     77	spinlock_t		lock;
     78};
     79
     80extern void __post_watch_notification(struct watch_list *,
     81				      struct watch_notification *,
     82				      const struct cred *,
     83				      u64);
     84extern struct watch_queue *get_watch_queue(int);
     85extern void put_watch_queue(struct watch_queue *);
     86extern void init_watch(struct watch *, struct watch_queue *);
     87extern int add_watch_to_object(struct watch *, struct watch_list *);
     88extern int remove_watch_from_object(struct watch_list *, struct watch_queue *, u64, bool);
     89extern long watch_queue_set_size(struct pipe_inode_info *, unsigned int);
     90extern long watch_queue_set_filter(struct pipe_inode_info *,
     91				   struct watch_notification_filter __user *);
     92extern int watch_queue_init(struct pipe_inode_info *);
     93extern void watch_queue_clear(struct watch_queue *);
     94
     95static inline void init_watch_list(struct watch_list *wlist,
     96				   void (*release_watch)(struct watch *))
     97{
     98	INIT_HLIST_HEAD(&wlist->watchers);
     99	spin_lock_init(&wlist->lock);
    100	wlist->release_watch = release_watch;
    101}
    102
    103static inline void post_watch_notification(struct watch_list *wlist,
    104					   struct watch_notification *n,
    105					   const struct cred *cred,
    106					   u64 id)
    107{
    108	if (unlikely(wlist))
    109		__post_watch_notification(wlist, n, cred, id);
    110}
    111
    112static inline void remove_watch_list(struct watch_list *wlist, u64 id)
    113{
    114	if (wlist) {
    115		remove_watch_from_object(wlist, NULL, id, true);
    116		kfree_rcu(wlist, rcu);
    117	}
    118}
    119
    120/**
    121 * watch_sizeof - Calculate the information part of the size of a watch record,
    122 * given the structure size.
    123 */
    124#define watch_sizeof(STRUCT) (sizeof(STRUCT) << WATCH_INFO_LENGTH__SHIFT)
    125
    126#else
    127static inline int watch_queue_init(struct pipe_inode_info *pipe)
    128{
    129	return -ENOPKG;
    130}
    131
    132#endif
    133
    134#endif /* _LINUX_WATCH_QUEUE_H */