x86, mm: Use a bitfield to mask nuisance get_user() warnings
authorH. Peter Anvin <hpa@zytor.com>
Tue, 12 Feb 2013 00:27:28 +0000 (16:27 -0800)
committerH. Peter Anvin <hpa@zytor.com>
Tue, 12 Feb 2013 01:26:51 +0000 (17:26 -0800)
Even though it is never executed, gcc wants to warn for casting from
a large integer to a pointer.  Furthermore, using a variable with
__typeof__() doesn't work because __typeof__ retains storage
specifiers (const, restrict, volatile).

However, we can declare a bitfield using sizeof(), which is legal
because sizeof() is a constant expression.  This quiets the warning,
although the code generated isn't 100% identical from the baseline
before 96477b4 x86-32: Add support for 64bit get_user():

[x86-mb is baseline, x86-mm is this commit]

   text      data        bss     filename
113716147  15858380   35037184   tip.x86-mb/o.i386-allconfig/vmlinux
113716145  15858380   35037184   tip.x86-mm/o.i386-allconfig/vmlinux
 12989837   3597944   12255232   tip.x86-mb/o.i386-modconfig/vmlinux
 12989831   3597944   12255232   tip.x86-mm/o.i386-modconfig/vmlinux
  1462784    237608    1401988   tip.x86-mb/o.i386-noconfig/vmlinux
  1462837    237608    1401964   tip.x86-mm/o.i386-noconfig/vmlinux
  7938994    553688    7639040   tip.x86-mb/o.i386-pae/vmlinux
  7943136    557784    7639040   tip.x86-mm/o.i386-pae/vmlinux
  7186126    510572    6574080   tip.x86-mb/o.i386/vmlinux
  7186124    510572    6574080   tip.x86-mm/o.i386/vmlinux
103747269  33578856   65888256   tip.x86-mb/o.x86_64-allconfig/vmlinux
103746949  33578856   65888256   tip.x86-mm/o.x86_64-allconfig/vmlinux
 12116695  11035832   20160512   tip.x86-mb/o.x86_64-modconfig/vmlinux
 12116567  11035832   20160512   tip.x86-mm/o.x86_64-modconfig/vmlinux
  1700790    380524     511808   tip.x86-mb/o.x86_64-noconfig/vmlinux
  1700790    380524     511808   tip.x86-mm/o.x86_64-noconfig/vmlinux
 12413612   1133376    1101824   tip.x86-mb/o.x86_64/vmlinux
 12413484   1133376    1101824   tip.x86-mm/o.x86_64/vmlinux

Cc: Jamie Lokier <jamie@shareable.org>
Cc: Ville Syrjälä <ville.syrjala@linux.intel.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Russell King <linux@arm.linux.org.uk>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: http://lkml.kernel.org/r/20130209110031.GA17833@n2100.arm.linux.org.uk
Signed-off-by: H. Peter Anvin <hpa@zytor.com>
arch/x86/include/asm/uaccess.h

index 1e963267d44eecd2abd62c6989722fad5c7d1883..a8d12653f30435aa1734477018efd81887f4af3b 100644 (file)
@@ -168,31 +168,29 @@ do {                                                    \
 #define get_user(x, ptr)                                               \
 ({                                                                     \
        int __ret_gu;                                                   \
-       unsigned long __val_gu;                                         \
-       unsigned long long __val_gu8;                                   \
+       struct {                                                        \
+               unsigned long long __val_n : 8*sizeof(*(ptr));          \
+       } __val_gu;                                                     \
        __chk_user_ptr(ptr);                                            \
        might_fault();                                                  \
        switch (sizeof(*(ptr))) {                                       \
        case 1:                                                         \
-               __get_user_x(1, __ret_gu, __val_gu, ptr);               \
+               __get_user_x(1, __ret_gu, __val_gu.__val_n, ptr);       \
                break;                                                  \
        case 2:                                                         \
-               __get_user_x(2, __ret_gu, __val_gu, ptr);               \
+               __get_user_x(2, __ret_gu, __val_gu.__val_n, ptr);       \
                break;                                                  \
        case 4:                                                         \
-               __get_user_x(4, __ret_gu, __val_gu, ptr);               \
+               __get_user_x(4, __ret_gu, __val_gu.__val_n, ptr);       \
                break;                                                  \
        case 8:                                                         \
-               __get_user_8(__ret_gu, __val_gu8, ptr);                 \
+               __get_user_8(__ret_gu, __val_gu.__val_n, ptr);          \
                break;                                                  \
        default:                                                        \
-               __get_user_x(X, __ret_gu, __val_gu, ptr);               \
+               __get_user_x(X, __ret_gu, __val_gu.__val_n, ptr);       \
                break;                                                  \
        }                                                               \
-       if (sizeof(*(ptr)) == 8)                                        \
-               (x) = (__typeof__(*(ptr)))__val_gu8;                    \
-       else                                                            \
-               (x) = (__typeof__(*(ptr)))__val_gu;                     \
+       (x) = (__typeof__(*(ptr)))__val_gu.__val_n;                     \
        __ret_gu;                                                       \
 })