alignment faults in 3.6
Michael Hope
michael.hope at linaro.org
Thu Oct 4 20:58:05 EDT 2012
On 5 October 2012 12:10, Rob Herring <robherring2 at gmail.com> wrote:
> I've been scratching my head with a "scheduling while atomic" bug I
> started seeing on 3.6. I can easily reproduce this problem when doing a
> wget on my system. It ultimately seems to be a combination of factors.
> The "scheduling while atomic" bug is triggered in do_alignment which
> gets triggered by this code in net/ipv4/af_inet.c, line 1356:
>
> id = ntohl(*(__be32 *)&iph->id);
> flush = (u16)((ntohl(*(__be32 *)iph) ^ skb_gro_len(skb)) | (id ^ IP_DF));
> id >>= 16;
>
> This code compiles into this using "gcc version 4.6.3 (Ubuntu/Linaro
> 4.6.3-1ubuntu5)":
>
> c02ac020: e8920840 ldm r2, {r6, fp}
> c02ac024: e6bfbf3b rev fp, fp
> c02ac028: e6bf6f36 rev r6, r6
> c02ac02c: e22bc901 eor ip, fp, #16384 ; 0x4000
> c02ac030: e0266008 eor r6, r6, r8
> c02ac034: e18c6006 orr r6, ip, r6
>
> which generates alignment faults on the ldm. These are silent until this
> commit is applied:
Hi Rob. I assume that iph is something like:
struct foo {
u32 x;
char id[8];
};
struct foo *iph;
GCC merged the two adjacent loads of x and id into one ldm. This is
an ARM specific optimisation done in load_multiple_sequence() and
enabled with -fpeephole2.
I think the assembly is correct - GCC knows that iph is aligned and
knows the offsets of both x and id. Happy to be corrected if I'm
wrong, but I think the assembly is valid given the C code.
-- Michael
More information about the linux-arm-kernel
mailing list