blob: 0c3439dfb3ef3c94621e75b676637c44819b38fb [file] [log] [blame]
// 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.
#pragma once
#include <cstdint>
#include <string>
#include <lib/zircon-internal/device/cpu-trace/intel-pt.h>
#include <zircon/syscalls.h>
#include "lib/fxl/macros.h"
#include "lib/fxl/strings/string_view.h"
#include "garnet/lib/inferior_control/exception_port.h"
#include "garnet/lib/inferior_control/process.h"
#include "garnet/lib/inferior_control/server.h"
#include "garnet/lib/inferior_control/thread.h"
namespace insntrace {
// The parameters controlling data collection.
struct IptConfig {
enum class AddrFilter { kOff = 0, kEnable = 1, kStop = 2 };
struct AddrRange {
// "" if no ELF
std::string elf;
uint64_t begin, end;
};
static constexpr uint32_t kDefaultMode = IPT_MODE_CPUS;
static constexpr uint32_t kDefaultMaxThreads = 16;
static constexpr size_t kDefaultNumChunks = 16;
static constexpr size_t kDefaultChunkOrder = 2; // 16kb
static constexpr bool kDefaultIsCircular = false;
static constexpr char kDefaultOutputPathPrefix[] = "/tmp/ptout";
IptConfig();
// Return the value to write to the CTL MSR.
uint64_t CtlMsr() const;
// Return values for the addr range MSRs.
uint64_t AddrBegin(unsigned index) const;
uint64_t AddrEnd(unsigned index) const;
// One of IPT_MODE_CPUS, IPT_MODE_THREADS.
uint32_t mode;
// The number of cpus on this system, as reported by
// zx_system_get_num_cpus().
uint32_t num_cpus;
// When tracing threads, the max number of threads we can trace.
uint32_t max_threads;
// Details of the tracing buffer.
size_t num_chunks;
// The size of each chunk, in pages as a power of 2.
size_t chunk_order;
bool is_circular;
// The various fields of IA32_RTIT_CTL MSR, and support MSRs.
AddrFilter addr[2];
AddrRange addr_range[2];
bool branch;
// zero if disabled
uint64_t cr3_match;
// True if cr3_match was specified on the command line.
bool cr3_match_set;
bool cyc;
uint32_t cyc_thresh;
bool mtc;
uint32_t mtc_freq;
uint32_t psb_freq;
bool os, user;
bool retc;
bool tsc;
// The path prefix of all of the output files.
std::string output_path_prefix;
};
// IptServer implements the main loop, which basically just waits until
// the inferior exits. The exception port thread does all the heavy lifting
// when tracing threads.
//
// NOTE: This class is generally not thread safe. Care must be taken when
// calling methods which modify the internal state of a IptServer instance.
class IptServer final : public inferior_control::Server {
public:
IptServer(const IptConfig& config);
bool Run() override;
private:
bool StartInferior();
bool DumpResults();
// Process::Delegate overrides.
void OnThreadStarting(inferior_control::Process* process,
inferior_control::Thread* thread,
const zx_exception_context_t& context) override;
void OnThreadExiting(inferior_control::Process* process,
inferior_control::Thread* thread,
const zx_exception_context_t& context) override;
void OnProcessExit(inferior_control::Process* process) override;
void OnArchitecturalException(inferior_control::Process* process,
inferior_control::Thread* thread,
const zx_excp_type_t type,
const zx_exception_context_t& context) override;
void OnSyntheticException(inferior_control::Process* process,
inferior_control::Thread* thread,
zx_excp_type_t type,
const zx_exception_context_t& context) override;
IptConfig config_;
FXL_DISALLOW_COPY_AND_ASSIGN(IptServer);
};
} // namespace insntrace