Hi,
For reference, the following questions refer to a Linux 3.10 aarch64 kernel (ARMv8, ARMv8-A) compiled with Linaro 5.3-2016.02 (5.3-2016.02 arm64 CROSS_COMPILE and 5.3-2016.02 armhf CROSS32CC cross compiled from x86_64). This Linux kernel compile requires the full 64-bit tool chain plus the 32-bit gcc.
There is a Linux kernel file "arch/arm64/kernel/deprecated.c". Within that file is a block of code which is apparently designed to detect some sort of older obsolete 32-bit code. Specifically, the warning message is "Using deprecated CP15 barrier instruction". I wouldn't think that this kernel, when compiled with such a recent compiler, would ever introduce CP15 barrier code (from what I see barrier code was deprecated in ARMv7 and used to deal with obsolete ARMv6 code). Is there any chance the 32-bit 5.3 gcc would still generate CP15 barrier code?
Although this kernel and "most" modules are built with Linaro 5.3 I'd like to be able to narrow the cause down to existing binary modules not compiled with the 5.3 Linaro. If I can guarantee 5.3 32-bit gcc does not produce the CP15 barrier instruction then I'll know it is in pre-built binary modules. Can anyone tell me if C code compiled from Linaro version 5.3 32-bit gcc code would ever contain CP15 instructions?
Thanks!
On Mon, Sep 5, 2016 at 8:10 AM, stimits@comcast.net wrote:
There is a Linux kernel file "arch/arm64/kernel/deprecated.c". Within that file is a block of code which is apparently designed to detect some sort of older obsolete 32-bit code. Specifically, the warning message is "Using deprecated CP15 barrier instruction".
I assume this is the same file as armv8_deprecated.c in the linux 4.0 sources I have. The file provides code to emulate deprecated instructions. You can emulate a deprecated instruction if you catch the illegal instruction trap that was generated, and then call some emulation code instead of sending a signal to the program. The emulation code prints a warning to let you know that you have some very old code that really should be re-compiled. That is the point of the emulation. it isn't to handle any code generated by the current compiler for current targets, but rather code generated by an old compiler or for old targets that is using instructions that have since been deprecated.
It appears that you need to use an armv6 compiler to get the cp15 barrier instruction, which was deprecated in favor of the new dmb/dsb instructions in armv7.
Since these are memory synchronization barriers, you can get them from C code, but only if you are doing something special, like calling the old sync built-ins or the new atomic built-ins, or using a compiler feature that will cause these builtins to be called automatically such as a feature that uses thread support or coroutines or some similar feature.
There is no synchronization support in gcc-4.3. Looking at the gcc-4.4 arm support, I see that there are two special instructions for getting memory synchronization support from the kernel. #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0) #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) It appears that reading from a protected memory location is somehow triggering the kernel support. In gcc-4.7, the sync intrinsics were rewritten, and here I see that gcc is now emitting dmb for armv7 and a cp15 barrier for armv6. The current support is the same.
So you can get a cp15 barrier from the current compiler, but you need to compile for armv6, and directly or indirectly call the synchronization and/or atomic builtins.
Jim
On 5 September 2016 at 22:20, Jim Wilson jim.wilson@linaro.org wrote:
On Mon, Sep 5, 2016 at 8:10 AM, stimits@comcast.net wrote:
There is a Linux kernel file "arch/arm64/kernel/deprecated.c". Within that file is a block of code which is apparently designed to detect some sort of older obsolete 32-bit code. Specifically, the warning message is "Using deprecated CP15 barrier instruction".
I assume this is the same file as armv8_deprecated.c in the linux 4.0 sources I have. The file provides code to emulate deprecated instructions. You can emulate a deprecated instruction if you catch the illegal instruction trap that was generated, and then call some emulation code instead of sending a signal to the program. The emulation code prints a warning to let you know that you have some very old code that really should be re-compiled. That is the point of the emulation. it isn't to handle any code generated by the current compiler for current targets, but rather code generated by an old compiler or for old targets that is using instructions that have since been deprecated.
In particular, this emulation is for handling occurrences of these old barrier operations in *userspace binaries*. In your initial email you write:
# Although this kernel and "most" modules are built with Linaro 5.3 # I'd like to be able to narrow the cause down to existing binary # modules not compiled with the 5.3 Linaro. If I can guarantee 5.3 # 32-bit gcc does not produce the CP15 barrier instruction then # I'll know it is in pre-built binary modules.
but this code will not handle any cp15 barriers in kernel code (modules or otherwise). If the CPU doesn't support the cp15 barriers then trying to execute them will result in an Oops or panic. So the symptoms you're seeing are nothing to do with the binary kernel modules or the compiler version you're using to build the kernel.
The thing you need to recompile is not your kernel but whatever old userspace code you're running. (Or don't bother, and put up with the poor performance and the warning messages. The code will still work fine.)
There is no synchronization support in gcc-4.3. Looking at the gcc-4.4 arm support, I see that there are two special instructions for getting memory synchronization support from the kernel. #define __kernel_cmpxchg (*(__kernel_cmpxchg_t *) 0xffff0fc0) #define __kernel_dmb (*(__kernel_dmb_t *) 0xffff0fa0) It appears that reading from a protected memory location is somehow triggering the kernel support.
(A point of detail only) This is a function pointer to be called, not a data location to be read. It's in the kernel user helpers page as documented here: https://www.kernel.org/doc/Documentation/arm/kernel_user_helpers.txt (Since the kernel knows what host CPU it's on it can put the right kind of barrier insn in the function in the helper page. So the compiler can use this if it's not already compiling for a sufficiently new CPU that it knows what kind of barriers it supports.)
thanks -- PMM
linaro-toolchain@lists.linaro.org