From c500b62a84f4c34330eccf9783c507b490202cc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alex=20Benn=C3=A9e?= Date: Thu, 13 Nov 2014 17:04:36 +0000 Subject: android_pipe: auto-detect PIPE_REG_ACCESS_PARAMS size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The PIPE_REG_ACCESS_PARAMS structure can be one of two sizes depending on the type of host kernel. As the pipe code is shared between both 32 bit and 64 bit worlds it needs to be able to handle both. Introspecting the CPU type is impractical as a 64 bit CPU may be booting a 32 bit kernel. Fortunately due to the overlap of the structures it's possible to detect the use of a 64 bit structure as it implies a non-zero value of the (currently) unused flags field. This also opens the way to the 32 bit code using the 64 bit structure at a later date. Signed-off-by: Alex Bennée --- hw/misc/android_pipe.c | 57 +++++++++++++++++++++--------------------- include/hw/misc/android_pipe.h | 32 ++++++++++++++---------- 2 files changed, 48 insertions(+), 41 deletions(-) diff --git a/hw/misc/android_pipe.c b/hw/misc/android_pipe.c index 942ca3760d..7b5dd7422e 100644 --- a/hw/misc/android_pipe.c +++ b/hw/misc/android_pipe.c @@ -87,12 +87,6 @@ static inline void uint64_set_high(uint64_t *addr, uint32 value) *addr = (*addr & 0xFFFFFFFFULL) | ((uint64_t)value << 32); } -/* FIXME: this is hardcoded for now but will break if used for - * lionhead/goldfish (32 bit) */ -static inline gboolean android_guest_is_64bit(void) { - return TRUE; -} - #define TYPE_ANDROID_PIPE "android_pipe" #define ANDROID_PIPE(obj) \ OBJECT_CHECK(AndroidPipeState, (obj), TYPE_ANDROID_PIPE) @@ -660,28 +654,37 @@ static void pipe_dev_write(void *opaque, hwaddr offset, uint64_t value, unsigned case PIPE_REG_ACCESS_PARAMS: { - struct access_params aps; - struct access_params_64 aps64; + union access_params aps; uint32_t cmd; + bool is_64bit = true; /* Don't touch aps.result if anything wrong */ if (s->params_addr == 0) break; - if (android_guest_is_64bit()) { - cpu_physical_memory_read(s->params_addr, (void*)&aps64, - sizeof(aps64)); - s->channel = aps64.channel; - s->size = aps64.size; - s->address = aps64.address; - cmd = aps64.cmd; + cpu_physical_memory_read(s->params_addr, (void*)&aps, sizeof(aps.aps32)); + + /* This auto-detection of 32bit/64bit ness relies on the + * currently unused flags parameter. As the 32 bit flags + * overlaps with the 64 bit cmd parameter. As cmd != 0 if we + * find it as 0 it's 32bit + */ + if (aps.aps32.flags == 0) { + is_64bit = false; + } else { + cpu_physical_memory_read(s->params_addr, (void*)&aps, sizeof(aps.aps64)); + } + + if (is_64bit) { + s->channel = aps.aps64.channel; + s->size = aps.aps64.size; + s->address = aps.aps64.address; + cmd = aps.aps64.cmd; } else { - cpu_physical_memory_read(s->params_addr, (void*)&aps, - sizeof(aps)); - s->channel = aps.channel; - s->size = aps.size; - s->address = aps.address; - cmd = aps.cmd; + s->channel = aps.aps32.channel; + s->size = aps.aps32.size; + s->address = aps.aps32.address; + cmd = aps.aps32.cmd; } if ((cmd != PIPE_CMD_READ_BUFFER) && (cmd != PIPE_CMD_WRITE_BUFFER)) @@ -689,14 +692,12 @@ static void pipe_dev_write(void *opaque, hwaddr offset, uint64_t value, unsigned pipeDevice_doCommand(s, cmd); - if (android_guest_is_64bit()) { - aps64.result = s->status; - cpu_physical_memory_write(s->params_addr, (void*)&aps64, - sizeof(aps64)); + if (is_64bit) { + aps.aps64.result = s->status; + cpu_physical_memory_write(s->params_addr, (void*)&aps, sizeof(aps.aps64)); } else { - aps.result = s->status; - cpu_physical_memory_write(s->params_addr, (void*)&aps, - sizeof(aps)); + aps.aps32.result = s->status; + cpu_physical_memory_write(s->params_addr, (void*)&aps, sizeof(aps.aps32)); } } break; diff --git a/include/hw/misc/android_pipe.h b/include/hw/misc/android_pipe.h index 962f2e96bd..2d98fa6d8c 100644 --- a/include/hw/misc/android_pipe.h +++ b/include/hw/misc/android_pipe.h @@ -197,26 +197,32 @@ extern void android_pipe_wake( void* hwpipe, unsigned flags ); #define PIPE_WAKE_READ (1 << 1) /* pipe can now be read from */ #define PIPE_WAKE_WRITE (1 << 2) /* pipe can now be written to */ -struct access_params{ - uint32_t channel; - uint32_t size; - uint32_t address; - uint32_t cmd; - uint32_t result; +struct access_params_32 { + uint32_t channel; /* 0x00 */ + uint32_t size; /* 0x04 */ + uint32_t address; /* 0x08 */ + uint32_t cmd; /* 0x0c */ + uint32_t result; /* 0x10 */ /* reserved for future extension */ - uint32_t flags; + uint32_t flags; /* 0x14 */ }; struct access_params_64 { - uint64_t channel; - uint32_t size; - uint64_t address; - uint32_t cmd; - uint32_t result; + uint64_t channel; /* 0x00 */ + uint32_t size; /* 0x08 */ + uint64_t address; /* 0x0c */ + uint32_t cmd; /* 0x14 */ + uint32_t result; /* 0x18 */ /* reserved for future extension */ - uint32_t flags; + uint32_t flags; /* 0x1c */ }; +union access_params { + struct access_params_32 aps32; + struct access_params_64 aps64; +}; + + extern void android_zero_pipe_init(void); extern void android_pingpong_init(void); extern void android_throttle_init(void); -- cgit v1.2.3