linux kernel - How Can I put ARM processor in different modes using C program? -
i going through different mode of arm processor. want check processor state(ex: register values) while in different mode.
so can me find out sample code put processor in different mode ?
for example found code undefined mode: asm volatile (".short 0xffff\n");
if wish test modes user space, difficult question. there maybe no way go fiq mode, if there no fiq peripheral in system. system may not using monitor mode @ all, etc. abort mode, can use invalid pointer, or use mmap
. however, answer mode switches user space book (or impossible) without assistance kernel. creating test module /proc or /sys file , using techniques below implement kernel code straight forward method.
you should aware not mode switch transitions allowed. instance, may never switch user mode other mode except through exception mechanisms. issue each arm mode has banked registers. 1 of these important sp
(or stack pointer) , lr
(or link register) that fundamental 'c' code.
it more safe use macro of in-line assembler bound test snippets, use function calls. test code must not call external routines. can difficult using floating point, etc may result in compiler inserting hidden sub-routine calls. should inspect generated assembler , provide comments others.
/* current mode restoration. */ static inline unsigned int get_cpsr(void) { unsigned int rval; asm (" mrs %0, cpsr\n" : "=r" (rval)); return rval; }
you can put in header file. compiler inline code so, msr
instruction placed within routine.
to change mode use define like,
/* change mode */ #define change_mode(mode) asm("cps %0" : : "i"(mode))
tangr's has correct mode defines,
#define mode_usr 0x10 /* never use one, there no way back! */ #define mode_fiq 0x11 /* banked r8-r14 */ #define mode_irq 0x12 #define mode_svc 0x13 #define mode_mon 0x16 #define mode_abt 0x17 #define mode_und 0x1b #define mode_sys 0x1f /* same user... */
you need restore previous mode,
#define restore_mode(mode) \ mode &= 0x1f; \ asm(" msr cpsr, %0\n" : : "r"(mode) : "cc")
put follows,
void test_abort(void) { unsigned int old_mode = get_cpsr() & 0x1f; change_mode(mode_abt); /* test code here... must not call functions. */ restore_mode(old_mode); }
this answers question directly. however, due of difficulties, easier write assembler achieve test. believe trying leverage existing linux code test modes. not arm-linux design goal , without modifying source, difficult achieve , highly system specific if is.
Comments
Post a Comment