1// Copyright 2016 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 <arch/arm64.h> 8#include <arch/debugger.h> 9#include <err.h> 10#include <kernel/thread.h> 11#include <kernel/thread_lock.h> 12#include <string.h> 13#include <sys/types.h> 14#include <zircon/syscalls/debug.h> 15#include <zircon/types.h> 16 17// Only the NZCV flags (bits 31 to 28 respectively) of the CPSR are 18// readable and writable by userland on ARM64. 19static uint32_t kUserVisibleFlags = 0xf0000000; 20 21// SS (="Single Step") is bit 0 in MDSCR_EL1. 22static constexpr uint64_t kMdscrSSMask = 1; 23 24// Single Step for PSTATE, see ARMv8 Manual C5.2.18, enable Single step for Process 25static constexpr uint64_t kSSMaskSPSR = (1 << 21); 26 27zx_status_t arch_get_general_regs(struct thread* thread, zx_thread_state_general_regs_t* out) { 28 Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()}; 29 30 // Punt if registers aren't available. E.g., 31 // ZX-563 (registers aren't available in synthetic exceptions) 32 if (thread->arch.suspended_general_regs == nullptr) 33 return ZX_ERR_NOT_SUPPORTED; 34 35 struct arm64_iframe_long* in = thread->arch.suspended_general_regs; 36 DEBUG_ASSERT(in); 37 38 static_assert(sizeof(in->r) == sizeof(out->r), ""); 39 memcpy(&out->r[0], &in->r[0], sizeof(in->r)); 40 out->lr = in->lr; 41 out->sp = in->usp; 42 out->pc = in->elr; 43 out->cpsr = in->spsr & kUserVisibleFlags; 44 45 return ZX_OK; 46} 47 48zx_status_t arch_set_general_regs(struct thread* thread, const zx_thread_state_general_regs_t* in) { 49 Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()}; 50 51 // Punt if registers aren't available. E.g., 52 // ZX-563 (registers aren't available in synthetic exceptions) 53 if (thread->arch.suspended_general_regs == nullptr) 54 return ZX_ERR_NOT_SUPPORTED; 55 56 struct arm64_iframe_long* out = thread->arch.suspended_general_regs; 57 DEBUG_ASSERT(out); 58 59 static_assert(sizeof(out->r) == sizeof(in->r), ""); 60 memcpy(&out->r[0], &in->r[0], sizeof(in->r)); 61 out->lr = in->lr; 62 out->usp = in->sp; 63 out->elr = in->pc; 64 out->spsr = (out->spsr & ~kUserVisibleFlags) | (in->cpsr & kUserVisibleFlags); 65 66 return ZX_OK; 67} 68 69zx_status_t arch_get_single_step(struct thread* thread, bool* single_step) { 70 Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()}; 71 72 // Punt if registers aren't available. E.g., 73 // ZX-563 (registers aren't available in synthetic exceptions) 74 if (thread->arch.suspended_general_regs == nullptr) 75 return ZX_ERR_NOT_SUPPORTED; 76 struct arm64_iframe_long* regs = thread->arch.suspended_general_regs; 77 78 const bool mdscr_ss_enable = !!(regs->mdscr & kMdscrSSMask); 79 const bool spsr_ss_enable = !!(regs->spsr & kSSMaskSPSR); 80 81 *single_step = mdscr_ss_enable && spsr_ss_enable; 82 return ZX_OK; 83} 84 85zx_status_t arch_set_single_step(struct thread* thread, bool single_step) { 86 Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()}; 87 88 // Punt if registers aren't available. E.g., 89 // ZX-563 (registers aren't available in synthetic exceptions) 90 if (thread->arch.suspended_general_regs == nullptr) 91 return ZX_ERR_NOT_SUPPORTED; 92 struct arm64_iframe_long* regs = thread->arch.suspended_general_regs; 93 if (single_step) { 94 regs->mdscr |= kMdscrSSMask; 95 regs->spsr |= kSSMaskSPSR; 96 } else { 97 regs->mdscr &= ~kMdscrSSMask; 98 regs->spsr &= ~kSSMaskSPSR; 99 } 100 return ZX_OK; 101} 102 103zx_status_t arch_get_fp_regs(struct thread* thread, zx_thread_state_fp_regs* out) { 104 // There are no ARM fp regs. 105 (void)out; 106 return ZX_OK; 107} 108 109zx_status_t arch_set_fp_regs(struct thread* thread, const zx_thread_state_fp_regs* in) { 110 // There are no ARM fp regs. 111 (void)in; 112 return ZX_OK; 113} 114 115zx_status_t arch_get_vector_regs(struct thread* thread, zx_thread_state_vector_regs* out) { 116 Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()}; 117 118 if (thread->state == THREAD_RUNNING) 119 return ZX_ERR_BAD_STATE; 120 121 const fpstate* in = &thread->arch.fpstate; 122 out->fpcr = in->fpcr; 123 out->fpsr = in->fpsr; 124 for (int i = 0; i < 32; i++) { 125 out->v[i].low = in->regs[i * 2]; 126 out->v[i].high = in->regs[i * 2 + 1]; 127 } 128 129 return ZX_OK; 130} 131 132zx_status_t arch_set_vector_regs(struct thread* thread, const zx_thread_state_vector_regs* in) { 133 Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()}; 134 135 if (thread->state == THREAD_RUNNING) 136 return ZX_ERR_BAD_STATE; 137 138 fpstate* out = &thread->arch.fpstate; 139 out->fpcr = in->fpcr; 140 out->fpsr = in->fpsr; 141 for (int i = 0; i < 32; i++) { 142 out->regs[i * 2] = in->v[i].low; 143 out->regs[i * 2 + 1] = in->v[i].high; 144 } 145 146 return ZX_OK; 147} 148 149zx_status_t arch_get_x86_register_fs(struct thread* thread, uint64_t* out) { 150 // There are no FS register on ARM. 151 (void)out; 152 return ZX_ERR_NOT_SUPPORTED; 153} 154 155zx_status_t arch_set_x86_register_fs(struct thread* thread, const uint64_t* in) { 156 // There are no FS register on ARM. 157 (void)in; 158 return ZX_ERR_NOT_SUPPORTED; 159} 160 161zx_status_t arch_get_x86_register_gs(struct thread* thread, uint64_t* out) { 162 // There are no GS register on ARM. 163 (void)out; 164 return ZX_ERR_NOT_SUPPORTED; 165} 166 167zx_status_t arch_set_x86_register_gs(struct thread* thread, const uint64_t* in) { 168 // There are no GS register on ARM. 169 (void)in; 170 return ZX_ERR_NOT_SUPPORTED; 171} 172