I implemented the following C snippet as normal C file:
/* * test.c - Demonstrating the Secure Monitor Calls (SMCs) in am335x TI armv7 A8 architecture. */ #include <stdio.h> static inline void asm_enable_L2_ECC(void) { unsigned int reg_value; printf("Start\n"); __asm ("dsb"); // data synchronization barrier operation __asm ("isb"); // instruction synchronization barrier operation __asm ("dmb"); // data memory barrier operation printf("End\n"); } void main (void) { asm_enable_L2_ECC(); }
This code compiles, links, and while being in privileged Supervisor mode does work as expected.
root@beaglebone:~/projects/LKM/cp15_smc# ./test Start End root@beaglebone:~/projects/LKM/cp15_smc#
Now, if I do from this code a simplistic kernel driver such as:
/* * cp15_smc.c - Demonstrating the Secure Monitor Calls (SMCs) in am335x TI armv7 A8 architecture. */ #include <linux/module.h> /* Needed by all modules */ #include <linux/kernel.h> /* Needed for KERN_INFO */ #include <linux/init.h> /* Needed for the macros */ MODULE_LICENSE("GPL"); ///< The license type -- this affects available functionality MODULE_DESCRIPTION("An armv7 A8 L2 ECC enabling driver"); ///< The description -- see modinfo MODULE_VERSION("0.01"); ///< A version number to inform users static inline void asm_enable_L2_ECC(void) { unsigned int reg_value; __asm ("mrc p15, 0, %0, c0, c2, 4" : "=r"(reg_value) ); printk(KERN_INFO "Instruction Set Attributes Register 4: 0x%08x\n", reg_value); if (0x000f0000 & reg_value) { printk(KERN_INFO "The processor does support DMB, DSB and ISB instructions\n"); } else { printk(KERN_INFO "The processor does NOT support DMB, DSB and ISB instructions\n"); return; } __asm ("stmfd sp!, {r0 - r4}"); // save contextof R0-R4,which secure monitor call may use __asm ("mrc p15, #1, %0, c9, c0, #2" : "=r"(reg_value) ); printk(KERN_INFO "L2 Cache Auxiliary Control Register 4: 0x%08x\n", reg_value); __asm ("mrc p15, #1, r0, c9, c0, #2"); // Read L2 Cache Auxiliary Control Register into R0 __asm ("mov r1, #0"); // Clear R1 __asm ("eor r1, r1, r1"); // xor R1, R1 - clear R1 __asm ("ldr r1, =#0x10200000"); // enable mask for ECC (set bits 21 and 28 to enable ECC) // __asm ("movt r1, #0x1020"); // enable mask for ECC (set bits 21 and 28 to enable ECC) __asm ("orr r0, r0, r1"); // OR with original register value __asm ("ldr r12, =#0x00000102"); // setup service ID in R12 // __asm ("movw r12, #0x0102"); // setup service ID in R12 __asm ("mcr p15, #0, r1, c7, c5, #6"); // invalidate entire branch predictor array __asm ("dsb"); // data synchronization barrier operation __asm ("isb"); // instruction synchronization barrier operation __asm ("dmb"); // data memory barrier operation // __asm ("smc #1"); // secure monitor call SMC (previously SMI) __asm ("ldmfd sp!, {r0 - r4}"); // after returning from SMC, restore R0-R4 // __asm ("mov pc, lr"); // return: does NOT work as expected, produces kernel panic! __asm ("mrc p15, #1, %0, c9, c0, #2" : "=r"(reg_value) ); printk(KERN_INFO "L2 Cache Auxiliary Control Register 4: 0x%08x\n", reg_value); return; } static int __init cp15_smc_init(void) { printk(KERN_INFO "cp15_SMC init\n"); asm_enable_L2_ECC(); return 0; } static void __exit cp15_smc_exit(void) { asm_enable_L2_ECC(); printk(KERN_INFO "cp15_SMC exit\n"); } module_init(cp15_smc_init); module_exit(cp15_smc_exit);
I get while compiling the following errors!?
root@beaglebone:~/projects/LKM/cp15_smc# make all make -C /lib/modules/5.0.15-jumpnow/build M=/home/root/projects/LKM/cp15_smc modules make[1]: Entering directory '/lib/modules/5.0.15-jumpnow/build' CC [M] /home/root/projects/LKM/cp15_smc/cp15_smc.o /tmp/ccrM1hRS.s: Assembler messages: /tmp/ccrM1hRS.s:118: Error: selected processor does not support `dsb' in ARM mode /tmp/ccrM1hRS.s:122: Error: selected processor does not support `isb' in ARM mode /tmp/ccrM1hRS.s:126: Error: selected processor does not support `dmb' in ARM mode /tmp/ccrM1hRS.s:266: Error: selected processor does not support `dsb' in ARM mode /tmp/ccrM1hRS.s:270: Error: selected processor does not support `isb' in ARM mode /tmp/ccrM1hRS.s:274: Error: selected processor does not support `dmb' in ARM mode make[2]: *** [scripts/Makefile.build:283: /home/root/projects/LKM/cp15_smc/cp15_smc.o] Error 1 make[1]: *** [Makefile:1577: _module_/home/root/projects/LKM/cp15_smc] Error 2 make[1]: Leaving directory '/lib/modules/5.0.15-jumpnow/build' make: *** [Makefile:4: all] Error 2
I use native gcc on the target BeagleBone Black (manual for silicon TI am335x here: http://www.ti.com/lit/ug/spruh73p/spruh73p.pdf )
root@beaglebone:~/projects/LKM/cp15_smc# gcc --version gcc (GCC) 8.3.0 Copyright (C) 2018 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
Why in the first case gcc compiles DSB, ISB, DMB instructions without any problems, while in the second it does not?
The SMC instruction is not recognized in both cases?!
/tmp/ccrM1hRS.s:278: Error: selected processor does not support `smc #1' in ARM mode
Why?
Thank you in advance,
_nobody_
I did more here...
Here is the new code (test.c) I run as root (in other words Supervisor Mode):
#include <stdio.h> static void asm_read_attr_reg4(void) { unsigned int reg_value; printf("Start\n"); __asm ("mrc p15, 0, %0, c0, c2, 4" : "=r"(reg_value) ); printf("Instruction Set Attributes Register 4: 0x%08x\n", reg_value); if (0x000f0000 & reg_value) { printf("The processor does support DMB, DSB and ISB instructions\n"); } else { printf("The processor does NOT support DMB, DSB and ISB instructions\n"); return; } return; } void main(void) { asm_read_attr_reg4(); }
Here are the compilation options and execution of this code:
root@beaglebone:~/projects/LKM/cp15_smc# gcc --machine=arm -march=armv7-a+fp -mfpu=vfp -mfloat-abi=hard test.c -o test root@beaglebone:~/projects/LKM/cp15_smc# ./test Start Illegal instruction root@beaglebone:~/projects/LKM/cp15_smc#
Why Illegal Instruction???
Thank you,