diff options
author | Jiang, Yunhong <yunhong.jiang@intel.com> | 2012-04-01 09:35:06 +0800 |
---|---|---|
committer | Jiang, Yunhong <yunhong.jiang@intel.com> | 2012-04-07 23:36:40 +0800 |
commit | e8bca780fc70318f38cab5bc38e5abdee60375da (patch) | |
tree | 3d0ab3aca8a01eb1a51571682059ca4e8ff9b746 /hw | |
parent | f597bde4b03c8732013c673ca920599d1ee3160d (diff) | |
download | external_qemu-e8bca780fc70318f38cab5bc38e5abdee60375da.zip external_qemu-e8bca780fc70318f38cab5bc38e5abdee60375da.tar.gz external_qemu-e8bca780fc70318f38cab5bc38e5abdee60375da.tar.bz2 |
Add qemu pipe access with parameter
The following changes are crucial for GPU H/W acceleration because
some graphics applications like games perform very frequent QEMU pipe
operations to send GLES commands to the host translator.
For each read/write buffer operation, currently QEMU pipe requires five
MMIO operations.
This causes significant overhead when running with hardware virtualization
enabled (e.g. HAXM) because each MMIO causes expensive transition from
the guest kernel to the kernel driver, and to the QEMU user space in the end.
Among such five MMIO accesses, four of them are required to just set up the
parameters for the access, like the buffer address, length etc. By passing
a buffer containing such parameters, we need only one MMIO operation to
send a GLES command to the host translator.
Update the qemu_pipe save version for pipe struct changes.
Change-Id: Idf6400f3c4c9c8473311312bb1d8f3ea92d68797
Signed-off-by: Xin, Xiaohui <xiaohui.xin@intel.com>
Signed-off-by: Jiang, Yunhong <yunhong.jiang@intel.com>
Signed-off-by: Nakajima, Jun <jun.nakajima@intel.com>
Diffstat (limited to 'hw')
-rw-r--r-- | hw/goldfish_pipe.c | 48 | ||||
-rw-r--r-- | hw/goldfish_pipe.h | 15 |
2 files changed, 61 insertions, 2 deletions
diff --git a/hw/goldfish_pipe.c b/hw/goldfish_pipe.c index 97daefb..276ac9a 100644 --- a/hw/goldfish_pipe.c +++ b/hw/goldfish_pipe.c @@ -55,7 +55,7 @@ /* Maximum length of pipe service name, in characters (excluding final 0) */ #define MAX_PIPE_SERVICE_NAME_SIZE 255 -#define GOLDFISH_PIPE_SAVE_VERSION 1 +#define GOLDFISH_PIPE_SAVE_VERSION 2 /*********************************************************************** *********************************************************************** @@ -960,9 +960,9 @@ struct PipeDevice { uint32_t status; uint32_t channel; uint32_t wakes; + uint64_t params_addr; }; - static void pipeDevice_doCommand( PipeDevice* dev, uint32_t command ) { @@ -1097,6 +1097,42 @@ static void pipe_dev_write(void *opaque, target_phys_addr_t offset, uint32_t val s->channel = value; break; + case PIPE_REG_PARAMS_ADDR_HIGH: + s->params_addr = (s->params_addr & ~(0xFFFFFFFFULL << 32) ) | + ((uint64_t)value << 32); + break; + + case PIPE_REG_PARAMS_ADDR_LOW: + s->params_addr = (s->params_addr & ~(0xFFFFFFFFULL) ) | value; + break; + + case PIPE_REG_ACCESS_PARAMS: + { + struct access_params aps; + uint32_t cmd; + + /* Don't touch aps.result if anything wrong */ + if (s->params_addr == 0) + break; + + cpu_physical_memory_read(s->params_addr, (void*)&aps, + sizeof(struct access_params)); + + /* sync pipe device state from batch buffer */ + s->channel = aps.channel; + s->size = aps.size; + s->address = aps.address; + cmd = aps.cmd; + if ((cmd != PIPE_CMD_READ_BUFFER) && (cmd != PIPE_CMD_WRITE_BUFFER)) + break; + + pipeDevice_doCommand(s, cmd); + aps.result = s->status; + cpu_physical_memory_write(s->params_addr, (void*)&aps, + sizeof(struct access_params)); + } + break; + default: D("%s: offset=%d (0x%x) value=%d (0x%x)\n", __FUNCTION__, offset, offset, value, value); @@ -1136,6 +1172,12 @@ static uint32_t pipe_dev_read(void *opaque, target_phys_addr_t offset) DR("%s: wakes %d", __FUNCTION__, dev->wakes); return dev->wakes; + case PIPE_REG_PARAMS_ADDR_HIGH: + return dev->params_addr >> 32; + + case PIPE_REG_PARAMS_ADDR_LOW: + return dev->params_addr & 0xFFFFFFFFUL; + default: D("%s: offset=%d (0x%x)\n", __FUNCTION__, offset, offset); } @@ -1165,6 +1207,7 @@ goldfish_pipe_save( QEMUFile* file, void* opaque ) qemu_put_be32(file, dev->status); qemu_put_be32(file, dev->channel); qemu_put_be32(file, dev->wakes); + qemu_put_be64(file, dev->params_addr); /* Count the number of pipe connections */ int count = 0; @@ -1193,6 +1236,7 @@ goldfish_pipe_load( QEMUFile* file, void* opaque, int version_id ) dev->status = qemu_get_be32(file); dev->channel = qemu_get_be32(file); dev->wakes = qemu_get_be32(file); + dev->params_addr = qemu_get_be64(file); /* Count the number of pipe connections */ int count = qemu_get_sbe32(file); diff --git a/hw/goldfish_pipe.h b/hw/goldfish_pipe.h index f08cef8..10efa96 100644 --- a/hw/goldfish_pipe.h +++ b/hw/goldfish_pipe.h @@ -153,6 +153,11 @@ extern void goldfish_pipe_wake( void* hwpipe, unsigned flags ); #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 */ +/* read/write: parameter buffer address */ +#define PIPE_REG_PARAMS_ADDR_LOW 0x18 +#define PIPE_REG_PARAMS_ADDR_HIGH 0x1c +/* write: access with paremeter buffer */ +#define PIPE_REG_ACCESS_PARAMS 0x20 /* list of commands for PIPE_REG_COMMAND */ #define PIPE_CMD_OPEN 1 /* open new channel */ @@ -189,4 +194,14 @@ extern void goldfish_pipe_wake( void* hwpipe, unsigned flags ); void pipe_dev_init(void); +struct access_params{ + uint32_t channel; + uint32_t size; + uint32_t address; + uint32_t cmd; + uint32_t result; + /* reserved for future extension */ + uint32_t flags; +}; + #endif /* _HW_GOLDFISH_PIPE_H */ |