Patchwork [01/16] memory: move endianness compensation to memory core

login
register
mail settings
Submitter Avi Kivity
Date Jan. 2, 2012, 4:33 p.m.
Message ID <1325522015-503-2-git-send-email-avi@redhat.com>
Download mbox | patch
Permalink /patch/133869/
State New
Headers show

Comments

Avi Kivity - Jan. 2, 2012, 4:33 p.m.
Instead of doing device endianness compensation in cpu_register_io_memory(),
do it in the memory core.

Signed-off-by: Avi Kivity <avi@redhat.com>
---
 exec-obsolete.h |    2 +-
 exec.c          |  142 ++++---------------------------------------------------
 memory.c        |   37 ++++++++++++--
 3 files changed, 41 insertions(+), 140 deletions(-)
Andreas Färber - Jan. 5, 2012, 6:26 p.m.
Am 02.01.2012 17:33, schrieb Avi Kivity:
> Instead of doing device endianness compensation in cpu_register_io_memory(),
> do it in the memory core.
> 
> Signed-off-by: Avi Kivity <avi@redhat.com>

This further broke PReP boot (Etch 2.4.x kernel):

be675c972088eba210e18dc125613e9f205a6bfb is the first bad commit
commit be675c972088eba210e18dc125613e9f205a6bfb
Author: Avi Kivity <avi@redhat.com>
Date:   Sun Nov 20 16:22:55 2011 +0200

    memory: move endianness compensation to memory core

    Instead of doing device endianness compensation in
cpu_register_io_memory(),
    do it in the memory core.

    Signed-off-by: Avi Kivity <avi@redhat.com>
    Reviewed-by: Richard Henderson <rth@twiddle.net>

:100644 100644 698d7fc4118edc71f00de6f87908bb4031df5b5a
79f989c65469ad068448f334b692b7ed60f1704a M	exec-obsolete.h
:100644 100644 28c057c08671a8b6bfa90d94e873460bda7afa69
507d37c61761d71d8b39d0073724ceb0200ff6d4 M	exec.c
:100644 100644 868ffd0bc5a1eea7a6f9deb9d6d39f689b89e014
6f9fea15ad1890c63c285fd62e72b8614030dd4f M	memory.c

My wild guess is that prep_pci.c is swapping too much or not enough now.
The bswap calls in the native-endian PCIIO there look fishy.

Andreas


register PCI host 'pci-bridge' 'pci' '<null>' 'PREP Host PCI Bridge -
Motorola Raven'
register 'pci-bridge' 'pci' '<null>' 'PREP Host PCI Bridge - Motorola
Raven' 0x80000000 in 'device-tree' 0xffffffff
Done 582b000 582b880
PCI device '<null>' 0 11 0 has no reg properties:
PCI device '<null>' 0 11 0 has no assigned addresses properties:
register pci device 'Qemu VGA' 0000000c 'display' 'VGA' 'Qemu VGA'
register 'Qemu VGA' 'display' 'VGA' 'Qemu VGA' 0x0000000c in
'pci-bridge' 0x80000000
Done 582b880 582b980
PCI device 'Qemu VGA' 0 12 0 reg properties:
  addr: 82006010 00000000 f0000000 size: 00000000 00800000
PCI device 'Qemu VGA' 0 12 0 assigned addresses properties:
  addr: 82006010 00000000 f0000000 size: 00000000 00800000
PPC Open Hack'Ware BIOS for qemu version 0.4.1
Build 2007-10-01 06:42:47
Copyright 2003-2005 Jocelyn Mayer

Memory size: 256 MB.
Booting from device m
ide0: drive 0: Hard Disk
ERROR: OF_property_copy cannot get property 'hd' for aliases
ERROR: WIN_READ_NATIVE_MAX : status 50 != 0x40
ide0: drive 1: none
ide1: drive 0: CD-ROM
ERROR: OF_property_copy cannot get property 'cd' for aliases
ERROR: ATAPI TEST_UNIT_READY : status 41 != 0x40
ide1: drive 1: none
Probe partitions for device m
ERROR: No MSDOS signature (38 0 0 0)
Use bloc device as raw partition
Boot partition: 0 9401fff8 9401fff8 0
ERROR: OF_property_copy cannot get property 'alias' for <null>
boot device: 5832080 image 1000000 size 1266665
Probe filesystem on unknown PREP partition 'PREP boot' (bootable) 5832100
Fix bootfile
Partition is bootable (0)
bd_set_boot_part: part 5832100 (0) 0
Boot partition: 5832100 582e400 582e400 0
boot device: 5832080
ERROR: Found boot partition : 5832100 582e400
ERROR: Not a MACH-O file
ERROR: Not an Apple CHRP boot file !
dest 100000 entry 00000200 => 100200
Load raw file into memory at 100000 1266665 (001353e9) 0 (00000000)
Boot: 00040000 e9531300 00000000 00000000
Bootinfos at : 300000

Now boot it... (0)

stack: 5bfff80 malloc_base: 0 0x05800000 0x06000000
PREP boot... 100200 100000
loaded at:     00100200 0023DDE8
relocated to:  00800000 0093DBE8
board data at: 05837000 0583DA0C
relocated to:  0093414C 0093AB58
zimage at:     00805B9C 00933AC6
avail ram:     00400000 00800000

Linux/PPC load: ide0=0x1f0,0x3f6,13 ide1=0x170,0x376,13
netdev=9,0x300,eth0 console=ttyS0 console=tty0 root=/dev/hda3 ro
Uncompressing Linux...done.
Now booting the kernel
Memory BAT mapping: BAT2=256Mb, BAT3=0Mb, residual: 0Mb
Total memory = 256MB; using 512kB for hash table (at c0300000)
Linux version 2.4.36.1 (root@debianppc) (gcc version 4.1.2 20061115
(prerelease) (Debian 4.1.1-21)) #3 Thu Feb 21 10:14:55 CET 2008
PReP architecture
On node 0 totalpages: 65536
zone(0): 65536 pages.
zone(1): 0 pages.
zone(2): 0 pages.
Kernel command line: ide0=0x1f0,0x3f6,13 ide1=0x170,0x376,13
netdev=9,0x300,eth0 console=ttyS0 console=tty0 root=/dev/hda3 ro
ide_setup: ide0=0x1f0,0x3f6,13

ide_setup: ide1=0x170,0x376,13

time_init: decrementer frequency = 28.252727 MHz
Warning: real time clock seems stuck!
Console: colour dummy device 80x25
Calibrating delay loop... 251.49 BogoMIPS
Memory: 255232k available (2052k kernel code, 816k data, 168k init, 0k
highmem)
Dentry cache hash table entries: 32768 (order: 6, 262144 bytes)
Inode cache hash table entries: 16384 (order: 5, 131072 bytes)
Mount cache hash table entries: 512 (order: 0, 4096 bytes)
Buffer cache hash table entries: 16384 (order: 4, 65536 bytes)
Page-cache hash table entries: 65536 (order: 6, 262144 bytes)
POSIX conformance testing by UNIFIX
PCI: Probing PCI hardware
Setting PCI interrupts for a "Mesquite cPCI (MCP750)"
PCI: Cannot allocate resource region 0 of device 00:0c.0
PCI: moved device 00:0c.0 resource 0 (1208) to 0
Linux NET4.0 for Linux 2.4
Based upon Swansea University Computer Society NET3.039
Initializing RT netlink socket
Starting kswapd
Journalled Block Device driver loaded
Installing knfsd (copyright (C) 1996 okir@monad.swb.de).
udf: registering filesystem
vga16fb: mapped to 0xf00a0000
Console: switching to colour frame buffer device 80x30
fb0: VGA16 VGA frame buffer device
pty: 256 Unix98 ptys configured
Serial driver version 5.05c (2001-07-08) with MANY_PORTS SHARE_IRQ
SERIAL_PCI enabled
ttyS00 at 0x03f8 (irq = 4) is a 16550A
rtc: I/O resource 70 is not free.
Generic RTC Driver v1.07
Floppy drive(s): fd0 is 2.88M
FDC 0 is a S82078B
ne.c:v1.10 9/23/94 Donald Becker (becker@scyld.com)
Last modified Nov 1, 2000 by Paul Gortmaker
NE*000 ethercard probe at 0x300: 52 54 00 12 34 56
eth0: NE2000 found at 0x300, using IRQ 9.
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
loop: loaded (max 8 devices)
PPP generic driver version 2.4.2
PPP Deflate Compression module registered
PPP BSD Compression module registered
Universal TUN/TAP device driver 1.5 (C)1999-2002 Maxim Krasnyansky
Uniform Multi-Platform E-IDE driver Revision: 7.00beta4-2.4
ide: Assuming 33MHz system bus speed for PIO modes; override with idebus=xx
Probing IDE interface ide0...
hda: EQUMH RADDSI K, ATA DISK drive
Probing IDE interface ide1...
hdc: EQUMD DVR-MO, ATAPI cdrom or floppy?, assuming FLOPPY drive
Probing IDE interface ide2...
ide2: Wait for ready failed before probe !
Probing IDE interface ide3...
ide3: Wait for ready failed before probe !
ide0 at 0x1f0-0x1f7,0x3f6 on irq 13
ide1 at 0x170-0x177,0x376 on irq 13 (shared with ide0)
hda: attached ide-disk driver.
hda: 0 sectors (0 MB) w/1KiB Cache, CHS=24856/0/0
hda: INVALID GEOMETRY: 0 PHYSICAL HEADS?
Partition check:
 hdc:end_request: I/O error, dev 16:00 (hdc), sector 0
end_request: I/O error, dev 16:00 (hdc), sector 2
end_request: I/O error, dev 16:00 (hdc), sector 4
end_request: I/O error, dev 16:00 (hdc), sector 6
end_request: I/O error, dev 16:00 (hdc), sector 0
end_request: I/O error, dev 16:00 (hdc), sector 2
end_request: I/O error, dev 16:00 (hdc), sector 4
end_request: I/O error, dev 16:00 (hdc), sector 6
 unable to read partition table
Macintosh non-volatile memory driver v1.0
mice: PS/2 mouse device common for all mice
NET4: Linux TCP/IP 1.0 for NET4.0
IP Protocols: ICMP, UDP, TCP, IGMP
IP: routing cache hash table of 2048 buckets, 16Kbytes
TCP: Hash tables configured (established 16384 bind 32768)
NET4: Unix domain sockets 1.0/SMP for Linux NET4.0.
hda3: bad access: block=2, count=2
end_request: I/O error, dev 03:03 (hda), sector 2
EXT3-fs: unable to read superblock
hda3: bad access: block=2, count=2
end_request: I/O error, dev 03:03 (hda), sector 2
EXT2-fs: unable to read superblock
hda3: bad access: block=0, count=8
end_request: I/O error, dev 03:03 (hda), sector 0
hda3: bad access: block=2, count=6
end_request: I/O error, dev 03:03 (hda), sector 2
hda3: bad access: block=4, count=4
end_request: I/O error, dev 03:03 (hda), sector 4
hda3: bad access: block=6, count=2
end_request: I/O error, dev 03:03 (hda), sector 6
hda3: bad access: block=0, count=16
end_request: I/O error, dev 03:03 (hda), sector 0
hda3: bad access: block=2, count=14
end_request: I/O error, dev 03:03 (hda), sector 2
hda3: bad access: block=4, count=12
end_request: I/O error, dev 03:03 (hda), sector 4
hda3: bad access: block=6, count=10
end_request: I/O error, dev 03:03 (hda), sector 6
hda3: bad access: block=8, count=8
end_request: I/O error, dev 03:03 (hda), sector 8
hda3: bad access: block=10, count=6
end_request: I/O error, dev 03:03 (hda), sector 10
hda3: bad access: block=12, count=4
end_request: I/O error, dev 03:03 (hda), sector 12
hda3: bad access: block=14, count=2
end_request: I/O error, dev 03:03 (hda), sector 14
hda3: bad access: block=8, count=16
end_request: I/O error, dev 03:03 (hda), sector 8
hda3: bad access: block=10, count=14
end_request: I/O error, dev 03:03 (hda), sector 10
hda3: bad access: block=12, count=12
end_request: I/O error, dev 03:03 (hda), sector 12
hda3: bad access: block=14, count=10
end_request: I/O error, dev 03:03 (hda), sector 14
hda3: bad access: block=16, count=8
end_request: I/O error, dev 03:03 (hda), sector 16
hda3: bad access: block=18, count=6
end_request: I/O error, dev 03:03 (hda), sector 18
hda3: bad access: block=20, count=4
end_request: I/O error, dev 03:03 (hda), sector 20
hda3: bad access: block=22, count=2
end_request: I/O error, dev 03:03 (hda), sector 22
hda3: bad access: block=16, count=16
end_request: I/O error, dev 03:03 (hda), sector 16
hda3: bad access: block=18, count=14
end_request: I/O error, dev 03:03 (hda), sector 18
hda3: bad access: block=20, count=12
end_request: I/O error, dev 03:03 (hda), sector 20
hda3: bad access: block=22, count=10
end_request: I/O error, dev 03:03 (hda), sector 22
hda3: bad access: block=24, count=8
end_request: I/O error, dev 03:03 (hda), sector 24
hda3: bad access: block=26, count=6
end_request: I/O error, dev 03:03 (hda), sector 26
hda3: bad access: block=28, count=4
end_request: I/O error, dev 03:03 (hda), sector 28
hda3: bad access: block=30, count=2
end_request: I/O error, dev 03:03 (hda), sector 30
hda3: bad access: block=24, count=8
end_request: I/O error, dev 03:03 (hda), sector 24
hda3: bad access: block=26, count=6
end_request: I/O error, dev 03:03 (hda), sector 26
hda3: bad access: block=28, count=4
end_request: I/O error, dev 03:03 (hda), sector 28
hda3: bad access: block=30, count=2
end_request: I/O error, dev 03:03 (hda), sector 30
cramfs: wrong magic
hda3: bad access: block=0, count=1
end_request: I/O error, dev 03:03 (hda), sector 0
FAT: unable to read boot sector
hda3: bad access: block=0, count=1
end_request: I/O error, dev 03:03 (hda), sector 0
FAT: unable to read boot sector
hda3: bad access: block=64, count=2
end_request: I/O error, dev 03:03 (hda), sector 64
isofs_read_super: bread failed, dev=03:03, iso_blknum=16, block=32
hda3: bad access: block=2, count=1
end_request: I/O error, dev 03:03 (hda), sector 2
HFS+-fs: unable to read VHDR or MDB
hda3: bad access: block=2, count=1
end_request: I/O error, dev 03:03 (hda), sector 2
hfs_fs: unable to read block 0x00000002 from dev 03:03
hfs_fs: Unable to read superblock
hda3: bad access: block=0, count=1
end_request: I/O error, dev 03:03 (hda), sector 0
hfs_fs: unable to read block 0x00000000 from dev 03:03
hfs_fs: Unable to read block 0.
You didn't specify the type of your ufs filesystem

mount -t ufs -o
ufstype=sun|sunx86|44bsd|old|hp|nextstep|netxstep-cd|openstep ...

>>>WARNING<<< Wrong ufstype may corrupt your filesystem, default is
ufstype=old
hda3: bad access: block=16, count=2
end_request: I/O error, dev 03:03 (hda), sector 16
hda3: bad access: block=0, count=2
end_request: I/O error, dev 03:03 (hda), sector 0
romfs: unable to read superblock
hda3: bad access: block=64, count=4
end_request: I/O error, dev 03:03 (hda), sector 64
hda3: bad access: block=1248, count=4
end_request: I/O error, dev 03:03 (hda), sector 1248
hda3: bad access: block=1024, count=4
end_request: I/O error, dev 03:03 (hda), sector 1024
UDF-fs: No partition found (1)
Kernel panic: VFS: Unable to mount root fs on 03:03
 <0>Rebooting in 180 seconds..


> ---
>  exec-obsolete.h |    2 +-
>  exec.c          |  142 ++++---------------------------------------------------
>  memory.c        |   37 ++++++++++++--
>  3 files changed, 41 insertions(+), 140 deletions(-)
> 
> diff --git a/exec-obsolete.h b/exec-obsolete.h
> index 698d7fc..79f989c 100644
> --- a/exec-obsolete.h
> +++ b/exec-obsolete.h
> @@ -33,7 +33,7 @@ void qemu_ram_free_from_ptr(ram_addr_t addr);
>  
>  int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
>                             CPUWriteMemoryFunc * const *mem_write,
> -                           void *opaque, enum device_endian endian);
> +                           void *opaque);
>  void cpu_unregister_io_memory(int table_address);
>  
>  void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
> diff --git a/exec.c b/exec.c
> index 28c057c..507d37c 100644
> --- a/exec.c
> +++ b/exec.c
> @@ -3507,8 +3507,7 @@ static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
>      mmio = g_malloc0(sizeof(subpage_t));
>  
>      mmio->base = base;
> -    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio,
> -                                            DEVICE_NATIVE_ENDIAN);
> +    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
>  #if defined(DEBUG_SUBPAGE)
>      printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
>             mmio, base, TARGET_PAGE_SIZE, subpage_memory);
> @@ -3532,106 +3531,6 @@ 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
> - */
> -
> -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 = g_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]) {
> -        g_free(io_mem_opaque[io_index]);
> -    }
> -}
> -
>  /* 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.
> @@ -3642,7 +3541,7 @@ static void swapendian_del(int io_index)
>  static int cpu_register_io_memory_fixed(int io_index,
>                                          CPUReadMemoryFunc * const *mem_read,
>                                          CPUWriteMemoryFunc * const *mem_write,
> -                                        void *opaque, enum device_endian endian)
> +                                        void *opaque)
>  {
>      int i;
>  
> @@ -3666,30 +3565,14 @@ 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);
>  }
>  
>  int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
>                             CPUWriteMemoryFunc * const *mem_write,
> -                           void *opaque, enum device_endian endian)
> +                           void *opaque)
>  {
> -    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque, endian);
> +    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
>  }
>  
>  void cpu_unregister_io_memory(int io_table_address)
> @@ -3697,8 +3580,6 @@ 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];
> @@ -3712,23 +3593,18 @@ static void io_mem_init(void)
>      int i;
>  
>      cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read,
> -                                 unassigned_mem_write, NULL,
> -                                 DEVICE_NATIVE_ENDIAN);
> +                                 unassigned_mem_write, NULL);
>      cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read,
> -                                 unassigned_mem_write, NULL,
> -                                 DEVICE_NATIVE_ENDIAN);
> +                                 unassigned_mem_write, NULL);
>      cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
> -                                 notdirty_mem_write, NULL,
> -                                 DEVICE_NATIVE_ENDIAN);
> +                                 notdirty_mem_write, NULL);
>      cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
> -                                 subpage_ram_write, NULL,
> -                                 DEVICE_NATIVE_ENDIAN);
> +                                 subpage_ram_write, NULL);
>      for (i=0; i<5; i++)
>          io_mem_used[i] = 1;
>  
>      io_mem_watch = cpu_register_io_memory(watch_mem_read,
> -                                          watch_mem_write, NULL,
> -                                          DEVICE_NATIVE_ENDIAN);
> +                                          watch_mem_write, NULL);
>  }
>  
>  static void memory_map_init(void)
> diff --git a/memory.c b/memory.c
> index 868ffd0..6f9fea1 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -857,6 +857,15 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
>      cpu_unregister_io_memory(mr->ram_addr & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
>  }
>  
> +static bool memory_region_wrong_endianness(MemoryRegion *mr)
> +{
> +#ifdef TARGET_BIG_ENDIAN
> +    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
> +#else
> +    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
> +#endif
> +}
> +
>  void memory_region_init(MemoryRegion *mr,
>                          const char *name,
>                          uint64_t size)
> @@ -967,12 +976,24 @@ static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
>  
>  static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
>  {
> -    return memory_region_read_thunk_n(mr, addr, 2);
> +    uint32_t data;
> +
> +    data = memory_region_read_thunk_n(mr, addr, 2);
> +    if (memory_region_wrong_endianness(mr)) {
> +        data = bswap16(data);
> +    }
> +    return data;
>  }
>  
>  static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
>  {
> -    return memory_region_read_thunk_n(mr, addr, 4);
> +    uint32_t data;
> +
> +    data = memory_region_read_thunk_n(mr, addr, 4);
> +    if (memory_region_wrong_endianness(mr)) {
> +        data = bswap32(data);
> +    }
> +    return data;
>  }
>  
>  static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
> @@ -984,12 +1005,18 @@ static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
>  static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
>                                          uint32_t data)
>  {
> +    if (memory_region_wrong_endianness(mr)) {
> +        data = bswap16(data);
> +    }
>      memory_region_write_thunk_n(mr, addr, 2, data);
>  }
>  
>  static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
>                                          uint32_t data)
>  {
> +    if (memory_region_wrong_endianness(mr)) {
> +        data = bswap32(data);
> +    }
>      memory_region_write_thunk_n(mr, addr, 4, data);
>  }
>  
> @@ -1014,8 +1041,7 @@ static void memory_region_prepare_ram_addr(MemoryRegion *mr)
>      mr->destructor = memory_region_destructor_iomem;
>      mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
>                                            memory_region_write_thunk,
> -                                          mr,
> -                                          mr->ops->endianness);
> +                                          mr);
>      mr->backend_registered = true;
>  }
>  
> @@ -1082,8 +1108,7 @@ void memory_region_init_rom_device(MemoryRegion *mr,
>      mr->ram_addr = qemu_ram_alloc(size, mr);
>      mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
>                                             memory_region_write_thunk,
> -                                           mr,
> -                                           mr->ops->endianness);
> +                                           mr);
>      mr->ram_addr |= IO_MEM_ROMD;
>      mr->backend_registered = true;
>  }
Andreas Färber - Jan. 7, 2012, 7:52 a.m.
Am 02.01.2012 17:33, schrieb Avi Kivity:
> Instead of doing device endianness compensation in cpu_register_io_memory(),
> do it in the memory core.
> 
> Signed-off-by: Avi Kivity <avi@redhat.com>

> diff --git a/exec.c b/exec.c
> index 28c057c..507d37c 100644
> --- a/exec.c
> +++ b/exec.c

> @@ -3666,30 +3565,14 @@ 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);
>  }

> diff --git a/memory.c b/memory.c
> index 868ffd0..6f9fea1 100644
> --- a/memory.c
> +++ b/memory.c
> @@ -857,6 +857,15 @@ static void memory_region_destructor_rom_device(MemoryRegion *mr)
>      cpu_unregister_io_memory(mr->ram_addr & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
>  }
>  
> +static bool memory_region_wrong_endianness(MemoryRegion *mr)
> +{
> +#ifdef TARGET_BIG_ENDIAN

This should've been TARGET_WORDS_BIGENDIAN. Patch coming up.

Andreas

> +    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
> +#else
> +    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
> +#endif
> +}

Patch

diff --git a/exec-obsolete.h b/exec-obsolete.h
index 698d7fc..79f989c 100644
--- a/exec-obsolete.h
+++ b/exec-obsolete.h
@@ -33,7 +33,7 @@  void qemu_ram_free_from_ptr(ram_addr_t addr);
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque, enum device_endian endian);
+                           void *opaque);
 void cpu_unregister_io_memory(int table_address);
 
 void cpu_register_physical_memory_log(target_phys_addr_t start_addr,
diff --git a/exec.c b/exec.c
index 28c057c..507d37c 100644
--- a/exec.c
+++ b/exec.c
@@ -3507,8 +3507,7 @@  static int subpage_register (subpage_t *mmio, uint32_t start, uint32_t end,
     mmio = g_malloc0(sizeof(subpage_t));
 
     mmio->base = base;
-    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio,
-                                            DEVICE_NATIVE_ENDIAN);
+    subpage_memory = cpu_register_io_memory(subpage_read, subpage_write, mmio);
 #if defined(DEBUG_SUBPAGE)
     printf("%s: %p base " TARGET_FMT_plx " len %08x %d\n", __func__,
            mmio, base, TARGET_PAGE_SIZE, subpage_memory);
@@ -3532,106 +3531,6 @@  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
- */
-
-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 = g_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]) {
-        g_free(io_mem_opaque[io_index]);
-    }
-}
-
 /* 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.
@@ -3642,7 +3541,7 @@  static void swapendian_del(int io_index)
 static int cpu_register_io_memory_fixed(int io_index,
                                         CPUReadMemoryFunc * const *mem_read,
                                         CPUWriteMemoryFunc * const *mem_write,
-                                        void *opaque, enum device_endian endian)
+                                        void *opaque)
 {
     int i;
 
@@ -3666,30 +3565,14 @@  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);
 }
 
 int cpu_register_io_memory(CPUReadMemoryFunc * const *mem_read,
                            CPUWriteMemoryFunc * const *mem_write,
-                           void *opaque, enum device_endian endian)
+                           void *opaque)
 {
-    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque, endian);
+    return cpu_register_io_memory_fixed(0, mem_read, mem_write, opaque);
 }
 
 void cpu_unregister_io_memory(int io_table_address)
@@ -3697,8 +3580,6 @@  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];
@@ -3712,23 +3593,18 @@  static void io_mem_init(void)
     int i;
 
     cpu_register_io_memory_fixed(IO_MEM_ROM, error_mem_read,
-                                 unassigned_mem_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 unassigned_mem_write, NULL);
     cpu_register_io_memory_fixed(IO_MEM_UNASSIGNED, unassigned_mem_read,
-                                 unassigned_mem_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 unassigned_mem_write, NULL);
     cpu_register_io_memory_fixed(IO_MEM_NOTDIRTY, error_mem_read,
-                                 notdirty_mem_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 notdirty_mem_write, NULL);
     cpu_register_io_memory_fixed(IO_MEM_SUBPAGE_RAM, subpage_ram_read,
-                                 subpage_ram_write, NULL,
-                                 DEVICE_NATIVE_ENDIAN);
+                                 subpage_ram_write, NULL);
     for (i=0; i<5; i++)
         io_mem_used[i] = 1;
 
     io_mem_watch = cpu_register_io_memory(watch_mem_read,
-                                          watch_mem_write, NULL,
-                                          DEVICE_NATIVE_ENDIAN);
+                                          watch_mem_write, NULL);
 }
 
 static void memory_map_init(void)
diff --git a/memory.c b/memory.c
index 868ffd0..6f9fea1 100644
--- a/memory.c
+++ b/memory.c
@@ -857,6 +857,15 @@  static void memory_region_destructor_rom_device(MemoryRegion *mr)
     cpu_unregister_io_memory(mr->ram_addr & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
 }
 
+static bool memory_region_wrong_endianness(MemoryRegion *mr)
+{
+#ifdef TARGET_BIG_ENDIAN
+    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
+#else
+    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
+#endif
+}
+
 void memory_region_init(MemoryRegion *mr,
                         const char *name,
                         uint64_t size)
@@ -967,12 +976,24 @@  static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
 
 static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
 {
-    return memory_region_read_thunk_n(mr, addr, 2);
+    uint32_t data;
+
+    data = memory_region_read_thunk_n(mr, addr, 2);
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap16(data);
+    }
+    return data;
 }
 
 static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
 {
-    return memory_region_read_thunk_n(mr, addr, 4);
+    uint32_t data;
+
+    data = memory_region_read_thunk_n(mr, addr, 4);
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap32(data);
+    }
+    return data;
 }
 
 static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
@@ -984,12 +1005,18 @@  static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
 static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
                                         uint32_t data)
 {
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap16(data);
+    }
     memory_region_write_thunk_n(mr, addr, 2, data);
 }
 
 static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
                                         uint32_t data)
 {
+    if (memory_region_wrong_endianness(mr)) {
+        data = bswap32(data);
+    }
     memory_region_write_thunk_n(mr, addr, 4, data);
 }
 
@@ -1014,8 +1041,7 @@  static void memory_region_prepare_ram_addr(MemoryRegion *mr)
     mr->destructor = memory_region_destructor_iomem;
     mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
                                           memory_region_write_thunk,
-                                          mr,
-                                          mr->ops->endianness);
+                                          mr);
     mr->backend_registered = true;
 }
 
@@ -1082,8 +1108,7 @@  void memory_region_init_rom_device(MemoryRegion *mr,
     mr->ram_addr = qemu_ram_alloc(size, mr);
     mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
                                            memory_region_write_thunk,
-                                           mr,
-                                           mr->ops->endianness);
+                                           mr);
     mr->ram_addr |= IO_MEM_ROMD;
     mr->backend_registered = true;
 }