// Copyright 2019 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <zircon/process.h>
#include <zircon/status.h>
#include <zircon/threads.h>

#include <atomic>

#include <test-utils/test-utils.h>
#include <zxtest/zxtest.h>

#include "inferior-control.h"
#include "inferior.h"
#include "utils.h"

namespace {

std::atomic<bool> gBreakpointThreadShouldContinue;

int hw_breakpoint_function(void*) {
  while (gBreakpointThreadShouldContinue) {
    zx_nanosleep(zx_deadline_after(ZX_SEC(1)));
  }
  return 0;
}

#if defined(__x86_64__)

zx_status_t set_hw_breakpoint(zx_handle_t thread_handle) {
  // TODO(donosoc): Implement one public place to get the debug masks values.
  zx_thread_state_debug_regs_t debug_regs = {};
  debug_regs.dr[0] = reinterpret_cast<uint64_t>(hw_breakpoint_function);
  debug_regs.dr7 = 1 |          // DR70 Enable
                   0b10 << 18;  // DR70 LEN

  return zx_thread_write_state(thread_handle, ZX_THREAD_STATE_DEBUG_REGS, &debug_regs,
                               sizeof(debug_regs));
}

#elif defined(__aarch64__)

zx_status_t set_hw_breakpoint(zx_handle_t thread_handle) {
  zx_thread_state_debug_regs_t debug_regs = {};
  auto& hw_bp = debug_regs.hw_bps[0];
  hw_bp.dbgbcr = 1;  // Activate it.
  hw_bp.dbgbvr = reinterpret_cast<uint64_t>(hw_breakpoint_function);

  return zx_thread_write_state(thread_handle, ZX_THREAD_STATE_DEBUG_REGS, &debug_regs,
                               sizeof(debug_regs));
}

#elif defined(__riscv)

zx_status_t set_hw_breakpoint(zx_handle_t thread_handle) { return ZX_ERR_NOT_SUPPORTED; }

#else
#error Unsupported arch.
#endif

zx_status_t unset_hw_breakpoint(zx_handle_t thread_handle) {
  zx_thread_state_debug_regs_t debug_regs = {};
  return zx_thread_write_state(thread_handle, ZX_THREAD_STATE_DEBUG_REGS, &debug_regs,
                               sizeof(debug_regs));
}

void test_hw_breakpoint_impl(zx_handle_t excp_channel) {
  gBreakpointThreadShouldContinue = false;

  thrd_t thread;
  thrd_create(&thread, hw_breakpoint_function, nullptr);
  zx_handle_t thread_handle = thrd_get_zx_handle(thread);

  zx_status_t status;

  zx_handle_t suspend_token;
  status = zx_task_suspend(thread_handle, &suspend_token);
  ASSERT_EQ(status, ZX_OK);

  zx_signals_t observed;
  status = zx_object_wait_one(thread_handle, ZX_THREAD_SUSPENDED,
                              zx_deadline_after(ZX_TIME_INFINITE), &observed);
  ASSERT_EQ(status, ZX_OK);
  ASSERT_TRUE((observed & ZX_THREAD_SUSPENDED) != 0);

  // Verify that the thread is suspended.
  zx_info_thread thread_info;
  status = zx_object_get_info(thread_handle, ZX_INFO_THREAD, &thread_info, sizeof(thread_info),
                              nullptr, nullptr);
  ASSERT_TRUE(status == ZX_OK);
  ASSERT_TRUE(thread_info.state == ZX_THREAD_STATE_SUSPENDED);

  printf("HW Breakpoint: Writing debug registers.\n");

  status = set_hw_breakpoint(thread_handle);
  ASSERT_EQ(status, ZX_OK);

  printf("Watchpoint: Resuming thread.\n");
  zx_handle_close(suspend_token);

  // We wait for the exception.
  tu_channel_wait_readable(excp_channel);

  zx_handle_t exception;
  zx_exception_info_t info;
  uint32_t num_bytes = sizeof(info);
  uint32_t num_handles = 1;
  status =
      zx_channel_read(excp_channel, 0, &info, &exception, num_bytes, num_handles, nullptr, nullptr);
  ASSERT_EQ(status, ZX_OK);

  ASSERT_EQ(info.type, ZX_EXCP_HW_BREAKPOINT);

  // Clear the state and resume the thread.
  status = unset_hw_breakpoint(thread_handle);
  ASSERT_EQ(status, ZX_OK);
  gBreakpointThreadShouldContinue = false;

  uint32_t state = ZX_EXCEPTION_STATE_HANDLED;
  status = zx_object_set_property(exception, ZX_PROP_EXCEPTION_STATE, &state, sizeof(state));
  ASSERT_EQ(status, ZX_OK);

  zx_handle_close(exception);

  // join the thread.
  int res = -1;
  ASSERT_EQ(thrd_join(thread, &res), thrd_success);
  ASSERT_EQ(res, 0);
}

}  // namespace

TEST(HwBreakpointStartTests, HWBreakpointTest) {
  // TODO(https://fxbug.dev/42110697): This test flakes.
  return;

#if defined(__x86_64__)
  // This test crashes QEMU, so for it's disabled for that arch.
  return;
#endif

  zx_handle_t excp_channel = ZX_HANDLE_INVALID;
  ASSERT_EQ(zx_task_create_exception_channel(zx_process_self(), 0, &excp_channel), ZX_OK);

  test_hw_breakpoint_impl(excp_channel);

  zx_handle_close(excp_channel);
}
