Messages in this thread | | | Date | Wed, 24 Mar 2021 20:16:06 +0100 | From | Peter Zijlstra <> | Subject | Re: [PATCH] static_call: fix function type mismatch |
| |
On Wed, Mar 24, 2021 at 06:33:39PM +0100, Peter Zijlstra wrote: > On Wed, Mar 24, 2021 at 05:45:52PM +0100, Rasmus Villemoes wrote: > > Sorry, I think I misread the code. The static calls are indeed > > initialized with a function with the right prototype. Try adding > > "preempt=full" on the command line so that we exercise these lines > > > > static_call_update(cond_resched, > > (typeof(&__cond_resched)) __static_call_return0); > > static_call_update(might_resched, > > (typeof(&__cond_resched)) __static_call_return0); > > > > I would expect that to blow up, since we end up calling a long (*)(void) > > function using a function pointer of type int (*)(void). > > Note that on x86 there won't actually be any calling of function > pointers. See what arch/x86/kernel/static_call.c does :-) > > But I think some of this code might need some __va_function() love when > combined with CFI. > > But yes, this is why I think something like -fcdecl might be a good > idea, that ought to tell the compiler about the calling convention, > which ought to be enough for the compiler to figure out that this magic > really is ok. > > Notable things we rely on: > > - caller cleanup of stack; the function caller sets up any stack > arguments and is also responsible for cleanin up the stack once the > function returns.
- the arguments are pushed on stack right to left;
> - the return value is in a register. > > Per the first we can call a function that has a partial (empty per > extremum) argument list.
That extra constraint is required to make partial args work; as it happens we only use empty args, and as such don't really care about this atm.
> Per the second we can call a function with a > different return type as long as they all fit in the same register. > > The calling of a 'long (*)()' function for a 'int (*)()' type then > becomes idential to something like: 'int x = (long)y', and that is > something C is perfectly fine with. > > We then slightly push things with the other __static_call_return0() > usage in the kernel, where we basically end up with: 'void *x = > (long)y', which is something C really rather would have a cast on.
| |