Re: gcc stack problem

From: Linus Torvalds
Date: Sat Apr 22 2006 - 17:15:05 EST




On Fri, 21 Apr 2006, Albert Cahalan wrote:
>
> I reported that problem involving asmlinkage and prevent_tail_call.

It's been discussed before, although I cannot for the life of me come up
with the right magic query for google to find it ;(

Btw, the "prevent_tail_call()" thing is really badly named. It does
exactly what it says, but the problem isn't even really fundamentally
tailcalls, that just is the deail that happens to trigger the problem (but
I could imagine other situations triggering it _too_, which is why the
naming is bad).

We don't actually care about tailcalls (they're absolutely _fine_, if the
tailcall arguments are all in registers, not overwriting the caller
stack-frame), so "prevent_tail_call()" really talks about the wrong thing.

In other words, it's too tightly coupled to an implementation issue, not
to the more fundamental _conceptual_ issue, which is that the caller owns
the stackframe at that point.

> I hope I got the details right. Here it is:
>
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=27234
>
> Note comment #3, suggesting that following the ABI would
> be a better way to write the assembly.

Sure, we could just do a slower system call entry. We always knew that.

Suggesting that as the solution is pretty stupid, though. That's _the_
most timing-critical part in the whole kernel on many loads. We've
literally spent time trying to remove single cycles there, and it matters.

I'd much rather have an officially sanctioned way to do what Linux wants
to do, but in the meantime, we can (and are forced to) rely on hacks like
"prevent_tail_call()". They are hacks, and we _know_ they are hacks, but
as long as gcc maintainers don't want to help us, we don't have much
choice (although we could perhaps make the hacks a bit nicer ;).

The fact is, the "official ABI" simply isn't appropriate. In fact, we
don't use the "official ABI" _anywhere_ in the kernel any more, since we
actually end up using other gcc calling conventions (ie regparm=3).

Btw, this is not even unusual. A lot of embedded platforms have support
for magic exception/interrupt calling conventions. Gcc even supports them:
things like "__attribute__((interrupt))". This is also exactly analogous
to stdcall/cdecl/regparm/longcall/naked/sp_switch/trap_exit etc
attributes.

So gcc already has support for the fact that people sometimes need special
calling conventions. We've historically worked around it by hand instead,
since our calling convention is very _close_ to the standard one

In fact, the calling convention we want there is _so_ close to the
standard one, that I'm not even convinced the i386 ABI really says that
the callee owns the parameter space - it may well be a local gcc decision
rather than any "official i386 ABI" issue.

Btw, we don't even need a real attribute. That would be the cleanest and
easiest way by far, but the hack mostly works, and I'd be more than
happy to just perhaps clean up the hacky "do it by hand" thing a bit.

For example, I've considered replacing the ugly "prevent_tail_call()" with
a slightly different macro that talks less about tailcalls, and talks
more about the ABI we want:

static inline long system_call_ret(long retval, void *arg)
{
asm("":
"=r" (retval),
"+m" (*(struct pt_regs *)arg)
:"0" (retval));
return retval;
}

#ifdef __x86__
#define sys_return(x, arg1) \
return system_call_ret((x), &(arg1))
#else
define sys_return(x, arg1) \
return (x)
#endif

where we'd make it extra clear that on x86 we're still _using_ the memory
pointed to by "arg1" when we return (so that any other strange gcc
optimization would also be kept from touching the call frame, not just
tailcalls).

That said, I'd much rather have a real gcc attribute. I don't _like_
having horrible hacks like the above to make gcc do what I want it to do.
And I know the gcc developers don't like it either when I force gcc to be
my biatch. It would be much better for everybody if gcc helped a bit.

Linus
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/