1// Copyright 2017 The Fuchsia Authors 2// 3// Use of this source code is governed by a MIT-style 4// license that can be found in the LICENSE file or at 5// https://opensource.org/licenses/MIT 6 7#include "constants_priv.h" 8 9.set CPACR_EL1_FPEN_NO_TRAP, (3 << 20) 10 11// See ARM ARM Table D1.10.2 for more details. 12.set CURRENT_EL_EL0_BASE, 0x000 13.set CURRENT_EL_ELx_BASE, 0x200 14.set LOWER_EL_ARCH64_BASE, 0x400 15.set LOWER_EL_ARCH32_BASE, 0x600 16.set SYNC_EXC_OFFSET, 0x000 17.set IRQ_EXC_OFFSET, 0x080 18.set FIQ_EXC_OFFSET, 0x100 19.set SERROR_EXC_OFFSET, 0x180 20 21.set SPSR_M_BIT_ARCH32, 0x010 22 23// Define new function 'name'. 24// Local label '1:' used by other macros to compute offsets. 25.macro FUNCTION name 26 .global \name 27 .type \name, STT_FUNC 28 \name: 29 1: 30.endm 31 32// Adjusts current text location to position at a specific exception handler. 33.macro exception_vector base offset 34 2: 35 .skip (\base + \offset) - (2b - 1b) 36.endm 37 38// test_complete Signals test completion by writing value (0-255) to 39// EXIT_TEST_ADDR. EXIT_TEST_ADDR is monitored by the test routine for 40// access - indicating test completion. 41.macro test_complete value=0 arch=aarch64 42 .if \value > 255 || \value < 0 43 .err 44 .endif 45 46 .ifeqs "\arch", "aarch64" 47 mov x0, EXIT_TEST_ADDR 48 .if \value == 0 49 str xzr, [x0] 50 .else 51 mov x1, \value 52 str x1, [x0] 53 .endif 54 .else 55 .ifeqs "\arch", "aarch32" 56 .word 0xE3A01000 + \value // aarch32: movw r1, \value 57 .word 0xE30F0000 // aarch32: movw r0, [lower]EXIT_TEST_ADDR 58 .word 0xE34000FF // aarch32: movw r0, [upper]EXIT_TEST_ADDR 59 .word 0xE5801000 // aarch32: str r0, [r1] 60 .else 61 .error "Unsupported architecture" 62 .endif 63 .endif 64.endm 65 66// Drop exception level from EL1 to EL0 and, if requested, switch execution 67// state. 68.macro drop_to_el0 arch=aarch64 69 .ifeqs "\arch", "aarch32" 70 mov x0, SPSR_M_BIT_ARCH32 // for aarch32, set PSTATE to AARCH32 71 msr spsr_el1, x0 // and clear everything else upon eret. 72 .else 73 .ifnes "\arch", "aarch64" // accept default architecture, do nothing. 74 .error "Unsupported architecture" 75 .endif 76 .endif 77 78 ldr w0, 2f // resume execution at label '2' ahead 79 msr elr_el1, x0 // store exception link register 80 eret // resume at el0 using specified arch. 81 2: 82 .word 2b - 1b + 4 83.endm 84 85.text 86 87// Test vcpu_resume. 88FUNCTION vcpu_resume_start 89 test_complete 90FUNCTION vcpu_resume_end 91 92// Test vcpu_interrupt. 93FUNCTION vcpu_interrupt_start 94 msr daifclr, #2 95 b . 96 97 exception_vector CURRENT_EL_ELx_BASE, IRQ_EXC_OFFSET 98 test_complete 99FUNCTION vcpu_interrupt_end 100 101// Test wfi instruction handling. 102FUNCTION vcpu_wfi_start 103 // Setup the virtual timer by: 104 // 1. Setting the compare value to 0. 105 // 2. Enabling the virtual timer. 106 msr cntv_cval_el0, xzr 107 mov x0, 1 108 msr cntv_ctl_el0, x0 109 110 wfi 111 test_complete 112FUNCTION vcpu_wfi_end 113 114// Test wfi instruction handling. 115// Execution of WFI at EL0 on AARCH32 is propagated to EL1 / AARCH64. 116FUNCTION vcpu_aarch32_wfi_start 117 drop_to_el0 aarch32 118 .word 0xE320F003 // aarch32: wfi 119 test_complete 1 aarch32 // Fail, if instruction was executed 120 // without raising exception. 121 122 exception_vector LOWER_EL_ARCH32_BASE, SYNC_EXC_OFFSET 123 test_complete 124FUNCTION vcpu_aarch32_wfi_end 125 126// Test floating-point instruction handling with trapping between levels. 127FUNCTION vcpu_fp_start 128 drop_to_el0 129 130 // Access vector registers. 131 mov w0, 0xff 132 dup v0.16b, w0 133 test_complete 134 135 // Handle EL1 floating-point trap. 136 // This is interpreted as a Lower exception level (coming from EL0) 137 // captured by AARCH64. See ARM ARM Table D1.10.2 for more details. 138 exception_vector LOWER_EL_ARCH64_BASE, SYNC_EXC_OFFSET 139 mov x0, CPACR_EL1_FPEN_NO_TRAP 140 msr cpacr_el1, x0 141 eret 142FUNCTION vcpu_fp_end 143 144// Test wfi instruction handling. 145FUNCTION vcpu_aarch32_fp_start 146 drop_to_el0 aarch32 147 // Load double precision register d0 from address 0. 148 // This should trigger floating point exception. 149 .word 0xE3A00000 // aarch32: mov r0, 0 150 .word 0xED900B00 // aarch32: vldr d0, [r0] 151 test_complete 0 aarch32 152 153 exception_vector LOWER_EL_ARCH32_BASE, SYNC_EXC_OFFSET 154 mov x0, CPACR_EL1_FPEN_NO_TRAP 155 msr cpacr_el1, x0 156 eret 157FUNCTION vcpu_aarch32_fp_end 158 159// Test vcpu_read_state and vcpu_write_state. 160FUNCTION vcpu_read_write_state_start 161 add x1, x1, #1 162 add x2, x2, #2 163 add x3, x3, #3 164 add x4, x4, #4 165 add x5, x5, #5 166 add x6, x6, #6 167 add x7, x7, #7 168 add x8, x8, #8 169 add x9, x9, #9 170 add x10, x10, #10 171 add x11, x11, #11 172 add x12, x12, #12 173 add x13, x13, #13 174 add x14, x14, #14 175 add x15, x15, #15 176 add x16, x16, #16 177 add x17, x17, #17 178 add x18, x18, #18 179 add x19, x19, #19 180 add x20, x20, #20 181 add x21, x21, #21 182 add x22, x22, #22 183 add x23, x23, #23 184 add x24, x24, #24 185 add x25, x25, #25 186 add x26, x26, #26 187 add x27, x27, #27 188 add x28, x28, #28 189 add x29, x29, #29 190 add x30, x30, #30 191 192 add sp, sp, #64 193 cmp sp, #128 // Set ZC bits of CPSR. 194 195 test_complete 196FUNCTION vcpu_read_write_state_end 197 198// Test guest_set_trap using a memory-based trap. 199FUNCTION guest_set_trap_start 200 mov x0, TRAP_ADDR 201 str xzr, [x0] 202 test_complete 203FUNCTION guest_set_trap_end 204