CS3210 Design Operating Systems

Taesoo Kim





Introduction to ARMv8/AArch64

Taesoo Kim

Administrivia

Administrivia

Q&A

Can a redesign of an OS in Rust give way to an even simpler framework of exception levels given its memory safety design?

Agenda

Overview

Overview

Overview

AArch64 and AArch32 are both Execution States unique to overall ARMv8-A architecture. AArch32 is meant to be backwards compatible with older 32-bit dependent versions of ARM like ARMv7-A. AArch64 is the state unique to ARMv8-A. AArch32 is comes bundled with the ARM Virtualization Extensions, Security Extensions, and Large Physical Address Extension. ARMv8-A also allows for the execution of code in both Execution States (32 vs 64) within the OS kernel or hypervisor layers.

Exception level / Execution states

Execution states of AArch32/64

Changing execution levels (target mode)

Execution state

Registers (in AArch64)

Special registers

Processor state (PSTATE)

Accessing PSTATE

MRS X0, SPSel   // Read SPSel into X0
MSR SPSel, X0   // Write X0 to SPSel

Accessing PSTATE

MSR DAIFSet, #Imm4  // Used to set any or all of DAIF to 1
MSR DAIFClr, #Imm4  // Used to clear any or all of DAIF to 0

System registers

System control registers

Tastes of instructions: accessing memory

ldr r0, [r3]      // r0 = *r3 (i.e., r0 = *(0x1234))
str r0, [r3]      // *r3 = r0 (i.e., *(0x1234) = r0)

Tastes of instructions: accessing memory

// Offset
ldr r0, [r3, #64]      // r0 = *(r3 + 64)
str r0, [r3, #-12]     // *(r3 - 12) = r0

// Post-index
ldr r0, [r3], #30      // r0 = *r3; r3 += 30
str r0, [r3], #-12     // *r3 = r0; r3 -= 12

// Pre-index
ldr r0, [r3, #30]!     // r3 += 30; r0 = *r3
str r0, [r3, #-12]!    // r3 -= 12; *r3 = r0

Tastes of instructions: accessing stack

// push `x0` and `x1` onto the stack. after this operation the stack is:
//
//   |------| <- SP
//   |  x0  |
//   |------|
//   |  x1  |
//   |------| <x (original SP)
//
stp x0, x1, [SP, #-16]!

Tastes of instructions: accessing stack

// pop `x0` and `x1` from the stack. after this operation, the stack is:
//
//   |------| <x (original SP)
//   |  x0  |
//   |------|
//   |  x1  |
//   |------| <- SP
//
ldp x0, x1, [SP], #16

Tastes of instructions: loading immediates

mov   x0, #0xABCD, LSL #32  // x0 = 0xABCD00000000
mov   x0, #0x1234, LSL #16  // x0 = 0x12340000

mov   x1, #0xBEEF           // x1 = 0xBEEF
movk  x1, #0xDEAD, LSL #16  // x1 = 0xDEADBEEF
movk  x1, #0xF00D, LSL #32  // x1 = 0xF00DDEADBEEF
movk  x1, #0xFEED, LSL #48  // x1 = 0xFEEDF00DDEADBEEF

Tastes of instructions: branching

my_function:
    add x0, x0, x1
    ret

mov  x0, #4
mov  x1, #30
bl   my_function  // lr = address of `mov x3, x0`
mov  x3, x0       // x3 = x0 = 4 + 30 = 34

Next plan

References