1fe6060f1SDimitry Andric //===-- TraceIntelPTGDBRemotePackets.cpp ------------------------*- C++ -*-===//
2fe6060f1SDimitry Andric //
3fe6060f1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fe6060f1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5fe6060f1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fe6060f1SDimitry Andric //
7fe6060f1SDimitry Andric //===----------------------------------------------------------------------===//
8fe6060f1SDimitry Andric
9fe6060f1SDimitry Andric #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
10fe6060f1SDimitry Andric
11fe6060f1SDimitry Andric using namespace llvm;
12fe6060f1SDimitry Andric using namespace llvm::json;
13fe6060f1SDimitry Andric
14fe6060f1SDimitry Andric namespace lldb_private {
15fe6060f1SDimitry Andric
1681ad6265SDimitry Andric const char *IntelPTDataKinds::kProcFsCpuInfo = "procfsCpuInfo";
1781ad6265SDimitry Andric const char *IntelPTDataKinds::kIptTrace = "iptTrace";
1881ad6265SDimitry Andric const char *IntelPTDataKinds::kPerfContextSwitchTrace =
1981ad6265SDimitry Andric "perfContextSwitchTrace";
2081ad6265SDimitry Andric
IsPerCpuTracing() const2181ad6265SDimitry Andric bool TraceIntelPTStartRequest::IsPerCpuTracing() const {
2281ad6265SDimitry Andric return per_cpu_tracing.value_or(false);
2381ad6265SDimitry Andric }
2481ad6265SDimitry Andric
toJSON(const JSONUINT64 & uint64,bool hex)2581ad6265SDimitry Andric json::Value toJSON(const JSONUINT64 &uint64, bool hex) {
2681ad6265SDimitry Andric if (hex)
2781ad6265SDimitry Andric return json::Value(formatv("{0:x+}", uint64.value));
2881ad6265SDimitry Andric else
2981ad6265SDimitry Andric return json::Value(formatv("{0}", uint64.value));
3081ad6265SDimitry Andric }
3181ad6265SDimitry Andric
fromJSON(const json::Value & value,JSONUINT64 & uint64,Path path)3281ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONUINT64 &uint64, Path path) {
33*bdd1243dSDimitry Andric if (std::optional<uint64_t> val = value.getAsUINT64()) {
3481ad6265SDimitry Andric uint64.value = *val;
3581ad6265SDimitry Andric return true;
36*bdd1243dSDimitry Andric } else if (std::optional<StringRef> val = value.getAsString()) {
3781ad6265SDimitry Andric if (!val->getAsInteger(/*radix=*/0, uint64.value))
3881ad6265SDimitry Andric return true;
3981ad6265SDimitry Andric path.report("invalid string number");
4081ad6265SDimitry Andric }
4181ad6265SDimitry Andric path.report("invalid number or string number");
4281ad6265SDimitry Andric return false;
4381ad6265SDimitry Andric }
4481ad6265SDimitry Andric
fromJSON(const json::Value & value,TraceIntelPTStartRequest & packet,Path path)45fe6060f1SDimitry Andric bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet,
46fe6060f1SDimitry Andric Path path) {
47fe6060f1SDimitry Andric ObjectMapper o(value, path);
4881ad6265SDimitry Andric if (!(o && fromJSON(value, (TraceStartRequest &)packet, path) &&
4981ad6265SDimitry Andric o.map("enableTsc", packet.enable_tsc) &&
5081ad6265SDimitry Andric o.map("psbPeriod", packet.psb_period) &&
5181ad6265SDimitry Andric o.map("iptTraceSize", packet.ipt_trace_size)))
52fe6060f1SDimitry Andric return false;
5381ad6265SDimitry Andric
5481ad6265SDimitry Andric if (packet.IsProcessTracing()) {
5581ad6265SDimitry Andric if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) ||
56753f127fSDimitry Andric !o.map("perCpuTracing", packet.per_cpu_tracing) ||
57753f127fSDimitry Andric !o.map("disableCgroupTracing", packet.disable_cgroup_filtering))
58fe6060f1SDimitry Andric return false;
59fe6060f1SDimitry Andric }
60fe6060f1SDimitry Andric return true;
61fe6060f1SDimitry Andric }
62fe6060f1SDimitry Andric
toJSON(const TraceIntelPTStartRequest & packet)63fe6060f1SDimitry Andric json::Value toJSON(const TraceIntelPTStartRequest &packet) {
64fe6060f1SDimitry Andric json::Value base = toJSON((const TraceStartRequest &)packet);
6581ad6265SDimitry Andric json::Object &obj = *base.getAsObject();
6681ad6265SDimitry Andric obj.try_emplace("iptTraceSize", packet.ipt_trace_size);
6781ad6265SDimitry Andric obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit);
6881ad6265SDimitry Andric obj.try_emplace("psbPeriod", packet.psb_period);
6981ad6265SDimitry Andric obj.try_emplace("enableTsc", packet.enable_tsc);
7081ad6265SDimitry Andric obj.try_emplace("perCpuTracing", packet.per_cpu_tracing);
71753f127fSDimitry Andric obj.try_emplace("disableCgroupTracing", packet.disable_cgroup_filtering);
7281ad6265SDimitry Andric return base;
7381ad6265SDimitry Andric }
7481ad6265SDimitry Andric
ToNanos(uint64_t tsc) const7581ad6265SDimitry Andric uint64_t LinuxPerfZeroTscConversion::ToNanos(uint64_t tsc) const {
7681ad6265SDimitry Andric uint64_t quot = tsc >> time_shift;
7781ad6265SDimitry Andric uint64_t rem_flag = (((uint64_t)1 << time_shift) - 1);
7881ad6265SDimitry Andric uint64_t rem = tsc & rem_flag;
7981ad6265SDimitry Andric return time_zero.value + quot * time_mult + ((rem * time_mult) >> time_shift);
8081ad6265SDimitry Andric }
8181ad6265SDimitry Andric
ToTSC(uint64_t nanos) const8281ad6265SDimitry Andric uint64_t LinuxPerfZeroTscConversion::ToTSC(uint64_t nanos) const {
8381ad6265SDimitry Andric uint64_t time = nanos - time_zero.value;
8481ad6265SDimitry Andric uint64_t quot = time / time_mult;
8581ad6265SDimitry Andric uint64_t rem = time % time_mult;
8681ad6265SDimitry Andric return (quot << time_shift) + (rem << time_shift) / time_mult;
8781ad6265SDimitry Andric }
8881ad6265SDimitry Andric
toJSON(const LinuxPerfZeroTscConversion & packet)8981ad6265SDimitry Andric json::Value toJSON(const LinuxPerfZeroTscConversion &packet) {
9081ad6265SDimitry Andric return json::Value(json::Object{
9181ad6265SDimitry Andric {"timeMult", packet.time_mult},
9281ad6265SDimitry Andric {"timeShift", packet.time_shift},
9381ad6265SDimitry Andric {"timeZero", toJSON(packet.time_zero, /*hex=*/false)},
9481ad6265SDimitry Andric });
9581ad6265SDimitry Andric }
9681ad6265SDimitry Andric
fromJSON(const json::Value & value,LinuxPerfZeroTscConversion & packet,json::Path path)9781ad6265SDimitry Andric bool fromJSON(const json::Value &value, LinuxPerfZeroTscConversion &packet,
9881ad6265SDimitry Andric json::Path path) {
9981ad6265SDimitry Andric ObjectMapper o(value, path);
10081ad6265SDimitry Andric uint64_t time_mult, time_shift;
10181ad6265SDimitry Andric if (!(o && o.map("timeMult", time_mult) && o.map("timeShift", time_shift) &&
10281ad6265SDimitry Andric o.map("timeZero", packet.time_zero)))
10381ad6265SDimitry Andric return false;
10481ad6265SDimitry Andric packet.time_mult = time_mult;
10581ad6265SDimitry Andric packet.time_shift = time_shift;
10681ad6265SDimitry Andric return true;
10781ad6265SDimitry Andric }
10881ad6265SDimitry Andric
fromJSON(const json::Value & value,TraceIntelPTGetStateResponse & packet,json::Path path)10981ad6265SDimitry Andric bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet,
11081ad6265SDimitry Andric json::Path path) {
11181ad6265SDimitry Andric ObjectMapper o(value, path);
11281ad6265SDimitry Andric return o && fromJSON(value, (TraceGetStateResponse &)packet, path) &&
113753f127fSDimitry Andric o.map("tscPerfZeroConversion", packet.tsc_perf_zero_conversion) &&
114753f127fSDimitry Andric o.map("usingCgroupFiltering", packet.using_cgroup_filtering);
11581ad6265SDimitry Andric }
11681ad6265SDimitry Andric
toJSON(const TraceIntelPTGetStateResponse & packet)11781ad6265SDimitry Andric json::Value toJSON(const TraceIntelPTGetStateResponse &packet) {
11881ad6265SDimitry Andric json::Value base = toJSON((const TraceGetStateResponse &)packet);
119753f127fSDimitry Andric json::Object &obj = *base.getAsObject();
120753f127fSDimitry Andric obj.insert({"tscPerfZeroConversion", packet.tsc_perf_zero_conversion});
121753f127fSDimitry Andric obj.insert({"usingCgroupFiltering", packet.using_cgroup_filtering});
122fe6060f1SDimitry Andric return base;
123fe6060f1SDimitry Andric }
124fe6060f1SDimitry Andric
125fe6060f1SDimitry Andric } // namespace lldb_private
126