On Mon, Jul 04, 2011 at 05:52:03PM +0100, Tixy wrote:
On Mon, 2011-07-04 at 17:16 +0100, Dave Martin wrote:
On Sat, Jul 02, 2011 at 12:28:01PM +0100, Tixy wrote:
On Fri, 2011-07-01 at 19:26 +0100, Dave Martin wrote:
The interworking behaviour is uniform for ARMv5(T) and above, but since kernels built in Thumb cannot run on pre-v7, and kernels built in ARM cannot (or certainly should not) contain any Thumb code, these niceties may not matter.
Interworking in different on v7, ARM mode ALU instructions now interwork, e.g. "sub pc, pc, #3" will switch from ARM to Thumb.
OK, I was just thinking about Thumb, but this is a fair distinction.
Alternatively, would it make sense to oops instead if we discover when simulating the branch that it would try to switch to ARM?
I'm not sure I understand what you mean here. In ARM mode the instruction "sub pc, pc, #3" does the following
on ARMv7, switch to Thumb on ARMv6, stay in ARM mode on ARMv5 and earlier, UNPREDICTABLE
Hmmm, I wasn't aware of the distinction between ARMv5 and ARMv6 here.
so are you saying OOPS in the last case? (I currently have it staying ARM mode as I only distinguish between <=ARMv6 and >=ARMv7 )
No, I mean oops in the ARMv7 case if it would switch to Thumb. By definition we cannot detect many of these case statically, and I suggest it may not be worth trying to catch any of them statically.
For ARMv6, we should implement the architecture correctly and stay in ARM.
For ARMv5, "UNPREDICTABLE" provides flexibility on how to interpret the architecture -- so we can do what's most convenient and mimic the ARMv6 behaviour. If we could detect the UNPREDICTABLE cases statically, it might be worth refusing the probe, but since the behaviour depends on the ALU result, we can't tell statically whether the instruction is an unpredictable usabe or not. But if you don't feel comfortable with that, we could also Oops or something. That too is within the scope of what the architecture permits for UNPREDICTABLE behaviours.
Note, in Thumb mode, the ALU instructions don't interwork on any architecture. (It makes you wonder why they changed the ARM mode behaviour in v7).
I think it's to make it easier to integrate legacy ARM code into a mixed ARM/Thumb environment.
Thumb-2 code is not legacy by definition, and Thumb-1 can't really be used for general-purpose stuff. Plus, ALU operations have never been the correct way to do procedure returns etc. since the introduction of EABI. So generally, Thumb code is not going to suffer from interworking problems to the same extent as ARM.
[...]
When doing doing the kprobes bug fixes it was decided that we should avoid writes to PC which produce unpredictable results, even though such instructions aren't legal and won't occur in normal code. So I believe it follows that we should implement interworking correctly, even on kernels not built for Thumb.
I'm not sure I understand your argument here.
I was trying to say that if we already have code to handle cases of invalid instructions that the compiler/assembler would never generate, then we should have code to handle legal instructions that the the compiler/assembler won't generate because we're not building for Thumb.
OK, I think I get it -- you mean we should not just silently execute these cases and hope for the best.
I agree with that; as above, my conclusion is that since attempts to detect these unpredictable ALU operations statically will be somewhat haphazard* it may be cleaner not to attempt it at all, and check at runtime on the architectures where it makes a difference.
(* i.e., subs add pc, lr, #3 is not an UNPREDICTABLE case if lr contains an odd number at run-time, where as subs pc, lr, #4 may be UNPREDICTABLE if lr is odd etc. -- we cannot tell just be decoding the instruction)
Before I started my work, the kprobes code already had a partial simulation of interworking, so someone else must have thought it worth while. Though it would obviously be a lot simpler if I could just wrap all interworking stuff up in #ifdef CONFIG_THUMB2_KERNEL.
Is it worth pinging the original committer to get his views on the rationale for this?
Over the weekend I implemented functions to check various interworking behaviour, and run these when kprobes is first initialised. So I now have things all simulated correctly and I think I may as well leave things in there now.
Do you mean you check the CPU ID etc?
I'm not sure that experimentally running instructions to see what happens is entirely safe, but that may not be what you're suggesting.
Cheers, ---Dave