[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20091217190453.GA362@shareable.org>
Date: Thu, 17 Dec 2009 19:04:53 +0000
From: Jamie Lokier <jamie@...reable.org>
To: Russell King - ARM Linux <linux@....linux.org.uk>
Cc: Richard Guenther <richard.guenther@...il.com>,
David Daney <ddaney@...iumnetworks.com>,
"gcc@....gnu.org" <gcc@....gnu.org>, linux-kernel@...r.kernel.org,
linux-arm-kernel@...ts.infradead.org,
Uwe Kleine-König
<u.kleine-koenig@...gutronix.de>
Subject: Re: [PATCH] ARM: Convert BUG() to use unreachable()
Russell King - ARM Linux wrote:
> Let me put it another way: I want this function to terminate with an
> explicit NULL pointer dereference in every case.
__builtin_trap cannot be used because the GCC manual says "The
mechanism used may vary from release to release so you should not rely
on any particular implementation". It includes calling abort() as a
possible implementation - not ideal.
This is not related to GCC, but I have an ARM system here where
dereferencing NULL does not trap. You guessed it, it doesn't have a
regular MMU. But there are other addresses which do trap. They would
be a much better choice for BUG().
(Aha! Maybe that's why the kernel just behaves weirdly when it runs
out of memory and eventually triggers a watchdog reboot, with no panic
message. I'd better try changing BUG() :-)
Even with an MMU, sometimes userspace maps page zero. For example,
Wine on x86 does that. (It might be possible to change Wine and
kernel vm86 to avoid it, but it has not happened).
Bug-free userspace behaviour should not stop kernel's BUG() from doing
it's basic job of trapping in the kernel!
It would be quite messy if userspace maps page zero, and then a kernel
BUG() ploughs ahead into __builtin_unreachable() and completely
undefined behaviour, possibly leading to worse behaviour than omitting
the check which called BUG().
Under those circumstances I'd rather see it use __builtin_trap() if
that really does trap :-)
The point of the exercise with __builtin_unreachable() is to reduce
the kernel size by removing the for(;;) loop. *(int *)0 = 0 isn't the
smallest trapping sequence. (When it works :-)
So the most compact _and_ reliable sequence for the kernel, on all
architectures, is probably:
__asm__ volatile("smallest undefined or always-trapping instruction")
followed by __builtin_unreachable(), because GCC documentation _does_
say that asm followed by that will execute the asm and assume the asm
doesn't return.
-- Jamie
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists