CS452 - Real-Time Programming - Winter 2015

Lecture 5 - Context Switches

Public Service Annoucements

  1. Due date for kernel 1, 26 May
  2. Partners: please let me know who you are.

Kernel of a Real-time Operating System

Kernel Structure

The kernel is just a function like any other, but which runs forever.

kernel( ) {
  initialize( );  // includes starting the first user task
  FOREVER {
    request = getNextRequest( );
    handle( request );
  }
}


All the interesting stuff inside done by the kernel is hidden inside getNextRequest.

int getNextRequest( ) {
  active = schedule( ... );
  return activate( active );

What's inside activate( active )?

  1. transfer of control to the active task
  2. execution to completion of the active task
  3. transfer of control back to the kernel

The hard part to get right is `transfer of control'


ARM 920T core

Specific documentation from ARM, which covers

Features

  1. 16 32-bit registers

    partially separate register sets in different modes

    some registers are special, but not very special

General Comments

  1. each instruction is exactly one word
  2. load and store RISC architecture
  3. rich set of addressing modes, based on barrel shifting
  4. allows you to keep any partial computation it makes

Context Switch

What gcc does

Register use

Function call

  1. Save r0-r3 into local variables.
  2. Put arguments into r0-r3.
  3. bl  #entry
    	lr gets pc; pc gets #entry
          
  4. ip gets sp
  5. save {fp, ip, lr} on stack; also registers written
  6. application code
  7. pop {fp, ip, pc} from stack; possibly others. This returns from the function.
  8. put r0 (return value) into local variable

Step-by-step

Function Call (gcc calling conventions)

; In calling code
                      ; store values of r0-r3
                      ; load arguments into r0-r3
   bl  #entry - pc   ; this treats the pc and lr specially: lr <- pc, pc <- <entry>
                      ; On return: r0 has the return value, r1-r3 have useless junk

; In called code
entry:
   mov     ip, sp
   stmdb   sp!, {fp, ip, lr} ; and sometimes others, 
                             ; determined by the registers the function uses
   ...
   ldmia   sp, {fp, sp, pc} ; and whatever others
                            ; exact inverse of stmdb

This sequence of four instructions is an example of the NOP design pattern, named by Bobby Xiao.

Note the role of the index pointer (ip), link register (lr) and stack pointer (sp).

The final instruction could be

   ldmia   sp, {fp, sp, lr}
   mov     pc, lr

The sequence

   bl   <junk> - pc
   .
   .
   .
junk:
   mov   pc, lr

is also a NOP.

Software Interrupt

The software interrupt instruction ( SWI{cond} <immed_24> ). What happens when it is executed?

  1. lr_svc gets address of the following instruction. This is where the kernel will return to.
  2. SPSR_svc gets CPSR. This saves the mode, condition codes, etc.
  3. CPSR[0:4] gets 0b10011. Supervisor mode.
  4. CPSR[5] gets 0. ARM (not Thumb) state.
  5. CPSR[6] gets 1. Privileged interrupts disabled.
  6. CPSR[7] gets 1. Normal interrupts disabled.
  7. PC gets 0x08

The CPU ignores the 24-bit immediate value, which can be used by the programmer as another argument, usually identifying the system call.

; In calling code
                          ; Store r0-r3 ; Put arguments into r0-r3
                          ; 0x28 holds the kernel entry point
   swi  n                 ; n identifies the system call
                          ; retrieve return value from r0 ; r1-r3 have useless junk

; In kernel
kernel entry:
			   ; Change to system mode
			   ; Save user state on user stack
			   ; Return to supervisor mode
   ldr    r4, [lr, #-4]    ; gets the request type
                           ; at this point you can get the arguments
                           ; Where are they?
			   ; Retrieve kernel state from kernel stack
			   ; Do kernel work

The sequence

   swi   n
   .
   .
   .
kernel entry:
   movs   pc, lr

is a NOP. The 's' in movs puts the SPSW into pc.

Questions:

  1. What is above kernel entry?
  2. If you put swi in a wrapper or stub what happens before and after it?
  3. If the request had arguments, how would you get them into the kernel?

    Hint. How does gcc pass arguments into a function?

  4. It might be important that there are two link registers. Which two link registers? Why?
  5. In practice it isn't important. Why not?

Suggestions:

  1. Try this first on paper drawing the stack, registers, etc after each instruction
  2. Try coding in baby steps, which is usually a good idea in assembly language.

Try reading this.


Return to: