// Copyright 2016 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 "server.h"

#include <array>
#include <cinttypes>
#include <cstdio>
#include <cstdlib>
#include <limits>
#include <string>
#include <vector>

#include <zircon/syscalls.h>

#include "src/lib/fxl/arraysize.h"
#include "src/lib/fxl/logging.h"
#include "src/lib/fxl/strings/string_printf.h"

#include "garnet/lib/debugger_utils/jobs.h"
#include "garnet/lib/debugger_utils/sysinfo.h"
#include "garnet/lib/debugger_utils/util.h"

#include "control.h"

namespace insntrace {

constexpr char IptConfig::kDefaultOutputPathPrefix[];

IptConfig::IptConfig()
    : mode(kDefaultMode),
      num_cpus(zx_system_get_num_cpus()),
      max_threads(kDefaultMaxThreads),
      num_chunks(kDefaultNumChunks),
      chunk_order(kDefaultChunkOrder),
      is_circular(kDefaultIsCircular),
      branch(true),
      cr3_match(0),
      cr3_match_set(false),
      cyc(false),
      cyc_thresh(0),
      mtc(false),
      mtc_freq(0),
      psb_freq(0),
      os(true),
      user(true),
      retc(true),
      tsc(true),
      output_path_prefix(kDefaultOutputPathPrefix) {
  addr[0] = AddrFilter::kOff;
  addr[1] = AddrFilter::kOff;
}

uint64_t IptConfig::CtlMsr() const {
  uint64_t msr = 0;

  // For documentation of the fields see the description of the IA32_RTIT_CTL
  // MSR in chapter 36 "Intel Processor Trace" of Intel Volume 3.

  if (cyc)
    msr |= 1 << 1;
  if (os)
    msr |= 1 << 2;
  if (user)
    msr |= 1 << 3;
  if (cr3_match)
    msr |= 1 << 7;
  if (mtc)
    msr |= 1 << 9;
  if (tsc)
    msr |= 1 << 10;
  if (!retc)
    msr |= 1 << 11;
  if (branch)
    msr |= 1 << 13;
  msr |= (mtc_freq & 15) << 14;
  msr |= (cyc_thresh & 15) << 19;
  msr |= (psb_freq & 15) << 24;
  msr |= (uint64_t)addr[0] << 32;
  msr |= (uint64_t)addr[1] << 36;

  return msr;
}

uint64_t IptConfig::AddrBegin(unsigned i) const {
  FXL_DCHECK(i < arraysize(addr_range));
  return addr_range[i].begin;
}

uint64_t IptConfig::AddrEnd(unsigned i) const {
  FXL_DCHECK(i < arraysize(addr_range));
  return addr_range[i].end;
}

IptServer::IptServer(const IptConfig& config,
                     const debugger_utils::Argv& argv)
    : Server(debugger_utils::GetRootJob(), debugger_utils::GetDefaultJob(),
             sys::ServiceDirectory::CreateFromNamespace()),
      config_(config), inferior_argv_(argv) {}

bool IptServer::StartInferior() {
  inferior_control::Process* inferior = current_process();
  std::unique_ptr<process::ProcessBuilder> builder;

  FXL_DCHECK(!inferior_argv_.empty());
  FXL_LOG(INFO) << "Starting program: " << inferior_argv_[0];

  if (!AllocTrace(config_))
    return false;

  if (config_.mode == IPT_MODE_CPUS) {
    if (!InitTrace(config_))
      goto Fail;
  }

  if (!InitProcessTrace(config_))
    goto Fail;

  // N.B. It's important that the PT device be closed at this point as we
  // don't want the inferior to inherit the open descriptor: the device can
  // only be opened once at a time.

  if (!CreateProcessViaBuilder(inferior_argv_[0], inferior_argv_, &builder)) {
    FXL_LOG(ERROR) << "Unable to initialize process builder";
    goto Fail;
  }

  builder->CloneAll();

  if (!inferior->InitializeFromBuilder(std::move(builder))) {
    FXL_LOG(ERROR) << "Unable to initialize inferior process";
    goto Fail;
  }

  if (!config_.cr3_match_set) {
    // TODO(dje): fetch cr3 for inferior and apply it to cr3_match
  }

  // If tracing cpus, defer turning on tracing as long as possible so that we
  // don't include all the initialization. For threads it doesn't matter.
  // TODO(dje): Could even defer until the first thread is started.
  if (config_.mode == IPT_MODE_CPUS) {
    if (!StartTrace(config_))
      goto Fail;
  }

  FXL_DCHECK(!inferior->IsLive());
  if (!inferior->Start()) {
    FXL_LOG(ERROR) << "Unable to start process";
    if (config_.mode == IPT_MODE_CPUS)
      StopTrace(config_);
    goto Fail;
  }
  FXL_DCHECK(inferior->IsLive());

  return true;

Fail:
  FreeTrace(config_);
  return false;
}

bool IptServer::DumpResults() {
  if (config_.mode == IPT_MODE_CPUS)
    StopTrace(config_);
  StopSidebandDataCollection(config_);
  if (config_.mode == IPT_MODE_CPUS)
    DumpTrace(config_);
  DumpSidebandData(config_);
  if (config_.mode == IPT_MODE_CPUS)
    ResetTrace(config_);
  FreeTrace(config_);
  return true;
}

bool IptServer::Run() {
  if (!exception_port_.Run()) {
    FXL_LOG(ERROR) << "Failed to initialize exception port!";
    return false;
  }

  if (!StartInferior()) {
    FXL_LOG(ERROR) << "Failed to start inferior";
    return false;
  }

  // Start the main loop.
  message_loop_.Run();

  FXL_LOG(INFO) << "Main loop exited";

  // Tell the exception port to quit and wait for it to finish.
  exception_port_.Quit();

  if (!DumpResults()) {
    FXL_LOG(ERROR) << "Error dumping results";
    return false;
  }

  return run_status_;
}

void IptServer::OnThreadStarting(inferior_control::Process* process,
                                 inferior_control::Thread* thread,
                                 zx_handle_t eport,
                                 const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  switch (process->state()) {
    case inferior_control::Process::State::kStarting:
    case inferior_control::Process::State::kRunning:
      break;
    default:
      FXL_DCHECK(false);
  }

  if (config_.mode == IPT_MODE_THREADS) {
    if (!InitThreadTrace(thread, config_))
      goto Fail;
    if (!StartThreadTrace(thread, config_)) {
      ResetThreadTrace(thread, config_);
      goto Fail;
    }
  }

Fail:
  thread->ResumeFromException(eport);
}

void IptServer::OnThreadExiting(inferior_control::Process* process,
                                inferior_control::Thread* thread,
                                zx_handle_t eport,
                                const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  // Dump any collected trace.
  if (config_.mode == IPT_MODE_THREADS) {
    if (thread->ipt_buffer() >= 0) {
      StopThreadTrace(thread, config_);
      DumpThreadTrace(thread, config_);
      ResetThreadTrace(thread, config_);
    }
  }

  // We still have to "resume" the thread so that the o/s will complete the
  // termination of the thread.
  thread->ResumeForExit(eport);
}

void IptServer::OnProcessTermination(inferior_control::Process* process) {
  FXL_DCHECK(process);

  printf("Process %s is gone, rc %d\n", process->GetName().c_str(),
         process->return_code());

  // If the process is gone, unset current thread, and exit main loop.
  SetCurrentThread(nullptr);
  QuitMessageLoop(true);
}

void IptServer::OnArchitecturalException(
    inferior_control::Process* process, inferior_control::Thread* thread,
    zx_handle_t eport, const zx_excp_type_t type,
    const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);
  // TODO(armansito): Fine-tune this check if we ever support multi-processing.
  FXL_DCHECK(process == current_process());

  // This is generally a segv or some such. Not much we can do.
  QuitMessageLoop(true);
}

void IptServer::OnSyntheticException(inferior_control::Process* process,
                                     inferior_control::Thread* thread,
                                     zx_handle_t eport, zx_excp_type_t type,
                                     const zx_exception_context_t& context) {
  FXL_DCHECK(process);
  FXL_DCHECK(thread);

  // Program is crashing.
  QuitMessageLoop(true);
}

}  // namespace insntrace
