[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aMqCPVmOArg8dIqR@shell.armlinux.org.uk>
Date: Wed, 17 Sep 2025 10:41:17 +0100
From: "Russell King (Oracle)" <linux@...linux.org.uk>
To: Thomas Gleixner <tglx@...utronix.de>
Cc: LKML <linux-kernel@...r.kernel.org>,
Linus Torvalds <torvalds@...ux-foundation.org>,
Peter Zijlstra <peterz@...radead.org>,
kernel test robot <lkp@...el.com>,
linux-arm-kernel@...ts.infradead.org,
Nathan Chancellor <nathan@...nel.org>,
Christophe Leroy <christophe.leroy@...roup.eu>,
Darren Hart <dvhart@...radead.org>,
Davidlohr Bueso <dave@...olabs.net>,
André Almeida <andrealmeid@...lia.com>,
x86@...nel.org, Alexander Viro <viro@...iv.linux.org.uk>,
Christian Brauner <brauner@...nel.org>, Jan Kara <jack@...e.cz>,
linux-fsdevel@...r.kernel.org
Subject: Re: [patch V2 1/6] ARM: uaccess: Implement missing
__get_user_asm_dword()
On Wed, Sep 17, 2025 at 07:48:00AM +0200, Thomas Gleixner wrote:
> On Tue, Sep 16 2025 at 22:26, Russell King wrote:
> > On Tue, Sep 16, 2025 at 06:33:09PM +0200, Thomas Gleixner wrote:
> >> When CONFIG_CPU_SPECTRE=n then get_user() is missing the 8 byte ASM variant
> >> for no real good reason. This prevents using get_user(u64) in generic code.
> >
> > I'm sure you will eventually discover the reason when you start getting
> > all the kernel build bot warnings that will result from a cast from a
> > u64 to a pointer.
>
> I really don't know which cast you are talking about.
I'll grant you that the problem is not obvious. It comes about because
of all the different types that get_user() is subject to - it's not
just integers, it's also pointers.
The next bit to realise is that casting between integers that are not
the same size as a pointer causes warnings. For example, casting
between a 64-bit integer type and pointer type causes the compiler to
emit a warning. It doesn't matter if the code path ends up being
optimised away, the warning is still issued.
Putting together a simple test case, where the only change is making
__gu_val an unsigned long long:
t.c: In function ‘get_ptr’:
t.c:40:15: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
40 | (x) = (__typeof__(*(ptr)))__gu_val; \
| ^
t.c:21:9: note: in expansion of macro ‘__get_user_err’
21 | __get_user_err((x), (ptr), __gu_err, TUSER()); \
| ^~~~~~~~~~~~~~
t.c:102:16: note: in expansion of macro ‘__get_user’
102 | return __get_user(p, ptr);
| ^~~~~~~~~~
In order for the code you are modifying to be reachable, you need to
build with CONFIG_CPU_SPECTRE disabled. This is produced by:
int get_ptr(void **ptr)
{
void *p;
return __get_user(p, ptr);
}
Now, one idea may be to declare __gu_val as:
__typeof__(x) __gu_val;
but then we run into:
t.c: In function ‘get_ptr’:
t.c:37:29: error: assignment to ‘void *’ from ‘int’ makes pointer from integer without a cast [-Wint-conversion]
37 | default: (__gu_val) = __get_user_bad(); \
| ^
t.c:21:9: note: in expansion of macro ‘__get_user_err’
21 | __get_user_err((x), (ptr), __gu_err, TUSER()); \
| ^~~~~~~~~~~~~~
t.c:102:16: note: in expansion of macro ‘__get_user’
102 | return __get_user(p, ptr);
| ^~~~~~~~~~
You may think this is easy to solve, just change the last cast to:
(x) = (__typeof__(*(ptr)))(__typeof__(x))__gu_val;
but that doesn't work either (because in the test case __typeof__(x) is
still a pointer type. You can't cast this down to a 32-bit quantity
because that will knock off the upper 32 bits for the case you're trying
to add.
You may think, why not move this cast into each switch statement...
there will still be warnings because the cast is still reachable at the
point the compiler evaluates the code for warnings, even though the
optimiser gets rid of it later.
Feel free to try to solve this, but I can assure you that you certainly
are not the first. Several people have already tried.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
Powered by blists - more mailing lists