// 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 <lib/zircon-internal/macros.h>
#include <string.h>
#include <sys/types.h>
#include <zircon/errors.h>
#include <zircon/syscalls/debug.h>
#include <zircon/types.h>

#include <arch/arm64.h>
#include <arch/arm64/registers.h>
#include <arch/debugger.h>
#include <arch/regs.h>
#include <kernel/thread.h>
#include <kernel/thread_lock.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(Thread* thread, zx_thread_state_general_regs_t* out) {
  Guard<MonitoredSpinLock, IrqSave> thread_lock_guard{ThreadLock::Get(), SOURCE_TAG};

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  // Punt if registers aren't available. E.g.,
  // TODO(fxbug.dev/30521): Registers aren't available in synthetic exceptions.
  if (thread->arch().suspended_general_regs == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  iframe_t* 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;
  out->tpidr = thread->arch().tpidr_el0;

  return ZX_OK;
}

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

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  // Punt if registers aren't available. E.g.,
  // TODO(fxbug.dev/30521): Registers aren't available in synthetic exceptions.
  if (thread->arch().suspended_general_regs == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  iframe_t* 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);
  thread->arch().tpidr_el0 = in->tpidr;

  return ZX_OK;
}

zx_status_t arch_get_single_step(Thread* thread, zx_thread_state_single_step_t* out) {
  Guard<MonitoredSpinLock, IrqSave> thread_lock_guard{ThreadLock::Get(), SOURCE_TAG};

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  // Punt if registers aren't available. E.g.,
  // TODO(fxbug.dev/30521): Registers aren't available in synthetic exceptions.
  if (thread->arch().suspended_general_regs == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  iframe_t* regs = thread->arch().suspended_general_regs;

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

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

zx_status_t arch_set_single_step(Thread* thread, const zx_thread_state_single_step_t* in) {
  if (*in != 0 && *in != 1) {
    return ZX_ERR_INVALID_ARGS;
  }

  Guard<MonitoredSpinLock, IrqSave> thread_lock_guard{ThreadLock::Get(), SOURCE_TAG};

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  // Punt if registers aren't available. E.g.,
  // TODO(fxbug.dev/30521): Registers aren't available in synthetic exceptions.
  if (thread->arch().suspended_general_regs == nullptr) {
    return ZX_ERR_NOT_SUPPORTED;
  }
  iframe_t* regs = thread->arch().suspended_general_regs;
  if (*in) {
    regs->mdscr |= kMdscrSSMask;
    regs->spsr |= kSSMaskSPSR;
  } else {
    regs->mdscr &= ~kMdscrSSMask;
    regs->spsr &= ~kSSMaskSPSR;
  }
  return ZX_OK;
}

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

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

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

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  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(Thread* thread, const zx_thread_state_vector_regs* in) {
  Guard<MonitoredSpinLock, IrqSave> thread_lock_guard{ThreadLock::Get(), SOURCE_TAG};

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  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(Thread* thread, zx_thread_state_debug_regs* out) {
  *out = {};
  out->hw_bps_count = arm64_hw_breakpoint_count();
  out->hw_wps_count = arm64_hw_watchpoint_count();

  Guard<MonitoredSpinLock, IrqSave> thread_lock_guard{ThreadLock::Get(), SOURCE_TAG};

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  // The kernel ensures that this state is being kept up to date, so we can safely copy the
  // information over.

  // HW breakpoints.
  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;
  }

  // Watchpoints.
  for (size_t i = 0; i < out->hw_wps_count; i++) {
    out->hw_wps[i].dbgwcr = thread->arch().debug_state.hw_wps[i].dbgwcr;
    out->hw_wps[i].dbgwvr = thread->arch().debug_state.hw_wps[i].dbgwvr;
  }

  out->esr = thread->arch().debug_state.esr;
  out->far = thread->arch().debug_state.far;

  return ZX_OK;
}

zx_status_t arch_set_debug_regs(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;
  }

  uint64_t wp_count = arm64_hw_watchpoint_count();
  for (size_t i = 0; i < wp_count; i++) {
    state.hw_wps[i].dbgwcr = in->hw_wps[i].dbgwcr;
    state.hw_wps[i].dbgwvr = in->hw_wps[i].dbgwvr;
  }

  uint32_t active_breakpoints = 0;
  uint32_t active_watchpoints = 0;
  if (!arm64_validate_debug_state(&state, &active_breakpoints, &active_watchpoints)) {
    return ZX_ERR_INVALID_ARGS;
  }

  Guard<MonitoredSpinLock, IrqSave> thread_lock_guard{ThreadLock::Get(), SOURCE_TAG};

  DEBUG_ASSERT(thread->IsUserStateSavedLocked());

  // If the suspended registers are not there, we cannot save the MDSCR values for this thread,
  // meaning that the debug HW state will be cleared almost immediatelly.
  // This should always be there.
  // TODO(fxbug.dev/30521): Registers aren't available in synthetic exceptions.
  if (!thread->arch().suspended_general_regs) {
    return ZX_ERR_NOT_SUPPORTED;
  }

  bool hw_debug_needed = (active_breakpoints > 0) || (active_watchpoints > 0);

  arm64_set_debug_state_for_thread(thread, hw_debug_needed);
  state.esr = thread->arch().debug_state.esr;
  state.far = thread->arch().debug_state.far;

  thread->arch().track_debug_state = true;
  thread->arch().debug_state = state;

  return ZX_OK;
}

uint8_t arch_get_hw_breakpoint_count() { return arm64_hw_breakpoint_count(); }

uint8_t arch_get_hw_watchpoint_count() { return arm64_hw_watchpoint_count(); }
