The 1117 snapshot alignment bug
I got a kernel unaligned access bug:
cp[31284]: Unaligned reference while in kernel
30
psr : 00001010080a6038 ifs : 8000000000000813 ip : [<e00000000063d170>]
unat: 0000000000000000 pfs : 000000000000040e rsc : 0000000000000003
rnat: 0000000000000008 bsps: 000000000001003e pr : 0000000000190293
ldrs: 0000000000000000 ccv : 0000000000000000 fpsr: 0009804c8270033f b0 : e000000000633b40 b6 : e00000000063d0e0 b7 : e000000000521140 f6 : 0fff3fffffffff0000000 f7 : 0ffe68000000000000000
f8 : 1000a8000000000000000 f9 : 1000a8000000000000000
r1 : e000000000b85a80 r2 : 0000000000000001 r3 : e000000008f3fbc8 r8 : e00000000063d0e0 r9 : 0000000000000309 r10 : 0000000000000000 r11 : 0000000000190093 r12 : e000000008f3fbf0 r13 : e000000008f38000 r14 : 000000000000001c r15 : e00000002c9c4740 r16 : e000000008f3fcd4 r17 : e000000008f3fcb8 r18 : e000000008f3fcc0 r19 : e000000008f3fcf0 r20 : e000000008f3fcc8 r21 : e000000008f3fc88 r22 : e0000000296a9028 r23 : 0000000000000c00 r24 : e0000000296a91f8 r25 : 0000000000000c00 r26 : e0000000296a9208 r27 : e000000008f3fd84 r28 : e000000008f3fdc8 r29 : e000000008f3fd60 r30 : 0000000000000002 r31 : 0000000000000000 r32 : 0000000000000000 r33 : 0000000000000000 r34 : 0000000000000000 r35 : 0000000000000000 r36 : 0000000000000000 r37 : 0000000000000000 r38 : 0000000000000000 r39 : 0000000000000000 r40 : 0000000000000000 r41 : 0000000000000000 r42 : 0000000000000000 r43 : 0000000000000000 r44 : 0000000000000000 r45 : 0000000000000000 r46 : 0000000000000000 r47 : 0000000000000000 r48 : 0000000000000000 r49 : 0000000000000000 r50 : 0000000000000000
when I copied over NFS. I believe it is a compiler bug.
# gcc al.c # a.out a.out(466): unaligned access to 0x80000ffffffff8bc, ip=0x4000000000000760 0x80000ffffffff890 0x80000ffffffff89c: 4 4
The problem is
struct bar x = { b->f4, 0, {0, 0} };gcc uses
st8 [rX] = r0
for {0, 0}. But st8 requires 8 byte aligment while
unsigned int f6 [2];
has 4 byte aligment.
BTW, nfs3_proc_create in fs/nfs/nfs3proc.c got miscompiled.
H.J.
----al.c---
#include <stdio.h>
enum bool { false, true };
struct bar
{
void *f4;
enum bool f5;
unsigned int f6 [2];
};
struct barf_bar (struct bar *b)
{
struct bar x = { b->f4, 0, {0, 0} };
printf ("%p\n", &x);
printf ("%p: %d\n", &x.f6, ((long) (&x.f6)) & 0x7); printf ("%d\n", __alignof__ (x.f6));
return x;
}
main ()
{
struct bar x;
x = f_bar (&x);
}
Quoted 10 lines · H . J . Lu
I got a kernel unaligned access bug:
The problem is
struct bar x = { b->f4, 0, {0, 0} };gcc uses
st8 [rX] = r0
Quoted 8 lines
for {0, 0}. But st8 requires 8 byte aligment while
unsigned int f6 [2];has 4 byte aligment.
BTW,
nfs3_proc_createinfs/nfs/nfs3proc.cgot miscompiled.
Here is a workaround for the compiler bug.
---
fs/nfs/nfs3proc.c renamed from fs/nfs/nfs3proc.c.align +17 -4
@@ -190,11 +190,17 @@ nfs3_proc_create(struct inode *dir, stru int flags, struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_fattr dir_attr; -struct nfs3_createargs arg = {NFS_FH (dir), name->name, name->len, - sattr,0 , {0 ,0 } }; +struct nfs3_createargs arg;struct nfs3_diropres res = { &dir_attr, fhandle, fattr };int status; + arg.fh =NFS_FH (dir); + arg.name = name->name; + arg.len = name->len, + arg.sattr = sattr; + arg.createmode =0 ; + arg.verifier [0 ] =0 ; + arg.verifier [1 ] =0 ;dprintk ("NFS call create %s\n" , name->name); arg.createmode =NFS3_CREATE_UNCHECKED ;if (flags &O_EXCL ) {
@@ -362,10 +368,17 @@ nfs3_proc_mkdir(struct inode *dir, struc struct nfs_fh *fhandle, struct nfs_fattr *fattr) { struct nfs_fattr dir_attr; -struct nfs3_createargs arg = {NFS_FH (dir), name->name, name->len, - sattr,0 , {0 ,0 } }; +struct nfs3_createargs arg;struct nfs3_diropres res = { &dir_attr, fhandle, fattr };int status; + + arg.fh =NFS_FH (dir); + arg.name = name->name; + arg.len = name->len, + arg.sattr = sattr; + arg.createmode =0 ; + arg.verifier [0 ] =0 ; + arg.verifier [1 ] =0 ;dprintk ("NFS call mkdir %s\n" , name->name); dir_attr.valid =0 ;
Yes, it is a compiler bug. It is a generic problem effecting all targets, though it is more noticable for 64-bit machines. Not clear when it was introduced, I didn't want to spend that much time looking at the problem. The bug was independently found and fixed by Richard Kenner last week.
Tue Jan 2 10:47:38 2001 Richard Kenner <[email protected].
* expr.c (store_constructor_field): Update ALIGN before calling store_constructor.
Index: expr.c
=================================RCS file: /cvs/cvsfiles/devo/gcc/expr.c,v retrieving revision 1.425.2.2
diff -p -r1.425.2.2 expr.c
*** expr.c 2000/08/14 20:10:41 1.425.2.2
--- expr.c 2001/01/12 02:04:27
*************** store_constructor_field (target, bitsize
*** 4224,4229 ****
--- 4224,4233 ----
? BLKmode : VOIDmode, plus_constant (XEXP (target, 0),
bitpos / BITS_PER_UNIT));
+
+ if (bitpos != 0)
+ align = MIN (align, bitpos & - bitpos);
+
store_constructor (exp, target, align, cleared, bitsize / BITS_PER_UNIT);
}
else