1a75eb03bSDavid Marchand /* 2a75eb03bSDavid Marchand * Copyright 6WIND S.A., 2014 3a75eb03bSDavid Marchand * 4a75eb03bSDavid Marchand * This work is licensed under the terms of the GNU GPL, version 2 or 5a75eb03bSDavid Marchand * (at your option) any later version. See the COPYING file in the 6a75eb03bSDavid Marchand * top-level directory. 7a75eb03bSDavid Marchand */ 8a75eb03bSDavid Marchand 9a75eb03bSDavid Marchand #ifndef _IVSHMEM_CLIENT_H_ 10a75eb03bSDavid Marchand #define _IVSHMEM_CLIENT_H_ 11a75eb03bSDavid Marchand 12a75eb03bSDavid Marchand /** 13a75eb03bSDavid Marchand * This file provides helper to implement an ivshmem client. It is used 14a75eb03bSDavid Marchand * on the host to ask QEMU to send an interrupt to an ivshmem PCI device in a 15a75eb03bSDavid Marchand * guest. QEMU also implements an ivshmem client similar to this one, they both 16a75eb03bSDavid Marchand * connect to an ivshmem server. 17a75eb03bSDavid Marchand * 18a75eb03bSDavid Marchand * A standalone ivshmem client based on this file is provided for debug/test 19a75eb03bSDavid Marchand * purposes. 20a75eb03bSDavid Marchand */ 21a75eb03bSDavid Marchand 22a75eb03bSDavid Marchand #include <limits.h> 23a75eb03bSDavid Marchand #include <sys/select.h> 24a75eb03bSDavid Marchand 25a75eb03bSDavid Marchand #include "qemu/queue.h" 26*5105b1d8SDavid Marchand #include "hw/misc/ivshmem.h" 27a75eb03bSDavid Marchand 28a75eb03bSDavid Marchand /** 29a75eb03bSDavid Marchand * Maximum number of notification vectors supported by the client 30a75eb03bSDavid Marchand */ 31a75eb03bSDavid Marchand #define IVSHMEM_CLIENT_MAX_VECTORS 64 32a75eb03bSDavid Marchand 33a75eb03bSDavid Marchand /** 34a75eb03bSDavid Marchand * Structure storing a peer 35a75eb03bSDavid Marchand * 36a75eb03bSDavid Marchand * Each time a client connects to an ivshmem server, it is advertised to 37a75eb03bSDavid Marchand * all connected clients through the unix socket. When our ivshmem 38a75eb03bSDavid Marchand * client receives a notification, it creates a IvshmemClientPeer 39a75eb03bSDavid Marchand * structure to store the infos of this peer. 40a75eb03bSDavid Marchand * 41a75eb03bSDavid Marchand * This structure is also used to store the information of our own 42a75eb03bSDavid Marchand * client in (IvshmemClient)->local. 43a75eb03bSDavid Marchand */ 44a75eb03bSDavid Marchand typedef struct IvshmemClientPeer { 45a75eb03bSDavid Marchand QTAILQ_ENTRY(IvshmemClientPeer) next; /**< next in list*/ 46a75eb03bSDavid Marchand long id; /**< the id of the peer */ 47a75eb03bSDavid Marchand int vectors[IVSHMEM_CLIENT_MAX_VECTORS]; /**< one fd per vector */ 48a75eb03bSDavid Marchand unsigned vectors_count; /**< number of vectors */ 49a75eb03bSDavid Marchand } IvshmemClientPeer; 50a75eb03bSDavid Marchand QTAILQ_HEAD(IvshmemClientPeerList, IvshmemClientPeer); 51a75eb03bSDavid Marchand 52a75eb03bSDavid Marchand typedef struct IvshmemClientPeerList IvshmemClientPeerList; 53a75eb03bSDavid Marchand typedef struct IvshmemClient IvshmemClient; 54a75eb03bSDavid Marchand 55a75eb03bSDavid Marchand /** 56a75eb03bSDavid Marchand * Typedef of callback function used when our IvshmemClient receives a 57a75eb03bSDavid Marchand * notification from a peer. 58a75eb03bSDavid Marchand */ 59a75eb03bSDavid Marchand typedef void (*IvshmemClientNotifCb)( 60a75eb03bSDavid Marchand const IvshmemClient *client, 61a75eb03bSDavid Marchand const IvshmemClientPeer *peer, 62a75eb03bSDavid Marchand unsigned vect, void *arg); 63a75eb03bSDavid Marchand 64a75eb03bSDavid Marchand /** 65a75eb03bSDavid Marchand * Structure describing an ivshmem client 66a75eb03bSDavid Marchand * 67a75eb03bSDavid Marchand * This structure stores all information related to our client: the name 68a75eb03bSDavid Marchand * of the server unix socket, the list of peers advertised by the 69a75eb03bSDavid Marchand * server, our own client information, and a pointer the notification 70a75eb03bSDavid Marchand * callback function used when we receive a notification from a peer. 71a75eb03bSDavid Marchand */ 72a75eb03bSDavid Marchand struct IvshmemClient { 73a75eb03bSDavid Marchand char unix_sock_path[PATH_MAX]; /**< path to unix sock */ 74a75eb03bSDavid Marchand int sock_fd; /**< unix sock filedesc */ 75a75eb03bSDavid Marchand int shm_fd; /**< shm file descriptor */ 76a75eb03bSDavid Marchand 77a75eb03bSDavid Marchand IvshmemClientPeerList peer_list; /**< list of peers */ 78a75eb03bSDavid Marchand IvshmemClientPeer local; /**< our own infos */ 79a75eb03bSDavid Marchand 80a75eb03bSDavid Marchand IvshmemClientNotifCb notif_cb; /**< notification callback */ 81a75eb03bSDavid Marchand void *notif_arg; /**< notification argument */ 82a75eb03bSDavid Marchand 83a75eb03bSDavid Marchand bool verbose; /**< true to enable debug */ 84a75eb03bSDavid Marchand }; 85a75eb03bSDavid Marchand 86a75eb03bSDavid Marchand /** 87a75eb03bSDavid Marchand * Initialize an ivshmem client 88a75eb03bSDavid Marchand * 89a75eb03bSDavid Marchand * @client: A pointer to an uninitialized IvshmemClient structure 90a75eb03bSDavid Marchand * @unix_sock_path: The pointer to the unix socket file name 91a75eb03bSDavid Marchand * @notif_cb: If not NULL, the pointer to the function to be called when 92a75eb03bSDavid Marchand * our IvshmemClient receives a notification from a peer 93a75eb03bSDavid Marchand * @notif_arg: Opaque pointer given as-is to the notification callback 94a75eb03bSDavid Marchand * function 95a75eb03bSDavid Marchand * @verbose: True to enable debug 96a75eb03bSDavid Marchand * 97a75eb03bSDavid Marchand * Returns: 0 on success, or a negative value on error 98a75eb03bSDavid Marchand */ 99a75eb03bSDavid Marchand int ivshmem_client_init(IvshmemClient *client, const char *unix_sock_path, 100a75eb03bSDavid Marchand IvshmemClientNotifCb notif_cb, void *notif_arg, 101a75eb03bSDavid Marchand bool verbose); 102a75eb03bSDavid Marchand 103a75eb03bSDavid Marchand /** 104a75eb03bSDavid Marchand * Connect to the server 105a75eb03bSDavid Marchand * 106a75eb03bSDavid Marchand * Connect to the server unix socket, and read the first initial 107a75eb03bSDavid Marchand * messages sent by the server, giving the ID of the client and the file 108a75eb03bSDavid Marchand * descriptor of the shared memory. 109a75eb03bSDavid Marchand * 110a75eb03bSDavid Marchand * @client: The ivshmem client 111a75eb03bSDavid Marchand * 112a75eb03bSDavid Marchand * Returns: 0 on success, or a negative value on error 113a75eb03bSDavid Marchand */ 114a75eb03bSDavid Marchand int ivshmem_client_connect(IvshmemClient *client); 115a75eb03bSDavid Marchand 116a75eb03bSDavid Marchand /** 117a75eb03bSDavid Marchand * Close connection to the server and free all peer structures 118a75eb03bSDavid Marchand * 119a75eb03bSDavid Marchand * @client: The ivshmem client 120a75eb03bSDavid Marchand */ 121a75eb03bSDavid Marchand void ivshmem_client_close(IvshmemClient *client); 122a75eb03bSDavid Marchand 123a75eb03bSDavid Marchand /** 124a75eb03bSDavid Marchand * Fill a fd_set with file descriptors to be monitored 125a75eb03bSDavid Marchand * 126a75eb03bSDavid Marchand * This function will fill a fd_set with all file descriptors 127a75eb03bSDavid Marchand * that must be polled (unix server socket and peers eventfd). The 128a75eb03bSDavid Marchand * function will not initialize the fd_set, it is up to the caller 129a75eb03bSDavid Marchand * to do this. 130a75eb03bSDavid Marchand * 131a75eb03bSDavid Marchand * @client: The ivshmem client 132a75eb03bSDavid Marchand * @fds: The fd_set to be updated 133a75eb03bSDavid Marchand * @maxfd: Must be set to the max file descriptor + 1 in fd_set. This value is 134a75eb03bSDavid Marchand * updated if this function adds a greater fd in fd_set. 135a75eb03bSDavid Marchand */ 136a75eb03bSDavid Marchand void ivshmem_client_get_fds(const IvshmemClient *client, fd_set *fds, 137a75eb03bSDavid Marchand int *maxfd); 138a75eb03bSDavid Marchand 139a75eb03bSDavid Marchand /** 140a75eb03bSDavid Marchand * Read and handle new messages 141a75eb03bSDavid Marchand * 142a75eb03bSDavid Marchand * Given a fd_set filled by select(), handle incoming messages from 143a75eb03bSDavid Marchand * server or peers. 144a75eb03bSDavid Marchand * 145a75eb03bSDavid Marchand * @client: The ivshmem client 146a75eb03bSDavid Marchand * @fds: The fd_set containing the file descriptors to be checked. Note 147a75eb03bSDavid Marchand * that file descriptors that are not related to our client are 148a75eb03bSDavid Marchand * ignored. 149a75eb03bSDavid Marchand * @maxfd: The maximum fd in fd_set, plus one. 150a75eb03bSDavid Marchand * 151a75eb03bSDavid Marchand * Returns: 0 on success, or a negative value on error 152a75eb03bSDavid Marchand */ 153a75eb03bSDavid Marchand int ivshmem_client_handle_fds(IvshmemClient *client, fd_set *fds, int maxfd); 154a75eb03bSDavid Marchand 155a75eb03bSDavid Marchand /** 156a75eb03bSDavid Marchand * Send a notification to a vector of a peer 157a75eb03bSDavid Marchand * 158a75eb03bSDavid Marchand * @client: The ivshmem client 159a75eb03bSDavid Marchand * @peer: The peer to be notified 160a75eb03bSDavid Marchand * @vector: The number of the vector 161a75eb03bSDavid Marchand * 162a75eb03bSDavid Marchand * Returns: 0 on success, or a negative value on error 163a75eb03bSDavid Marchand */ 164a75eb03bSDavid Marchand int ivshmem_client_notify(const IvshmemClient *client, 165a75eb03bSDavid Marchand const IvshmemClientPeer *peer, unsigned vector); 166a75eb03bSDavid Marchand 167a75eb03bSDavid Marchand /** 168a75eb03bSDavid Marchand * Send a notification to all vectors of a peer 169a75eb03bSDavid Marchand * 170a75eb03bSDavid Marchand * @client: The ivshmem client 171a75eb03bSDavid Marchand * @peer: The peer to be notified 172a75eb03bSDavid Marchand * 173a75eb03bSDavid Marchand * Returns: 0 on success, or a negative value on error (at least one 174a75eb03bSDavid Marchand * notification failed) 175a75eb03bSDavid Marchand */ 176a75eb03bSDavid Marchand int ivshmem_client_notify_all_vects(const IvshmemClient *client, 177a75eb03bSDavid Marchand const IvshmemClientPeer *peer); 178a75eb03bSDavid Marchand 179a75eb03bSDavid Marchand /** 180a75eb03bSDavid Marchand * Broadcat a notification to all vectors of all peers 181a75eb03bSDavid Marchand * 182a75eb03bSDavid Marchand * @client: The ivshmem client 183a75eb03bSDavid Marchand * 184a75eb03bSDavid Marchand * Returns: 0 on success, or a negative value on error (at least one 185a75eb03bSDavid Marchand * notification failed) 186a75eb03bSDavid Marchand */ 187a75eb03bSDavid Marchand int ivshmem_client_notify_broadcast(const IvshmemClient *client); 188a75eb03bSDavid Marchand 189a75eb03bSDavid Marchand /** 190a75eb03bSDavid Marchand * Search a peer from its identifier 191a75eb03bSDavid Marchand * 192a75eb03bSDavid Marchand * Return the peer structure from its peer_id. If the given peer_id is 193a75eb03bSDavid Marchand * the local id, the function returns the local peer structure. 194a75eb03bSDavid Marchand * 195a75eb03bSDavid Marchand * @client: The ivshmem client 196a75eb03bSDavid Marchand * @peer_id: The identifier of the peer structure 197a75eb03bSDavid Marchand * 198a75eb03bSDavid Marchand * Returns: The peer structure, or NULL if not found 199a75eb03bSDavid Marchand */ 200a75eb03bSDavid Marchand IvshmemClientPeer * 201a75eb03bSDavid Marchand ivshmem_client_search_peer(IvshmemClient *client, long peer_id); 202a75eb03bSDavid Marchand 203a75eb03bSDavid Marchand /** 204a75eb03bSDavid Marchand * Dump information of this ivshmem client on stdout 205a75eb03bSDavid Marchand * 206a75eb03bSDavid Marchand * Dump the id and the vectors of the given ivshmem client and the list 207a75eb03bSDavid Marchand * of its peers and their vectors on stdout. 208a75eb03bSDavid Marchand * 209a75eb03bSDavid Marchand * @client: The ivshmem client 210a75eb03bSDavid Marchand */ 211a75eb03bSDavid Marchand void ivshmem_client_dump(const IvshmemClient *client); 212a75eb03bSDavid Marchand 213a75eb03bSDavid Marchand #endif /* _IVSHMEM_CLIENT_H_ */ 214