Skip to main content

Section 17.2 Supervisor Call

When the computer is first started, the operating system is at the EL1 exception level. This level allows the operating system kernel to access all the hardware components of the computing system. When a user launches an application, the operating system sets up the hardware resources required by the application, changes the CPU to exception level EL0 and transfers CPU control to the application.

Software executing at the EL0 level has fewer privileges with respect to accessing the hardware. For example, when preparing the hardware for running an application, the operating system allocates enough memory to load the machine code that has been marked as “.text”. The operating system can write to this area of memory because the CPU is at EL1. But when CPU control is transferred to the application, the CPU is switched to EL0, and the application is prevented from writing to any memory location that is within the .text segment.

Using exception level switching, the operating system can maintain control over all the hardware resources. This is especially important in multi-user environments, where several users can be using the same hardware resources. It is also useful to allow the operating system to make efficient use of the hardware. For example, if an application is waiting for input from the keyboard, the CPU can be used to perform another task until the user presses a key.

This raises the question of how an application can use something like the terminal window, since the operating system prevents direct access. This can be done by using an svc instruction, which generates an exception from the software that is running.

SVC

Generates an exception, often used for a supervisor call.

SVC{<c>}    <#imm>
  • <c> is the condition code, Table 9.2.1.

  • <imm> is the supervisor call number.

We can see how to use the svc instruction by rewriting the “Hello, World” program from Listing 10.3.1 to get the program in Listing 17.2.1.

@ helloWorld4.s
@ Hello World program, using system call.
@ 2017-09-29: Bob Plantz

@ Define my Raspberry Pi
        .cpu    cortex-a53
        .fpu    neon-fp-armv8
        .syntax unified         @ modern syntax

@ Useful source code constant
        .equ    STDOUT,1
        .equ    write,4

@ Constant program data
        .section  .rodata
        .align  2
helloMsg:
        .asciz	 "Hello, World!\n"
        .equ    helloLngth,.-helloMsg

@ Program code
        .text
        .align  2
        .global main
        .type   main, %function
main:
        sub     sp, sp, 16      @ space for saving regs
                                @ (keeping 8-byte sp align)
        str     r7, [sp, 4]     @ save r7
        str     fp, [sp, 8]     @      fp
        str     lr, [sp, 12]    @      lr
        add     fp, sp, 12      @ set our frame pointer

        mov     r0, STDOUT      @ file number to write to
        ldr     r1, helloMsgAddr   @ pointer to message
        mov     r2, helloLngth  @ number of bytes to write
        mov     r7, write       @ system call 'write'
        svc     0               @ write the message
        
        mov     r0, 0           @ return 0;
        ldr     r7, [sp, 4]     @ restore r7
        ldr     fp, [sp, 8]     @         fp
        ldr     lr, [sp, 12]    @         lr
        add     sp, sp, 16      @         sp
        bx      lr              @ return
        
        .align  2
helloMsgAddr:
        .word   helloMsg
Listing 17.2.1. “Hello World” program using the svc supervisor call instruction. (prog asm)

The arguments passed to the write supervisor call are the same as the write C system call function. The write request is made with:

mov     r7, write       @ system call 'write'
swi     0               @ write the message

The “write” identifier is equated to \(4\text{.}\) The numbers for each supervisor call supported by Raspbian are found in the file /usr/include/arm-linux-gnueabihf/asm/unistd.h. The appropriate number is placed in r7, and then the request for service is made with the svc 0 instruction. As you surely can guess, the write C system function call is simply a C function “wrapper” for the write supervisor call.