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