I have a small function which I have added in kernel source (linux 3.0) which does some task and works fine in SVC mode. But in interrupt mode (i.e., when timer interrupts are enabled in kernel through local_irq_enable
) it does not work. So I am thinking of switching to SVC mode before executing my function. I have taken code for switching modes from one of the posts.
void myfunction(..some args)
{
unsigned int oldmode = get_cpsr() & 0x1f;
if (oldmode == 18) // Check for IRQ mode
change_mode(MODE_SVC);
// ...My code ....
restore_mode(oldmode);
}
Definitions are as follows:
#define MODE_IRQ 0x12
#define MODE_SVC 0x13
#define change_mode(mode) asm("cps %0" : : "I"(mode))
#define restore_mode(mode) \
mode &= 0x1f; \
asm(" msr cpsr, %0\n" : : "r"(mode) : "cc")
static inline unsigned int get_cpsr(void)
{
unsigned int val;
__asm__ __volatile__ (" mrs %0, cpsr\n"
: "=r" (val));
return val;
}
Even after this I am not getting correct output. Function execution gets stuck somewhere. I have debugged the address where it gets stuck and it is pointing to these symbols of System.map
__exception_text_start
_stext
asm_do_IRQ
Is my usage of function correct. Can you suggest me any other solution for this problem. I am running this image then on ARMv7 board. And lastly there are calls to some kernel APIs like printch()
in my function after changing mode.