aboutsummaryrefslogtreecommitdiffstats
path: root/hw/goldfish_pipe.h
diff options
context:
space:
mode:
authorDavid 'Digit' Turner <digit@android.com>2011-04-26 18:09:17 +0200
committerDavid 'Digit' Turner <digit@android.com>2011-04-28 16:41:50 +0200
commitd4d688e926097faba7fd3717d1c0d3f296bdb526 (patch)
treeb6e89c99abae42e5bcef26afaa2952b5a870895b /hw/goldfish_pipe.h
parenta65e41529e4e3900372d54859f8c559cf79d953c (diff)
downloadexternal_qemu-d4d688e926097faba7fd3717d1c0d3f296bdb526.zip
external_qemu-d4d688e926097faba7fd3717d1c0d3f296bdb526.tar.gz
external_qemu-d4d688e926097faba7fd3717d1c0d3f296bdb526.tar.bz2
New goldfish_pipe virtual device.
This adds a new virtual hardware device named "goldfish_pipe" used to implement a very fast communication channel between the guest system and the emulator. IMPORTANT: This depends on a special kernel driver, see: https://review.source.android.com/#change,22496 Usage from the guest is simply the following: fd = open("/dev/qemu_pipe", O_RDWR); const char* pipename = "pipe:<name>"; ret = write(fd, pipename, strlen(pipename)+1); if (ret < 0) { /* could not connect to service named <name> */ } /* now you can read()/write()/close() as a normal * file descriptor to exchange data with the service. */ In addition, this implements the following pipe services in the emulator: tcp:<port> tcp:<hostname>:<port> unix:<path> opengles The 'tcp:' and 'unix:' services simply redirect to a TCP or Unix socket on the host with minimal The 'opengles' service simply connects to tcp:locahost:22468 for now. We may change this to be more configurable in the future, but that's the port number used by the current experimental OpenGL ES hardware emulation host libraries / programs. Benchmarking with a simple ping-pong program shows that the guest <-> emulator can achieve a roundtrip bandwidth of 192 MB/s (on a 2.7 Ghz Xeon PC). Using the tcp: service to talk to a ping-pong server listening on localhost reaches 102 MB/s on the same machine, using a Unix socket reaches 140 MB/s. By contrast, using standard sockets in the guest reaches only 3.8 MB/s on the same machine (and requires special privileges from the application anyway).
Diffstat (limited to 'hw/goldfish_pipe.h')
-rw-r--r--hw/goldfish_pipe.h203
1 files changed, 138 insertions, 65 deletions
diff --git a/hw/goldfish_pipe.h b/hw/goldfish_pipe.h
index 03bc443..be5c449 100644
--- a/hw/goldfish_pipe.h
+++ b/hw/goldfish_pipe.h
@@ -13,66 +13,45 @@
#define _HW_GOLDFISH_PIPE_H
#include <stdint.h>
-#include "android/hw-qemud.h"
+#include "hw/hw.h"
-/* The following functions should called from hw/goldfish_trace.c and are
- * used to implement QEMUD 'fast-pipes' in the Android emulator.
- */
-extern void goldfish_pipe_thread_death(int tid);
-extern void goldfish_pipe_write(int tid, int offset, uint32_t value);
-extern uint32_t goldfish_pipe_read(int tid, int offset);
-
-/* The following definitions are used to define a "pipe handler" type.
- * Each pipe handler manages a given, named pipe type, and must provide
- * a few callbacks that will be used at appropriate times:
- *
- * - init ::
- * is called when a guest client has connected to a given
- * pipe. The function should return an opaque pointer that
- * will be passed as the first parameter to other callbacks.
- *
- * Note: pipeOpaque is the value that was passed to
- * goldfish_pipe_add_type() to register the pipe handler.
- *
- * - close ::
- * is called when the pipe is closed.(either from the guest, or
- * when the handler itself calls qemud_client_close() on the
- * corresponding QemudClient object passed to init()).
- *
- * - sendBuffers ::
- * is called when the guest is sending data through the pipe. This
- * callback receives a list of buffer descriptors that indicate
- * where the data is located in memory.
- *
- * Must return 0 on success, or -1 on failure, with errno of:
- *
- * ENOMEM -> indicates that the message is too large
- * EAGAIN -> indicates that the handler is not ready
- * to accept the message yet.
- *
- * - recvBuffers ::
- * Is called when the guest wants to receive data from the pipe.
- * The caller provides a list of memory buffers to put the data into.
- *
- * Must return the size of the incoming data on success, or -1
- * on error, with errno of:
- *
- * ENOMEM -> buffer too small to receive the message
- * EAGAIN -> no incoming data yet
- *
- * - wakeOn ::
- * is called to indicate that the guest wants to be waked when the
- * pipe becomes able to either receive data from the guest, or send it
- * new incoming data. It is the responsability of the pipe handler to
- * signal the corresponding events by sending a single byte containing
- * QEMUD_PIPE_WAKE_XXX bit flags through qemud_client_send() to do so.
+/* TECHNICAL NOTE:
+ *
+ * A goldfish pipe is a very fast communication channel between the guest
+ * system and the emulator program.
+ *
+ * To open a new pipe to the emulator, a guest client will do the following:
+ *
+ * fd = open("/dev/qemu_pipe", O_RDWR);
+ * char invite[64];
+ * snprintf(invite, sizeof invite, "%s", pipeName);
+ * ret = write(fd, invite, strlen(invite));
+ *
+ * if (ret < 0) {
+ * // something bad happened, see errno
+ * }
+ *
+ * now read()/write() to communicate with <pipeName> service in the
+ * emulator.
+ *
+ * This header provides the interface used by pipe services in the emulator
+ * to receive new client connection and deal with them.
+ *
+ *
+ * 1/ Call goldfish_pipe_add_type() to register a new pipe service by name.
+ * This must provide a pointer to a series of functions that will be called
+ * during normal pipe operations.
+ *
+ * 2/ When a client connects to the service, the 'init' callback will be called
+ * to create a new service-specific client identifier (which must returned
+ * by the function).
+ *
+ * 3/ Call goldfish_pipe_close() to force the closure of a given pipe.
+ *
+ * 4/ Call goldfish_pipe_signal() to signal a change of state to the pipe.
+ *
*/
-enum {
- QEMUD_PIPE_WAKE_ON_SEND = (1 << 0),
- QEMUD_PIPE_WAKE_ON_RECV = (1 << 1),
-};
-
/* Buffer descriptor for sendBuffers() and recvBuffers() callbacks */
typedef struct GoldfishPipeBuffer {
uint8_t* data;
@@ -81,18 +60,112 @@ typedef struct GoldfishPipeBuffer {
/* Pipe handler funcs */
typedef struct {
- void* (*init)( QemudClient* client, void* pipeOpaque );
- void (*close)( void* opaque );
- int (*sendBuffers)( void* opaque, const GoldfishPipeBuffer* buffers, int numBuffers );
- int (*recvBuffers)( void* opaque, GoldfishPipeBuffer* buffers, int numBuffers );
+ /* Create new client connection, 'hwpipe' must be passed to other
+ * goldfish_pipe_xxx functions, while the returned value will be passed
+ * to other callbacks (e.g. close). 'pipeOpaque' is the value passed
+ * to goldfish_pipe_add_type() when registering a given pipe service.
+ */
+ void* (*init)( void* hwpipe, void* pipeOpaque, const char* args );
+
+ /* Called when the guest kernel has finally closed a pipe connection.
+ * This is the only place where you can release/free the client connection.
+ * You should never invoke this callback directly. Call goldfish_pipe_close()
+ * instead.
+ */
+ void (*close)( void* pipe );
+
+ /* Called when the guest is write()-ing to the pipe. Should return the
+ * number of bytes transfered, 0 for EOF status, or a negative error
+ * value otherwise, including PIPE_ERROR_AGAIN to indicate that the
+ * emulator is not ready to receive data yet.
+ */
+ int (*sendBuffers)( void* pipe, const GoldfishPipeBuffer* buffers, int numBuffers );
+
+ /* Same as sendBuffers when the guest is read()-ing from the pipe. */
+ int (*recvBuffers)( void* pipe, GoldfishPipeBuffer* buffers, int numBuffers );
+
+ /* Called when guest wants to poll the read/write status for the pipe.
+ * Should return a combination of PIPE_WAKE_XXX flags.
+ */
+ unsigned (*poll)( void* pipe );
+
+ /* Called to signal that the guest wants to be woken when the set of
+ * PIPE_WAKE_XXX bit-flags in 'flags' occur. When the condition occurs,
+ * then the pipe implementation shall call goldfish_pipe_wake().
+ */
void (*wakeOn)( void* opaque, int flags );
-} QemudPipeHandlerFuncs;
+} GoldfishPipeFuncs;
/* Register a new pipe handler type. 'pipeOpaque' is passed directly
* to 'init() when a new pipe is connected to.
*/
-extern void goldfish_pipe_add_type(const char* pipeName,
- void* pipeOpaque,
- const QemudPipeHandlerFuncs* pipeFuncs );
+extern void goldfish_pipe_add_type(const char* pipeName,
+ void* pipeOpaque,
+ const GoldfishPipeFuncs* pipeFuncs );
+
+/* This tells the guest system that we want to close the pipe and that
+ * further attempts to read or write to it will fail. This will not
+ * necessarily call the 'close' callback immediately though.
+ *
+ * This will also wake-up any blocked guest threads waiting for i/o.
+ */
+extern void goldfish_pipe_close( void* hwpipe );
+
+/* Signal that the pipe can be woken up. 'flags' must be a combination of
+ * PIPE_WAKE_READ and PIPE_WAKE_WRITE.
+ */
+extern void goldfish_pipe_wake( void* hwpipe, unsigned flags );
+
+/* The following definitions must match those under:
+ *
+ * $KERNEL/drivers/misc/qemupipe/qemu_pipe.c
+ *
+ * Where $KERNEL points to the android-goldfish-2.6.xx branch on:
+ *
+ * android.git.kernel.org/kernel/qemu.git.
+ */
+
+/* pipe device registers */
+#define PIPE_REG_COMMAND 0x00 /* write: value = command */
+#define PIPE_REG_STATUS 0x04 /* read */
+#define PIPE_REG_CHANNEL 0x08 /* read/write: channel id */
+#define PIPE_REG_SIZE 0x0c /* read/write: buffer size */
+#define PIPE_REG_ADDRESS 0x10 /* write: physical address */
+#define PIPE_REG_WAKES 0x14 /* read: wake flags */
+
+/* list of commands for PIPE_REG_COMMAND */
+#define PIPE_CMD_OPEN 1 /* open new channel */
+#define PIPE_CMD_CLOSE 2 /* close channel (from guest) */
+#define PIPE_CMD_POLL 3 /* poll read/write status */
+
+/* List of bitflags returned in status of CMD_POLL command */
+#define PIPE_POLL_IN (1 << 0)
+#define PIPE_POLL_OUT (1 << 1)
+#define PIPE_POLL_HUP (1 << 2)
+
+/* The following commands are related to write operations */
+#define PIPE_CMD_WRITE_BUFFER 4 /* send a user buffer to the emulator */
+#define PIPE_CMD_WAKE_ON_WRITE 5 /* tell the emulator to wake us when writing is possible */
+
+/* The following commands are related to read operations, they must be
+ * listed in the same order than the corresponding write ones, since we
+ * will use (CMD_READ_BUFFER - CMD_WRITE_BUFFER) as a special offset
+ * in qemu_pipe_read_write() below.
+ */
+#define PIPE_CMD_READ_BUFFER 6 /* receive a page-contained buffer from the emulator */
+#define PIPE_CMD_WAKE_ON_READ 7 /* tell the emulator to wake us when reading is possible */
+
+/* Possible status values used to signal errors - see qemu_pipe_error_convert */
+#define PIPE_ERROR_INVAL -1
+#define PIPE_ERROR_AGAIN -2
+#define PIPE_ERROR_NOMEM -3
+#define PIPE_ERROR_IO -4
+
+/* Bit-flags used to signal events from the emulator */
+#define PIPE_WAKE_CLOSED (1 << 0) /* emulator closed pipe */
+#define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */
+#define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */
+
+void pipe_dev_init(void);
#endif /* _HW_GOLDFISH_PIPE_H */