2.7. Supervisor Calls (SVC)

As with previous ARM cores there is an instruction, SVC (formerly SWI) that generates a supervisor call. Supervisor calls are normally used to request privileged operations or access to system resources from an operating system.

The SVC instruction has a number embedded within it, often referred to as the SVC number. This is sometimes used to indicate what the caller is requesting. On previous ARM cores you had to extract the SVC number from the instruction using the return address in the link register, and the other SVC arguments were already available in R0 through R3.

On the Cortex-M3, the core saves the argument registers to the stack on the initial exception entry. A late-arriving exception, taken before the first instruction of the SVC handler executes, might corrupt the copy of the arguments still held in R0 to R3. This means that the stack copy of the arguments must be used by the SVC handler. Any return value must also be passed back to the caller by modifying the stacked register values. In order to do this, a short piece of assembly code must be implemented as the start of the SVC handler. This identifies which stack the registers were saved to, extracts the SVC number from the instruction, and passes the number and a pointer to the arguments to the main body of the handler written in C.

Example 10 shows an example SVC handler. This code tests the EXC_RETURN value set by the processor to determine which stack pointer was in use when the SVC was called. On most systems this will be unnecessary, because in a typical system design supervisor calls will only be made from user code which uses the process stack. In this case, the assembly code can consist of a single MSR instruction followed by a tailcall branch (B instruction) to the C body of the handler.

Example 10. Example SVC Handler

__asm void SVCHandler(void){    IMPORT SVCHandler_main    TST lr, #4    MRSEQ r0, MSP    MRSNE r0, PSP    B SVCHandler_main}void SVCHandler_main(unsigned int * svc_args){    unsigned int svc_number;    /*    * Stack contains:    * r0, r1, r2, r3, r12, r14, the return address and xPSR    * First argument (r0) is svc_args[0]    */    svc_number = ((char *)svc_args[6])[-2];    switch(svc_number)    {        case SVC_00:            /* Handle SVC 00 */            break;        case SVC_01:            /* Handle SVC 01 */            break;        default:            /* Unknown SVC */            break;    }}

Example 11 shows how you can have different declarations for a number of SVCs. __svc is a compiler keyword that replaces a function call with an SVC instruction containing the specified number.

Example 11. Example of calling an SVC from C code

#define SVC_00 0x00#define SVC_01 0x01void __svc(SVC_00) svc_zero(const char *string);void __svc(SVC_01) svc_one(const char *string);int call_system_func(void){    svc_zero("String to pass to SVC handler zero");    svc_one("String to pass to a different OS function");}
Copyright © 2007. All rights reserved.ARM DAI0179B