This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Big problems using DSB, ISB, DMB and SMC mnemonics with armv7 A8 TI Sitara am335x

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,

    _nobody_