qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Hollis Blanchard <hollisb@us.ibm.com>
To: Aurelien Jarno <aurelien@aurel32.net>
Cc: kvm-ppc-devel <kvm-ppc-devel@lists.sourceforge.net>,
	qemu-devel@nongnu.org
Subject: Re: [Qemu-devel] Re: [PATCH] e1000: fix endianness issues
Date: Wed, 12 Mar 2008 08:52:00 -0500	[thread overview]
Message-ID: <1205329920.16914.20.camel@diesel> (raw)
In-Reply-To: <20080311224925.GA8753@volta.aurel32.net>

On Tue, 2008-03-11 at 23:49 +0100, Aurelien Jarno wrote:
> On Sat, Mar 08, 2008 at 11:08:48AM -0600, Hollis Blanchard wrote:
> > On Sat, 2008-03-08 at 14:59 +0100, Aurelien Jarno wrote: 
> > > On Fri, Mar 07, 2008 at 11:23:51AM -0600, Hollis Blanchard wrote:
> > > > Below is a patch I'm using to fix rtl8139.c for PowerPC/PowerPC
> > > > target/host combination. It works enough for the target to send a DHCP
> > > > request and get a response from slirp, but other unrelated bugs prevent
> > > > me from testing it more thoroughly. (I'm only sending it now at
> > > > Aurelien's request.) Other code that I know is broken (because I've
> > > > tried to use it) include isa_mmio.c and pci_host.h, but I don't have
> > > > patches for these at this time.
> > > 
> > > 
> > > 
> > > 
> > > > Fix endianness conversion in rtl8139.c.
> > > > 
> > > > PCI data is always in LE format, so convert from LE at the interface to
> > > > "qemu endianness" internally, then convert again on the way back out.
> > > > 
> > > > Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
> > > > 
> > > > diff --git a/qemu/hw/rtl8139.c b/qemu/hw/rtl8139.c
> > > > --- a/qemu/hw/rtl8139.c
> > > > +++ b/qemu/hw/rtl8139.c
> 
> [snip]
> 
> > > > @@ -3091,12 +3067,12 @@ static void rtl8139_mmio_writeb(void *op
> > > >  
> > > >  static void rtl8139_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
> > > >  {
> > > > -    rtl8139_io_writew(opaque, addr & 0xFF, val);
> > > > +    rtl8139_io_writew(opaque, addr & 0xFF, le16_to_cpu(val));
> > > >  }
> > > >  
> > > >  static void rtl8139_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
> > > >  {
> > > > -    rtl8139_io_writel(opaque, addr & 0xFF, val);
> > > > +    rtl8139_io_writel(opaque, addr & 0xFF, le32_to_cpu(val));
> > > >  }
> > > >  
> > > >  static uint32_t rtl8139_mmio_readb(void *opaque, target_phys_addr_t addr)
> > > > @@ -3106,12 +3082,12 @@ static uint32_t rtl8139_mmio_readb(void 
> > > >  
> > > >  static uint32_t rtl8139_mmio_readw(void *opaque, target_phys_addr_t addr)
> > > >  {
> > > > -    return rtl8139_io_readw(opaque, addr & 0xFF);
> > > > +    return cpu_to_le16(rtl8139_io_readw(opaque, addr & 0xFF));
> > > >  }
> > > >  
> > > >  static uint32_t rtl8139_mmio_readl(void *opaque, target_phys_addr_t addr)
> > > >  {
> > > > -    return rtl8139_io_readl(opaque, addr & 0xFF);
> > > > +    return cpu_to_le32(rtl8139_io_readl(opaque, addr & 0xFF));
> > > >  }
> > > >  
> > > 
> > > Are those changes really necessary? The rtl8139 emulation works
> > > correctly on a big endian host (tested with an i386 target). This part
> > > of the patch would probably break it. Unless the Linux driver only does
> > > byte accesses, which are not changed by this patch.
> 
> I have tested this part of the patch on a big endian host (PowerPC), and
> I confirm it breaks the rtl8139 emulation (tested on i386 and mipsel
> targets).

OK, I will do some regression testing too before I submit a patch for
inclusion.

> > Hmm, yes, there is a problem with this patch. In the "touching many
> > 1-byte registers as a single 4-byte access" change to rtl8139_io_readl()
> > above, we made sure that the result was LE. What we should have done is
> > make it host-endianness like all the other return values from
> > rtl8139_io_readl(). Then in rtl8139_mmio_readl(), we know we must swap
> > host->LE.
> > 
> > I don't know why rtl8139 would work today with LE/BE target/host, but if
> > it does, it must be due to swapping in another layer, because this patch
> > is the right thing to do here. If qemu currently swaps 5 times and that
> > comes out the same as swapping once, we still need to fix it... :)
> 
> I hope the discussion on IRC last week-end convinced you that you don't
> need to swap the value depending on the host endianness.

Absolutely not! At least, not with the current qemu design.

> For those who
> haven't followed the discussion, qemu does memory accesses with a couple
> (address, value). The addresses and values are always stored in host 
> endianness, and this does not need to be swapped depending on the host. 
> It may have to be swapped depending on the target, if the value is 
> swapped on the real hardware (bus connected backward, chipset, etc.)
> 
> Thanks to Paul Brook for all the explanations.

The scheme Paul outlined (but hasn't actually proposed as far as I've
seen) involved an end-to-end overhaul of endianness manipulations in
qemu, removing byte swapping from some device emulation and adding some
to bus layers. I still don't understand his entire idea, and I think
some prototype code will be needed to see it. Until/unless that is
implemented, we will continue to require swapping in the device
emulation.

> Basically that means that one part of my e1000 part is actually correct,
> while the other is correct in the case of the MIPS Malta machine, but
> may be wrong for other targets/machines. I am therefore planning to 
> commit the correct part (see patch below), except if someone still have
> some comments on it.
> 
> 
> diff --git a/hw/e1000.c b/hw/e1000.c
> index 1c77afc..e3dbef9 100644
> --- a/hw/e1000.c
> +++ b/hw/e1000.c
> @@ -721,7 +721,7 @@ e1000_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
>      unsigned int index = ((addr - s->mmio_base) & 0x1ffff) >> 2;
> 
>      if (index < NWRITEOPS && macreg_writeops[index])
> -        macreg_writeops[index](s, index, le32_to_cpu(val));
> +        macreg_writeops[index](s, index, val);
>      else if (index < NREADOPS && macreg_readops[index])
>          DBGOUT(MMIO, "e1000_mmio_writel RO %x: 0x%04x\n", index<<2, val);
>      else

This cannot work. PowerPC targets have MMIO instructions that can
produce "val" in either BE or LE format. Given that e1000 is a PCI
device, val in this case is LE, and will need swapping on a BE host.

The only reason this code might work for MIPS is due to a *lack* of
endianness handling in the gt64xxx.c bridge emulation, but that is a
bug, not a feature. :)

-- 
Hollis Blanchard
IBM Linux Technology Center

  reply	other threads:[~2008-03-12 13:54 UTC|newest]

Thread overview: 8+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-03-07 17:23 [Qemu-devel] Re: [PATCH] e1000: fix endianness issues Hollis Blanchard
2008-03-08 13:59 ` Aurelien Jarno
2008-03-08 17:08   ` Hollis Blanchard
2008-03-11 22:49     ` Aurelien Jarno
2008-03-12 13:52       ` Hollis Blanchard [this message]
2008-03-12 14:38         ` Aurelien Jarno
2008-03-12 22:07           ` Aurelien Jarno
2008-03-13  2:59             ` Hollis Blanchard

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1205329920.16914.20.camel@diesel \
    --to=hollisb@us.ibm.com \
    --cc=aurelien@aurel32.net \
    --cc=kvm-ppc-devel@lists.sourceforge.net \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).