arch/arm/kernel/setup.c does not compile at -O0
Suman Tripathi
stripathi at apm.com
Thu Jul 30 09:13:57 PDT 2015
On Thu, Jul 30, 2015 at 9:20 PM, Russell King - ARM Linux
<linux at arm.linux.org.uk> wrote:
> On Thu, Jul 30, 2015 at 08:53:45PM +0530, Suman Tripathi wrote:
>> Hi,
>>
>> On Thu, Jul 30, 2015 at 6:23 PM, Mason <slash.tmp at free.fr> wrote:
>> >
>> > Hello everyone,
>> >
>> > I'm trying to debug a live kernel (v3.14) using a DS-5 JTAG probe.
>> >
>> > In order to make the control flow easier to follow, I disabled
>> > optimizations by adding
>> >
>> > subdir-ccflags-y := -O0
>> >
>> > to arch/arm/kernel/Makefile
>> >
>> > With that change, linking fails:
>> >
>> > arch/arm/kernel/setup.c:924: undefined reference to `psci_smp_ops'
>> >
>> > if (psci_smp_available())
>> > smp_set_ops(&psci_smp_ops);
>> >
>> > #ifdef CONFIG_ARM_PSCI
>> > void psci_init(void);
>> > bool psci_smp_available(void);
>> > #else
>> > static inline void psci_init(void) { }
>> > static inline bool psci_smp_available(void) { return false; }
>> > #endif
>> >
>> > The optimizer is able to remove the entire block, but this
>> > does not happen when optimizations are disabled.
>> >
>> > Is compiling at -O0 not supported?
>>
>> If you have inline functions, it won't compile at -O0
>
> That's incorrect.
>
> If you have static inline functions, there isn't a problem irrespective
> of optimisation level - they'll become merely static functions which
> won't be inlined, and you'll end up with a copy of the function per
> compilation unit.
>
> If you have extern inline functions, they also won't be inlined, but
> unlike static inline, the compiler won't emit a static function.
> Instead, the compiler expects the function to be provided via another
> compilation unit or library (which won't happen in the Linux kernel.)
> However, Linux kernel coding style does not allow the use of extern
> inline functions.
>
> The problem which the Linux kernel has is that we rely on the compiler
> performing optimisations in multiple places - such as eliminating code
> which can't be reached. Disabling the optimiser prevents such
> eliminations from happening, and ends up leaving symbols behind which
> are purposely not-defined (which are so in order to detect errors for
> accessors like get_user(), etc. which are only defined to operate on
> 1, 2, 4 and maybe 8 byte values.)
>
> For example:
>
> #define __put_user_check(x, p) \
> ({ \
> unsigned long __limit = current_thread_info()->addr_limit - 1; \ const typeof(*(p)) __user *__tmp_p = (p); \
> register const typeof(*(p)) __r2 asm("r2") = (x); \
> register const typeof(*(p)) __user *__p asm("r0") = __tmp_p; \
> register unsigned long __l asm("r1") = __limit; \
> register int __e asm("r0"); \
> switch (sizeof(*(__p))) { \
> case 1: \
> __put_user_x(__r2, __p, __e, __l, 1); \
> break; \
> case 2: \
> __put_user_x(__r2, __p, __e, __l, 2); \
> break; \
> case 4: \
> __put_user_x(__r2, __p, __e, __l, 4); \
> break; \
> case 8: \
> __put_user_x(__r2, __p, __e, __l, 8); \
> break; \
> default: __e = __put_user_bad(); break; \
> } \
> __e; \
> })
>
> which relies on the optimiser removing all the cases which don't apply to
> the access size. Disabling optimisation prevents that happening, so you
> end up with the entire switch() statement coded in the output assembly
> for every invocation of this macro - which includes a call to
> __put_user_bad() just in case sizeof(*__p) changes unexpectedly.
>
> Building the kernel with optimisation disabled is not supported.
Thanks for the info Russell !!
>
> --
> FTTC broadband for 0.8mile line: currently at 10.5Mbps down 400kbps up
> according to speedtest.net.
--
Thanks,
with regards,
Suman Tripathi
More information about the linux-arm-kernel
mailing list