[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <CALCETrV2kV5cm7xJfKJ4J4VjhhypnMhfOYkOcU5w2Ps1BiMxMw@mail.gmail.com>
Date: Fri, 14 Dec 2018 13:27:40 -0800
From: Andy Lutomirski <luto@...nel.org>
To: Linus Torvalds <torvalds@...ux-foundation.org>
Cc: Rich Felker <dalias@...c.org>, Florian Weimer <fweimer@...hat.com>,
Bernd Petrovitsch <bernd@...rovitsch.priv.at>,
John Paul Adrian Glaubitz <glaubitz@...sik.fu-berlin.de>,
Andrew Lutomirski <luto@...nel.org>, X86 ML <x86@...nel.org>,
LKML <linux-kernel@...r.kernel.org>,
Linux API <linux-api@...r.kernel.org>,
"H. Peter Anvin" <hpa@...or.com>,
Peter Zijlstra <peterz@...radead.org>,
Borislav Petkov <bp@...en8.de>,
Mike Frysinger <vapier@...too.org>,
"H. J. Lu" <hjl.tools@...il.com>, x32@...ldd.debian.org,
Arnd Bergmann <arnd@...db.de>,
Will Deacon <will.deacon@....com>,
Catalin Marinas <catalin.marinas@....com>
Subject: Re: Can we drop upstream Linux x32 support?
On Fri, Dec 14, 2018 at 12:13 PM Linus Torvalds
<torvalds@...ux-foundation.org> wrote:
>
> On Fri, Dec 14, 2018 at 10:58 AM Andy Lutomirski <luto@...capital.net> wrote:
> >
> > Does anyone know *why* Linux’s x32 has __kernel_long_t defined as long long?
>
> It *needs* to be long long, since the headers are used for builds in
> user mode using ILP32.
>
> Since __kernel_long_t is a 64-bit (the _kernel_ is not ILP32), you
> need to use "long long" when building in ILP32.
>
> Obviously, it could be something like
>
> #ifdef __KERNEL__
> typedef long __kernel_long_t;
> #else
> typedef long long __kernel_long_t;
> #endif
>
> or similar to make it more obvious what's going on.
>
> Or we could encourage all the uapi header files to always just use
> explicit sizing like __u64, but some of the structures really end up
> being "kernel long size" for sad historical reasons. Not lovely, but
> there we are..
>
This is probably water under the bridge, but I disagree with you here.
Or rather, I agree with you in principle but I really don't like the
way it turned out.
For legacy uapi structs (and probably some new ones too, sigh), as a
practical matter, user code is going to shove them at the C compiler,
and the C compiler is going to interpret them in the usual way, and
either we need a usermode translation layer or the kernel needs to
deal with the result.
It's a nice thought that, by convincing an x32 compiler that
__kernel_long_t is 64 bits, we end up with the x32 struct being
compatible with the native Linux struct, but it only works for structs
where the only ABI-dependent type is long. But the real structs in
uapi aren't all like this. We have struct iovec:
struct iovec
{
void __user *iov_base; /* BSD uses caddr_t (1003.1g requires void *) */
__kernel_size_t iov_len; /* Must be size_t (1003.1g) */
};
Whoops, this one looks the same on x32 and i386, but neither one of
them match x86_64, and, just randomly grepping around a bit, I see:
struct snd_hwdep_dsp_image {
unsigned int index; /* W: DSP index */
unsigned char name[64]; /* W: ID (e.g. file name) */
unsigned char __user *image; /* W: binary image */
size_t length; /* W: size of image in bytes */
unsigned long driver_data; /* W: driver-specific data */
};
struct __sysctl_args {
int __user *name;
int nlen;
void __user *oldval;
size_t __user *oldlenp;
void __user *newval;
size_t newlen;
unsigned long __unused[4];
};
If these had been switched from "unsigned long" to __kernel_ulong_t,
they would have had three different layouts on i386, x32, and x86_64.
So now we have a situation where, if we were to make x32 work 100%,
the whole kernel would need to recognize that there are three possible
ABIs, not two. And this sucks.
So I think it would have been a better choice to let long be 32-bit on
x32 and to therefore make x32 match the x86_32 "compat" layout as much
as possible. Sure, this would make x32 be more of a second-class
citizen, but I think it would have worked better, had fewer bugs, and
been more maintainable.
--Andy
Powered by blists - more mailing lists