// Copyright 2016 The Fuchsia Authors
//
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file or at
// https://opensource.org/licenses/MIT

#include <arch/arm64.h>
#include <arch/arm64/registers.h>
#include <arch/debugger.h>
#include <err.h>
#include <kernel/thread.h>
#include <kernel/thread_lock.h>
#include <string.h>
#include <sys/types.h>
#include <zircon/syscalls/debug.h>
#include <zircon/types.h>

// Only the NZCV flags (bits 31 to 28 respectively) of the CPSR are
// readable and writable by userland on ARM64.
static uint32_t kUserVisibleFlags = 0xf0000000;

// SS (="Single Step") is bit 0 in MDSCR_EL1.
static constexpr uint64_t kMdscrSSMask = 1;

// Single Step for PSTATE, see ARMv8 Manual C5.2.18, enable Single step for Process
static constexpr uint64_t kSSMaskSPSR = (1 << 21);

zx_status_t arch_get_general_regs(struct thread* thread, zx_thread_state_general_regs_t* out) {
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    // Punt if registers aren't available. E.g.,
    // ZX-563 (registers aren't available in synthetic exceptions)
    if (thread->arch.suspended_general_regs == nullptr)
        return ZX_ERR_NOT_SUPPORTED;

    struct arm64_iframe_long* in = thread->arch.suspended_general_regs;
    DEBUG_ASSERT(in);

    static_assert(sizeof(in->r) == sizeof(out->r), "");
    memcpy(&out->r[0], &in->r[0], sizeof(in->r));
    out->lr = in->lr;
    out->sp = in->usp;
    out->pc = in->elr;
    out->cpsr = in->spsr & kUserVisibleFlags;

    return ZX_OK;
}

zx_status_t arch_set_general_regs(struct thread* thread, const zx_thread_state_general_regs_t* in) {
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    // Punt if registers aren't available. E.g.,
    // ZX-563 (registers aren't available in synthetic exceptions)
    if (thread->arch.suspended_general_regs == nullptr)
        return ZX_ERR_NOT_SUPPORTED;

    struct arm64_iframe_long* out = thread->arch.suspended_general_regs;
    DEBUG_ASSERT(out);

    static_assert(sizeof(out->r) == sizeof(in->r), "");
    memcpy(&out->r[0], &in->r[0], sizeof(in->r));
    out->lr = in->lr;
    out->usp = in->sp;
    out->elr = in->pc;
    out->spsr = (out->spsr & ~kUserVisibleFlags) | (in->cpsr & kUserVisibleFlags);

    return ZX_OK;
}

zx_status_t arch_get_single_step(struct thread* thread, bool* single_step) {
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    // Punt if registers aren't available. E.g.,
    // ZX-563 (registers aren't available in synthetic exceptions)
    if (thread->arch.suspended_general_regs == nullptr)
        return ZX_ERR_NOT_SUPPORTED;
    struct arm64_iframe_long* regs = thread->arch.suspended_general_regs;

    const bool mdscr_ss_enable = !!(regs->mdscr & kMdscrSSMask);
    const bool spsr_ss_enable = !!(regs->spsr & kSSMaskSPSR);

    *single_step = mdscr_ss_enable && spsr_ss_enable;
    return ZX_OK;
}

zx_status_t arch_set_single_step(struct thread* thread, bool single_step) {
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    // Punt if registers aren't available. E.g.,
    // ZX-563 (registers aren't available in synthetic exceptions)
    if (thread->arch.suspended_general_regs == nullptr)
        return ZX_ERR_NOT_SUPPORTED;
    struct arm64_iframe_long* regs = thread->arch.suspended_general_regs;
    if (single_step) {
        regs->mdscr |= kMdscrSSMask;
        regs->spsr |= kSSMaskSPSR;
    } else {
        regs->mdscr &= ~kMdscrSSMask;
        regs->spsr &= ~kSSMaskSPSR;
    }
    return ZX_OK;
}

zx_status_t arch_get_fp_regs(struct thread* thread, zx_thread_state_fp_regs* out) {
    // There are no ARM fp regs.
    (void)out;
    return ZX_OK;
}

zx_status_t arch_set_fp_regs(struct thread* thread, const zx_thread_state_fp_regs* in) {
    // There are no ARM fp regs.
    (void)in;
    return ZX_OK;
}

zx_status_t arch_get_vector_regs(struct thread* thread, zx_thread_state_vector_regs* out) {
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    const fpstate* in = &thread->arch.fpstate;
    out->fpcr = in->fpcr;
    out->fpsr = in->fpsr;
    for (int i = 0; i < 32; i++) {
        out->v[i].low = in->regs[i * 2];
        out->v[i].high = in->regs[i * 2 + 1];
    }

    return ZX_OK;
}

zx_status_t arch_set_vector_regs(struct thread* thread, const zx_thread_state_vector_regs* in) {
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    fpstate* out = &thread->arch.fpstate;
    out->fpcr = in->fpcr;
    out->fpsr = in->fpsr;
    for (int i = 0; i < 32; i++) {
        out->regs[i * 2] = in->v[i].low;
        out->regs[i * 2 + 1] = in->v[i].high;
    }

    return ZX_OK;
}

zx_status_t arch_get_debug_regs(struct thread* thread, zx_thread_state_debug_regs* out) {
    out->hw_bps_count = arm64_hw_breakpoint_count();
    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};

    // The kernel ensures that this state is being kept up to date, so we can safely copy the
    // information over.
    for (size_t i = 0; i < out->hw_bps_count; i++) {
        out->hw_bps[i].dbgbcr = thread->arch.debug_state.hw_bps[i].dbgbcr;
        out->hw_bps[i].dbgbvr = thread->arch.debug_state.hw_bps[i].dbgbvr;
    }

    // Hacked through the last debug registers for now for development.
    // THIS CODE WILL GO AWAY!
    // This normally doesn't affect functionality as normally a CPU implementation has around six
    // debug registers.
    // TODO(ZX-3038): This should be exposed through a standard interface.
    //                Either the sysinfo fidl, the vDSO info mapping or some other mechanism.
    out->hw_bps[AARCH64_MAX_HW_BREAKPOINTS - 1].dbgbvr = __arm_rsr64("id_aa64dfr0_el1");
    out->hw_bps[AARCH64_MAX_HW_BREAKPOINTS - 2].dbgbvr = __arm_rsr64("mdscr_el1");

    return ZX_OK;
}

zx_status_t arch_set_debug_regs(struct thread* thread, const zx_thread_state_debug_regs* in) {
    arm64_debug_state_t state = {};

    // We copy over the state from the input.
    uint64_t bp_count = arm64_hw_breakpoint_count();
    for (size_t i = 0; i < bp_count; i++) {
        state.hw_bps[i].dbgbcr = in->hw_bps[i].dbgbcr;
        state.hw_bps[i].dbgbvr = in->hw_bps[i].dbgbvr;
    }

    if (!arm64_validate_debug_state(&state)) {
        return ZX_ERR_INVALID_ARGS;
    }

    Guard<spin_lock_t, IrqSave> thread_lock_guard{ThreadLock::Get()};
    thread->arch.track_debug_state = true;
    thread->arch.debug_state = state;

    return ZX_OK;
}

zx_status_t arch_get_x86_register_fs(struct thread* thread, uint64_t* out) {
    // There are no FS register on ARM.
    (void)out;
    return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t arch_set_x86_register_fs(struct thread* thread, const uint64_t* in) {
    // There are no FS register on ARM.
    (void)in;
    return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t arch_get_x86_register_gs(struct thread* thread, uint64_t* out) {
    // There are no GS register on ARM.
    (void)out;
    return ZX_ERR_NOT_SUPPORTED;
}

zx_status_t arch_set_x86_register_gs(struct thread* thread, const uint64_t* in) {
    // There are no GS register on ARM.
    (void)in;
    return ZX_ERR_NOT_SUPPORTED;
}
