[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio
From: |
Alexander Graf |
Subject: |
[Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio |
Date: |
Thu, 25 Nov 2010 08:35:41 +0100 |
The way we're currently modeling mmio is too simplified. We assume that
every device has the same endianness as the target CPU. In reality,
most devices are little endian (all PCI and ISA ones I'm aware of). Some
are big endian (special system devices) and a very little fraction is
target native endian (fw_cfg).
So instead of assuming every device to be native endianness, let's move
to a model where the device tells us which endianness it's in.
That way we can compile the devices only once and get rid of all the ugly
swap will be done by the underlying layer.
For the same of readability, this patch only introduces the helper framework
but doesn't allow the registering code to set its endianness yet.
Signed-off-by: Alexander Graf <address@hidden>
---
cpu-common.h | 4 ++
exec.c | 122 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 126 insertions(+), 0 deletions(-)
diff --git a/cpu-common.h b/cpu-common.h
index a543b5d..839b236 100644
--- a/cpu-common.h
+++ b/cpu-common.h
@@ -20,6 +20,10 @@
#if !defined(CONFIG_USER_ONLY)
+#define DEVICE_NATIVE_ENDIAN 0
+#define DEVICE_BIG_ENDIAN 1
+#define DEVICE_LITTLE_ENDIAN 2
+
/* address in the RAM (different from a physical address) */
typedef unsigned long ram_addr_t;
diff --git a/exec.c b/exec.c
index db9ff55..f54a360 100644
--- a/exec.c
+++ b/exec.c
@@ -3336,6 +3336,109 @@ static int get_free_io_mem_idx(void)
return -1;
}
+/*
+ * Usually, devices operate in little endian mode. There are devices out
+ * there that operate in big endian too. Each device gets byte swapped
+ * mmio if plugged onto a CPU that does the other endianness.
+ *
+ * CPU Device swap?
+ *
+ * little little no
+ * little big yes
+ * big little yes
+ * big big no
+ */
+#ifdef TARGET_WORDS_BIGENDIAN
+
+typedef struct SwapEndianContainer {
+ CPUReadMemoryFunc *read[3];
+ CPUWriteMemoryFunc *write[3];
+ void *opaque;
+} SwapEndianContainer;
+
+static uint32_t swapendian_mem_readb (void *opaque, target_phys_addr_t addr)
+{
+ uint32_t val;
+ SwapEndianContainer *c = opaque;
+ val = c->read[0](c->opaque, addr);
+ return val;
+}
+
+static uint32_t swapendian_mem_readw(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t val;
+ SwapEndianContainer *c = opaque;
+ val = bswap16(c->read[1](c->opaque, addr));
+ return val;
+}
+
+static uint32_t swapendian_mem_readl(void *opaque, target_phys_addr_t addr)
+{
+ uint32_t val;
+ SwapEndianContainer *c = opaque;
+ val = bswap32(c->read[2](c->opaque, addr));
+ return val;
+}
+
+static CPUReadMemoryFunc * const swapendian_readfn[3]={
+ swapendian_mem_readb,
+ swapendian_mem_readw,
+ swapendian_mem_readl
+};
+
+static void swapendian_mem_writeb(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ SwapEndianContainer *c = opaque;
+ c->write[0](c->opaque, addr, val);
+}
+
+static void swapendian_mem_writew(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ SwapEndianContainer *c = opaque;
+ c->write[1](c->opaque, addr, bswap16(val));
+}
+
+static void swapendian_mem_writel(void *opaque, target_phys_addr_t addr,
+ uint32_t val)
+{
+ SwapEndianContainer *c = opaque;
+ c->write[2](c->opaque, addr, bswap32(val));
+}
+
+static CPUWriteMemoryFunc * const swapendian_writefn[3]={
+ swapendian_mem_writeb,
+ swapendian_mem_writew,
+ swapendian_mem_writel
+};
+
+static void swapendian_init(int io_index)
+{
+ SwapEndianContainer *c = qemu_malloc(sizeof(SwapEndianContainer));
+ int i;
+
+ /* Swap mmio for big endian targets */
+ c->opaque = io_mem_opaque[io_index];
+ for (i = 0; i < 3; i++) {
+ c->read[i] = io_mem_read[io_index][i];
+ c->write[i] = io_mem_write[io_index][i];
+
+ io_mem_read[io_index][i] = swapendian_readfn[i];
+ io_mem_write[io_index][i] = swapendian_writefn[i];
+ }
+ io_mem_opaque[io_index] = c;
+}
+
+static void swapendian_del(int io_index)
+{
+ if (io_mem_read[io_index][0] == swapendian_readfn[0]) {
+ qemu_free(io_mem_opaque[io_index]);
+ }
+}
+
+#endif
+
/* mem_read and mem_write are arrays of functions containing the
function to access byte (index 0), word (index 1) and dword (index
2). Functions can be omitted with a NULL function pointer.
@@ -3349,6 +3452,7 @@ static int cpu_register_io_memory_fixed(int io_index,
void *opaque)
{
int i;
+ int endian = DEVICE_NATIVE_ENDIAN;
if (io_index <= 0) {
io_index = get_free_io_mem_idx();
@@ -3370,6 +3474,22 @@ static int cpu_register_io_memory_fixed(int io_index,
}
io_mem_opaque[io_index] = opaque;
+ switch (endian) {
+ case DEVICE_BIG_ENDIAN:
+#ifndef TARGET_WORDS_BIGENDIAN
+ swapendian_init(io_index);
+#endif
+ break;
+ case DEVICE_LITTLE_ENDIAN:
+#ifdef TARGET_WORDS_BIGENDIAN
+ swapendian_init(io_index);
+#endif
+ break;
+ case DEVICE_NATIVE_ENDIAN:
+ default:
+ break;
+ }
+
return (io_index << IO_MEM_SHIFT);
}
@@ -3385,6 +3505,8 @@ void cpu_unregister_io_memory(int io_table_address)
int i;
int io_index = io_table_address >> IO_MEM_SHIFT;
+ swapendian_del(io_index);
+
for (i=0;i < 3; i++) {
io_mem_read[io_index][i] = unassigned_mem_read[i];
io_mem_write[io_index][i] = unassigned_mem_write[i];
--
1.6.0.2
- [Qemu-devel] [PATCH 00/15] [RFC] MMIO endianness cleanup, Alexander Graf, 2010/11/25
- [Qemu-devel] [PATCH 04/15] dbdma: Make little endian, Alexander Graf, 2010/11/25
- [Qemu-devel] [PATCH 03/15] Make simple io mem handler endian aware, Alexander Graf, 2010/11/25
- [Qemu-devel] [PATCH 06/15] uninorth: Get rid of bswap, Alexander Graf, 2010/11/25
- [Qemu-devel] [PATCH 07/15] e1000: Make little endian, Alexander Graf, 2010/11/25
- [Qemu-devel] [PATCH 12/15] rtl8139: Declare as little endian, Alexander Graf, 2010/11/25
- [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio,
Alexander Graf <=
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Andreas Färber, 2010/11/26
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Alexander Graf, 2010/11/26
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Peter Maydell, 2010/11/26
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Paul Brook, 2010/11/26
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Blue Swirl, 2010/11/27
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Paul Brook, 2010/11/27
- Re: [Qemu-devel] [PATCH 01/15] exec: introduce endianness swapped mmio, Gleb Natapov, 2010/11/28
[Qemu-devel] [PATCH 05/15] pci-host: Delegate bswap to mmio layer, Alexander Graf, 2010/11/25
[Qemu-devel] [PATCH 13/15] heathrow_pic: Declare as little endian, Alexander Graf, 2010/11/25