// 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 "garnet/bin/insntrace/control.h"

#include <fcntl.h>
#include <fuchsia/hardware/cpu/insntrace/cpp/fidl.h>
#include <lib/fdio/directory.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/syslog/cpp/macros.h>
#include <lib/zircon-internal/device/cpu-trace/intel-pt.h>
#include <lib/zircon-internal/ktrace.h>
#include <lib/zx/handle.h>
#include <lib/zx/vmo.h>
#include <link.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <zircon/syscalls.h>

#include <cinttypes>
#include <iostream>

#include <fbl/unique_fd.h>

#include "garnet/bin/insntrace/config.h"
#include "garnet/bin/insntrace/ktrace_controller.h"
#include "garnet/bin/insntrace/utils.h"
#include "garnet/lib/debugger_utils/util.h"
#include "garnet/lib/debugger_utils/x86_cpuid.h"
#include "garnet/lib/debugger_utils/x86_pt.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace insntrace {

using Allocation = ::fuchsia::hardware::cpu::insntrace::Allocation;
using BufferConfig = ::fuchsia::hardware::cpu::insntrace::BufferConfig;
using BufferState = ::fuchsia::hardware::cpu::insntrace::BufferState;
using ControllerSyncPtr = ::fuchsia::hardware::cpu::insntrace::ControllerSyncPtr;

// This isn't emitted by the fidl compiler.
using BufferDescriptor = uint32_t;

static constexpr char ipt_device_path[] = "/dev/sys/cpu-trace/insntrace";

static constexpr char buffer_output_path_suffix[] = "pt";
static constexpr char ktrace_output_path_suffix[] = "ktrace";
static constexpr char cpuid_output_path_suffix[] = "cpuid";
static constexpr char pt_list_output_path_suffix[] = "ptlist";

static constexpr uint32_t kKtraceGroupMask = KTRACE_GRP_ARCH | KTRACE_GRP_TASKS;

static ControllerSyncPtr OpenDevice() {
  ControllerSyncPtr controller_ptr;
  zx_status_t status =
      fdio_service_connect(ipt_device_path, controller_ptr.NewRequest().TakeChannel().release());
  if (status != ZX_OK) {
    FX_LOGS(ERROR) << "Error connecting to " << ipt_device_path << ": " << status;
    return ControllerSyncPtr();
  }
  return controller_ptr;
}

bool AllocTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "AllocTrace called";

  ControllerSyncPtr ipt{OpenDevice()};
  if (!ipt) {
    return false;
  }

  Allocation allocation;
  // TODO(61706): memset is done as the padding is set to 0xAA in release builds and encoding of the
  // FIDL request fails as the non-zero padding is also copied to the FIDL message.
  // Remove this once the bug is fixed.
  memset(&allocation, 0x0, sizeof(Allocation));
  allocation.mode = config.mode;
  allocation.num_traces = (config.mode == Mode::CPU ? config.num_cpus : config.max_threads);
  FX_VLOGS(2) << fxl::StringPrintf("mode=%u, num_traces=0x%x",
                                   static_cast<unsigned>(allocation.mode), allocation.num_traces);

  ::fuchsia::hardware::cpu::insntrace::Controller_Initialize_Result result;
  zx_status_t status = ipt->Initialize(allocation, &result);
  if (status != ZX_OK || result.is_err()) {
    LogFidlFailure("Initialize", status, result.err());
    return false;
  }

  return true;
}

static void InitIptBufferConfig(BufferConfig* ipt_config, const IptConfig& config) {
  memset(ipt_config, 0, sizeof(*ipt_config));
  ipt_config->num_chunks = config.num_chunks;
  ipt_config->chunk_order = config.chunk_order;
  ipt_config->is_circular = config.is_circular;
  ipt_config->ctl = config.CtlMsr();
  ipt_config->address_space_match = config.cr3_match;
  ipt_config->address_range_0.start = config.AddrBegin(0);
  ipt_config->address_range_0.end = config.AddrEnd(0);
  ipt_config->address_range_1.start = config.AddrBegin(1);
  ipt_config->address_range_1.end = config.AddrEnd(1);
}

bool InitTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "InitTrace called";
  FX_DCHECK(config.mode == Mode::CPU);

  ControllerSyncPtr ipt{OpenDevice()};
  if (!ipt) {
    return false;
  }

  for (uint32_t cpu = 0; cpu < config.num_cpus; ++cpu) {
    BufferConfig ipt_config;
    InitIptBufferConfig(&ipt_config, config);

    ::fuchsia::hardware::cpu::insntrace::Controller_AllocateBuffer_Result result;
    zx_status_t status = ipt->AllocateBuffer(ipt_config, &result);
    if (status != ZX_OK || result.is_err()) {
      LogFidlFailure("AllocateBuffer", status, result.err());
      return false;
    }
    // Buffers are automagically assigned to cpus, descriptor == cpu#,
    // so we can just ignore descriptor here.
  }

  return true;
}

// This must be called before a process is started so we emit a ktrace
// process start record for it.

bool InitProcessTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "InitProcessTrace called";

  fuchsia::tracing::kernel::ControllerSyncPtr ktrace;
  if (OpenKtraceControllerChannel(&ktrace) != ZX_OK) {
    return false;
  }

  // If tracing cpus we may want all the records for processes that were
  // started during boot, so don't reset ktrace here. If tracing threads it
  // doesn't much matter other than hopefully the necessary records don't get
  // over run, which is handled below by only enabling the collection groups
  // we need. So for now leave existing records alone.
  // A better solution would be to collect the data we need at the time we
  // need it.
#if 0  // TODO(dje)
  if (config.mode == Mode::THREAD) {
    RequestKtraceStop(ktrace);
    RequestKtraceRewind(ktrace);
  }
#endif

  // We definitely need ktrace turned on in order to get cr3->pid mappings,
  // which we need to map trace cr3 values to ld.so mappings, which we need in
  // order to be able to find the ELFs, which are required by the decoder.
  // So this isn't a nice-to-have, we need it. It's possible ktrace is
  // currently off, so ensure it's turned on.
  // For now just include arch info in the ktrace - we need it, and we don't
  // want to risk the ktrace buffer filling without it.
  // Also include task info to get process exit records - we need to know when
  // a cr3 value becomes invalid. Hopefully this won't cause the buffer to
  // overrun. It it does we could consider having special ktrace records just
  // for this, but that's a last resort kind of thing.
  if (RequestKtraceStart(ktrace, kKtraceGroupMask)) {
    return true;
  }

  // TODO(dje): Resume original ktracing? Need ability to get old value.
  RequestKtraceStop(ktrace);
  return false;
}

bool StartTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "StartTrace called";
  FX_DCHECK(config.mode == Mode::CPU);

  ControllerSyncPtr ipt{OpenDevice()};
  if (!ipt) {
    return false;
  }

  zx_status_t status = ipt->Start();
  if (status != ZX_OK) {
    LogFidlFailure("Start", status);
    return false;
  }

  return true;
}

void StopTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "StopTrace called";
  FX_DCHECK(config.mode == Mode::CPU);

  ControllerSyncPtr ipt{OpenDevice()};
  if (!ipt) {
    return;
  }

  [[maybe_unused]] zx_status_t status = ipt->Stop();
  FX_DCHECK(status == ZX_OK);
}

void StopSidebandDataCollection(const IptConfig& config) {
  FX_LOGS(INFO) << "StopSidebandDataCollection called";

  fuchsia::tracing::kernel::ControllerSyncPtr ktrace;
  if (OpenKtraceControllerChannel(&ktrace) != ZX_OK) {
    return;
  }

  // Avoid having the records we need overrun by the time we collect them by
  // stopping ktrace here. It will get turned back on by "reset".
  RequestKtraceStop(ktrace);
}

static std::string GetCpuPtFileName(const std::string& output_path_prefix, uint64_t id) {
  const char* name_prefix = "cpu";
  return fxl::StringPrintf("%s.%s%" PRIu64 ".%s", output_path_prefix.c_str(), name_prefix, id,
                           buffer_output_path_suffix);
}

static std::string GetThreadPtFileName(const std::string& output_path_prefix, uint64_t id) {
  const char* name_prefix = "thr";
  return fxl::StringPrintf("%s.%s%" PRIu64 ".%s", output_path_prefix.c_str(), name_prefix, id,
                           buffer_output_path_suffix);
}

// Write the contents of buffer |descriptor| to a file.
// The file's name is $output_path_prefix.$name_prefix$id.pt.

static zx_status_t WriteBufferData(const IptConfig& config, const ControllerSyncPtr& ipt,
                                   uint32_t descriptor, uint64_t id) {
  std::string output_path;
  if (config.mode == Mode::CPU)
    output_path = GetCpuPtFileName(config.output_path_prefix, id);
  else
    output_path = GetThreadPtFileName(config.output_path_prefix, id);
  const char* c_path = output_path.c_str();

  // Refetch the buffer config as we can be invoked in a separate process,
  // after tracing has started, and shouldn't rely on what the user thinks
  // the config is.
  std::unique_ptr<BufferConfig> buffer_config;
  zx_status_t status = ipt->GetBufferConfig(descriptor, &buffer_config);
  if (status != ZX_OK) {
    LogFidlFailure("GetBufferConfig", status);
    return status;
  }
  if (!buffer_config) {
    FX_LOGS(ERROR) << "Failed getting buffer config";
    return ZX_ERR_INTERNAL;
  }

  std::unique_ptr<BufferState> buffer_state;
  status = ipt->GetBufferState(descriptor, &buffer_state);
  if (status != ZX_OK) {
    LogFidlFailure("GetBufferState", status);
    return status;
  }
  if (!buffer_state) {
    FX_LOGS(ERROR) << "Failed getting buffer state";
    return ZX_ERR_INTERNAL;
  }

  fbl::unique_fd fd(open(c_path, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR));
  if (!fd.is_valid()) {
    FX_LOGS(ERROR) << fxl::StringPrintf("Failed writing file: %s", c_path) << ", "
                   << debugger_utils::ErrnoString(errno);
    return ZX_ERR_BAD_PATH;
  }

  // TODO(dje): Fetch from vmo?
  size_t chunk_size = (1 << buffer_config->chunk_order) * PAGE_SIZE;
  uint32_t num_chunks = buffer_config->num_chunks;

  // If using a circular buffer there's (currently) no way to know if
  // tracing wrapped, so for now we just punt and always dump the entire
  // buffer. It's highly likely it wrapped anyway.
  size_t bytes_left;
  if (buffer_config->is_circular)
    bytes_left = num_chunks * chunk_size;
  else
    bytes_left = buffer_state->capture_end;

  FX_LOGS(INFO) << fxl::StringPrintf("Writing %zu bytes to %s", bytes_left, c_path);

  char buf[4096];

  for (uint32_t i = 0; i < num_chunks && bytes_left > 0; ++i) {
    zx::vmo vmo;
    status = ipt->GetChunkHandle(descriptor, i, &vmo);
    if (status != ZX_OK) {
      LogFidlFailure("GetChunkHandle", status);
      FX_LOGS(ERROR) << "Buffer " << descriptor << ", chunk " << i;
      goto Fail;
    }

    size_t buffer_remaining = chunk_size;
    size_t offset = 0;
    while (buffer_remaining && bytes_left) {
      size_t to_write = sizeof(buf);
      if (to_write > buffer_remaining)
        to_write = buffer_remaining;
      if (to_write > bytes_left)
        to_write = bytes_left;
      // TODO(dje): Mapping into process and reading directly from that
      // left for another day.
      status = vmo.read(buf, offset, to_write);
      if (status != ZX_OK) {
        FX_LOGS(ERROR) << fxl::StringPrintf("zx_vmo_read: buffer %u, buffer %u, offset %zu: ",
                                            descriptor, i, offset)
                       << debugger_utils::ZxErrorString(status);
        goto Fail;
      }
      if (write(fd.get(), buf, to_write) != (ssize_t)to_write) {
        FX_LOGS(ERROR) << fxl::StringPrintf("Short write, file: %s\n", c_path);
        status = ZX_ERR_IO;
        goto Fail;
      }
      offset += to_write;
      buffer_remaining -= to_write;
      bytes_left -= to_write;
    }
  }

  assert(bytes_left == 0);
  status = ZX_OK;
  // fallthrough

Fail:
  // We don't delete the file on failure on purpose, it is kept for
  // debugging purposes.
  return status;
}

// Write all output files.
// This assumes tracing has already been stopped.

void DumpTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "DumpTrace called";
  FX_DCHECK(config.mode == Mode::CPU);

  ControllerSyncPtr ipt{OpenDevice()};
  if (!ipt) {
    return;
  }

  for (uint32_t cpu = 0; cpu < config.num_cpus; ++cpu) {
    // Buffer descriptors for cpus is the cpu number.
    auto status = WriteBufferData(config, ipt, cpu, cpu);
    if (status != ZX_OK) {
      FX_LOGS(ERROR) << fxl::StringPrintf("Dump perf of cpu %u: ", cpu)
                     << debugger_utils::ZxErrorString(status);
      // Keep trying to dump other cpu's data.
    }
  }
}

void DumpSidebandData(const IptConfig& config) {
  FX_LOGS(INFO) << "DumpSidebandData called";

  DumpKtraceBuffer(config.output_path_prefix.c_str(), ktrace_output_path_suffix);

  // TODO(dje): UniqueFILE?
  {
    std::string cpuid_output_path =
        fxl::StringPrintf("%s.%s", config.output_path_prefix.c_str(), cpuid_output_path_suffix);
    const char* cpuid_c_path = cpuid_output_path.c_str();

    FILE* f = fopen(cpuid_c_path, "w");
    if (f != nullptr) {
      debugger_utils::x86_feature_debug(f);
      // Also put the mtc_freq value in the cpuid file, it's as good a place
      // for it as any. See intel-pt.h:pt_config.
      // Alternatively this could be added to the ktrace record.
      // TODO(dje): Put constants in zircon/device/intel-pt.h.
      unsigned mtc_freq = config.mtc_freq;
      fprintf(f, "mtc_freq: %u\n", mtc_freq);
      // TODO(dje): verify writes succeed
      fclose(f);
    } else {
      FX_LOGS(ERROR) << "unable to write PT config to " << cpuid_c_path;
    }
  }

  // TODO(dje): UniqueFILE?
  // TODO(dje): Handle Mode::THREAD
  if (config.mode == Mode::CPU) {
    std::string pt_list_output_path =
        fxl::StringPrintf("%s.%s", config.output_path_prefix.c_str(), pt_list_output_path_suffix);
    const char* pt_list_c_path = pt_list_output_path.c_str();

    FILE* f = fopen(pt_list_c_path, "w");
    if (f != nullptr) {
      for (uint32_t cpu = 0; cpu < config.num_cpus; ++cpu) {
        std::string pt_file = GetCpuPtFileName(config.output_path_prefix, cpu);
        fprintf(f, "%u %s\n", cpu, pt_file.c_str());
      }
      // TODO(dje): verify writes succeed
      fclose(f);
    } else {
      FX_LOGS(ERROR) << "unable to write PT list to " << pt_list_c_path;
    }
  }
}

void ResetTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "ResetTrace called";
  FX_DCHECK(config.mode == Mode::CPU);

  // TODO(dje): Nothing to do currently. There use to be. So keep this
  // function around for a bit.
}

// Free all resources associated with the true.
// This means restoring ktrace to its original state.
// This assumes tracing has already been stopped.

void FreeTrace(const IptConfig& config) {
  FX_LOGS(INFO) << "FreeTrace called";

  ControllerSyncPtr ipt{OpenDevice()};
  if (!ipt) {
    return;
  }

  ::fuchsia::hardware::cpu::insntrace::Controller_Terminate_Result result;
  zx_status_t status = ipt->Terminate(&result);
  if (status != ZX_OK || result.is_err()) {
    LogFidlFailure("Terminate", status, result.err());
  }

  // TODO(dje): Resume original ktracing? Need ability to get old value.
  // For now set the values to what we need: A later run might still need
  // the boot time records.

  fuchsia::tracing::kernel::ControllerSyncPtr ktrace;
  if (OpenKtraceControllerChannel(&ktrace) != ZX_OK) {
    return;
  }

  RequestKtraceStop(ktrace);
#if 0  // TODO(dje): See rewind comments in InitProcessTrace.
  RequestKtraceRewind(ktrace);
#endif
  RequestKtraceStart(ktrace, kKtraceGroupMask);
}

}  // namespace insntrace
