On Fri, Sep 23, 2016 at 10:19:50AM -0700, Eric Nelson wrote: > Oddly, it does prevent the vast majority (90%+) of the alignment errors. > > I believe this is because the compiler is generating an ldm instruction > when the ntohl() call is used, but I'm stumped about why these aren't > generating faults:
ldm generates alignment faults when the address is not aligned to a 32-bit boundary. ldr on ARMv6+ does not. > I don't think that's the case. > > # CONFIG_IPV6_GRE is not set > > Hmm... Instrumenting the kernel, it seems that iphdr **is** aligned on > a 4-byte boundary. > > Does the ldm instruction require 8-byte alignment? > > There's definitely a compiler-version dependency involved here, > since using gcc 4.9 also reduced the number of faults dramatically. Well, I don't think it's that gcc related: User: 0 System: 312855 (ip6_route_input+0x6c/0x1e0) Skipped: 0 Half: 0 Word: 0 DWord: 2 Multi: 312853 c06d8998 <ip6_route_input>: c06d89ac: e1a04000 mov r4, r0 c06d89b0: e1d489b4 ldrh r8, [r4, #148] ; 0x94 c06d89b8: e594a0a0 ldr sl, [r4, #160] ; 0xa0 c06d89cc: e08ac008 add ip, sl, r8 c06d89d4: e28c3018 add r3, ip, #24 c06d89dc: e28c7008 add r7, ip, #8 c06d89e4: e893000f ldm r3, {r0, r1, r2, r3} c06d89ec: e24be044 sub lr, fp, #68 ; 0x44 c06d89f4: e24b5054 sub r5, fp, #84 ; 0x54 c06d89fc: e885000f stm r5, {r0, r1, r2, r3} c06d8a04: e897000f ldm r7, {r0, r1, r2, r3} c06d8a10: e88e000f stm lr, {r0, r1, r2, r3} This is from: struct flowi6 fl6 = { .flowi6_iif = l3mdev_fib_oif(skb->dev), .daddr = iph->daddr, .saddr = iph->saddr, .flowlabel = ip6_flowinfo(iph), .flowi6_mark = skb->mark, .flowi6_proto = iph->nexthdr, }; specifically, I suspect, the saddr and daddr initialisations. There's not much to get away from this - the FEC on iMX requires a 16-byte alignment for DMA addresses, which violates the network stack's requirement for the ethernet packet to be received with a two byte offset. So the IP header (and IPv6 headers) will always be mis-aligned in memory, which leads to a huge number of alignment faults. There's not much getting away from this - the problem is not in the networking stack, but the FEC hardware/network driver. See: struct fec_enet_private *fep = netdev_priv(ndev); int off; off = ((unsigned long)skb->data) & fep->rx_align; if (off) skb_reserve(skb, fep->rx_align + 1 - off); bdp->cbd_bufaddr = cpu_to_fec32(dma_map_single(&fep->pdev->dev, skb->data, FEC_ENET_RX_FRSIZE - fep->rx_align, DMA_FROM_DEVICE)); in fec_enet_new_rxbdp(). -- RMK's Patch system: http://www.armlinux.org.uk/developer/patches/ FTTC broadband for 0.8mile line: currently at 9.6Mbps down 400kbps up according to speedtest.net.