1 /**
2  * @file
3  * @section AUTHORS
4  *
5  * Copyright (C) 2010  Rafal Wojtczuk  <rafal@invisiblethingslab.com>
6  *
7  *  Authors:
8  *       Rafal Wojtczuk  <rafal@invisiblethingslab.com>
9  *       Daniel De Graaf <dgdegra@tycho.nsa.gov>
10  *
11  * @section LICENSE
12  *
13  *  This library is free software; you can redistribute it and/or
14  *  modify it under the terms of the GNU Lesser General Public
15  *  License as published by the Free Software Foundation; either
16  *  version 2.1 of the License, or (at your option) any later version.
17  *
18  *  This library is distributed in the hope that it will be useful,
19  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21  *  Lesser General Public License for more details.
22  *
23  *  You should have received a copy of the GNU Lesser General Public
24  *  License along with this library; If not, see <http://www.gnu.org/licenses/>.
25  *
26  * @section DESCRIPTION
27  *
28  *  Originally borrowed from the Qubes OS Project, http://www.qubes-os.org,
29  *  this code has been substantially rewritten to use the gntdev and gntalloc
30  *  devices instead of raw MFNs and map_foreign_range.
31  *
32  *  This is a library for inter-domain communication.  A standard Xen ring
33  *  buffer is used, with a datagram-based interface built on top.  The grant
34  *  reference and event channels are shared in XenStore under the path
35  *  /local/domain/<srv-id>/data/vchan/<cli-id>/<port>/{ring-ref,event-channel}
36  *
37  *  The ring.h macros define an asymmetric interface to a shared data structure
38  *  that assumes all rings reside in a single contiguous memory space. This is
39  *  not suitable for vchan because the interface to the ring is symmetric except
40  *  for the setup. Unlike the producer-consumer rings defined in ring.h, the
41  *  size of the rings used in vchan are determined at execution time instead of
42  *  compile time, so the macros in ring.h cannot be used to access the rings.
43  */
44 
45 #include <xen/io/libxenvchan.h>
46 #include <xen/xen.h>
47 #include <xen/sys/evtchn.h>
48 #include <xenevtchn.h>
49 #include <xengnttab.h>
50 
51 /* Callers who don't care don't need to #include <xentoollog.h> */
52 struct xentoollog_logger;
53 
54 struct libxenvchan_ring {
55 	/* Pointer into the shared page. Offsets into buffer. */
56 	struct ring_shared* shr;
57 	/* ring data; may be its own shared page(s) depending on order */
58 	void* buffer;
59 	/**
60 	 * The size of the ring is (1 << order); offsets wrap around when they
61 	 * exceed this. This copy is required because we can't trust the order
62 	 * in the shared page to remain constant.
63 	 */
64 	int order;
65 };
66 
67 /**
68  * struct libxenvchan: control structure passed to all library calls
69  */
70 struct libxenvchan {
71 	/* Mapping handle for shared ring page */
72 	union {
73 		xengntshr_handle *gntshr; /* for server */
74 		xengnttab_handle *gnttab; /* for client */
75 	};
76 	/* Pointer to shared ring page */
77 	struct vchan_interface *ring;
78 	/* event channel interface */
79 	xenevtchn_handle *event;
80 	uint32_t event_port;
81 	/* informative flags: are we acting as server? */
82 	unsigned int is_server:1;
83 	/* true if server remains active when client closes (allows reconnection) */
84 	unsigned int server_persist:1;
85 	/* true if operations should block instead of returning 0 */
86 	unsigned int blocking:1;
87 	/* communication rings */
88 	struct libxenvchan_ring read, write;
89 	/**
90 	 * Base xenstore path for storing ring/event data used by the server
91 	 * during cleanup.
92 	 * */
93 	char *xs_path;
94 };
95 
96 /**
97  * Set up a vchan, including granting pages
98  * @param logger Logger for libxc errors
99  * @param domain The peer domain that will be connecting
100  * @param xs_path Base xenstore path for storing ring/event data
101  * @param send_min The minimum size (in bytes) of the send ring (left)
102  * @param recv_min The minimum size (in bytes) of the receive ring (right)
103  * @return The structure, or NULL in case of an error
104  */
105 struct libxenvchan *libxenvchan_server_init(struct xentoollog_logger *logger,
106                                             int domain, const char* xs_path,
107                                             size_t read_min, size_t write_min);
108 /**
109  * Connect to an existing vchan. Note: you can reconnect to an existing vchan
110  * safely, however no locking is performed, so you must prevent multiple clients
111  * from connecting to a single server.
112  *
113  * @param logger Logger for libxc errors
114  * @param domain The peer domain to connect to
115  * @param xs_path Base xenstore path for storing ring/event data
116  * @return The structure, or NULL in case of an error
117  */
118 struct libxenvchan *libxenvchan_client_init(struct xentoollog_logger *logger,
119                                             int domain, const char* xs_path);
120 /**
121  * Close a vchan. This deallocates the vchan and attempts to free its
122  * resources. The other side is notified of the close, but can still read any
123  * data pending prior to the close.
124  */
125 void libxenvchan_close(struct libxenvchan *ctrl);
126 
127 /**
128  * Packet-based receive: always reads exactly $size bytes.
129  * @param ctrl The vchan control structure
130  * @param data Buffer for data that was read
131  * @param size Size of the buffer and amount of data to read
132  * @return -1 on error, 0 if nonblocking and insufficient data is available, or $size
133  */
134 int libxenvchan_recv(struct libxenvchan *ctrl, void *data, size_t size);
135 /**
136  * Stream-based receive: reads as much data as possible.
137  * @param ctrl The vchan control structure
138  * @param data Buffer for data that was read
139  * @param size Size of the buffer
140  * @return -1 on error, otherwise the amount of data read (which may be zero if
141  *         the vchan is nonblocking)
142  */
143 int libxenvchan_read(struct libxenvchan *ctrl, void *data, size_t size);
144 /**
145  * Packet-based send: send entire buffer if possible
146  * @param ctrl The vchan control structure
147  * @param data Buffer for data to send
148  * @param size Size of the buffer and amount of data to send
149  * @return -1 on error, 0 if nonblocking and insufficient space is available, or $size
150  */
151 int libxenvchan_send(struct libxenvchan *ctrl, const void *data, size_t size);
152 /**
153  * Stream-based send: send as much data as possible.
154  * @param ctrl The vchan control structure
155  * @param data Buffer for data to send
156  * @param size Size of the buffer
157  * @return -1 on error, otherwise the amount of data sent (which may be zero if
158  *         the vchan is nonblocking)
159  */
160 int libxenvchan_write(struct libxenvchan *ctrl, const void *data, size_t size);
161 /**
162  * Waits for reads or writes to unblock, or for a close
163  */
164 int libxenvchan_wait(struct libxenvchan *ctrl);
165 /**
166  * Returns the event file descriptor for this vchan. When this FD is readable,
167  * libxenvchan_wait() will not block, and the state of the vchan has changed since
168  * the last invocation of libxenvchan_wait().
169  */
170 int libxenvchan_fd_for_select(struct libxenvchan *ctrl);
171 /**
172  * Query the state of the vchan shared page:
173  *  return 0 when one side has called libxenvchan_close() or crashed
174  *  return 1 when both sides are open
175  *  return 2 [server only] when no client has yet connected
176  */
177 int libxenvchan_is_open(struct libxenvchan* ctrl);
178 /** Amount of data ready to read, in bytes */
179 int libxenvchan_data_ready(struct libxenvchan *ctrl);
180 /** Amount of data it is possible to send without blocking */
181 int libxenvchan_buffer_space(struct libxenvchan *ctrl);
182