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