Messages in this thread | | | Date | Wed, 24 Mar 2021 18:33:39 +0100 | From | Peter Zijlstra <> | Subject | Re: [PATCH] static_call: fix function type mismatch |
| |
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 return value is in a register.
Per the first we can call a function that has a partial (empty per extremum) argument list. 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.
| |