xref: /freebsd-src/contrib/llvm-project/lldb/source/Utility/TraceIntelPTGDBRemotePackets.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
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 
16*81ad6265SDimitry Andric const char *IntelPTDataKinds::kProcFsCpuInfo = "procfsCpuInfo";
17*81ad6265SDimitry Andric const char *IntelPTDataKinds::kIptTrace = "iptTrace";
18*81ad6265SDimitry Andric const char *IntelPTDataKinds::kPerfContextSwitchTrace =
19*81ad6265SDimitry Andric     "perfContextSwitchTrace";
20*81ad6265SDimitry Andric 
21*81ad6265SDimitry Andric bool TraceIntelPTStartRequest::IsPerCpuTracing() const {
22*81ad6265SDimitry Andric   return per_cpu_tracing.value_or(false);
23*81ad6265SDimitry Andric }
24*81ad6265SDimitry Andric 
25*81ad6265SDimitry Andric json::Value toJSON(const JSONUINT64 &uint64, bool hex) {
26*81ad6265SDimitry Andric   if (hex)
27*81ad6265SDimitry Andric     return json::Value(formatv("{0:x+}", uint64.value));
28*81ad6265SDimitry Andric   else
29*81ad6265SDimitry Andric     return json::Value(formatv("{0}", uint64.value));
30*81ad6265SDimitry Andric }
31*81ad6265SDimitry Andric 
32*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, JSONUINT64 &uint64, Path path) {
33*81ad6265SDimitry Andric   if (Optional<uint64_t> val = value.getAsUINT64()) {
34*81ad6265SDimitry Andric     uint64.value = *val;
35*81ad6265SDimitry Andric     return true;
36*81ad6265SDimitry Andric   } else if (Optional<StringRef> val = value.getAsString()) {
37*81ad6265SDimitry Andric     if (!val->getAsInteger(/*radix=*/0, uint64.value))
38*81ad6265SDimitry Andric       return true;
39*81ad6265SDimitry Andric     path.report("invalid string number");
40*81ad6265SDimitry Andric   }
41*81ad6265SDimitry Andric   path.report("invalid number or string number");
42*81ad6265SDimitry Andric   return false;
43*81ad6265SDimitry Andric }
44*81ad6265SDimitry Andric 
45fe6060f1SDimitry Andric bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet,
46fe6060f1SDimitry Andric               Path path) {
47fe6060f1SDimitry Andric   ObjectMapper o(value, path);
48*81ad6265SDimitry Andric   if (!(o && fromJSON(value, (TraceStartRequest &)packet, path) &&
49*81ad6265SDimitry Andric         o.map("enableTsc", packet.enable_tsc) &&
50*81ad6265SDimitry Andric         o.map("psbPeriod", packet.psb_period) &&
51*81ad6265SDimitry Andric         o.map("iptTraceSize", packet.ipt_trace_size)))
52fe6060f1SDimitry Andric     return false;
53*81ad6265SDimitry Andric 
54*81ad6265SDimitry Andric   if (packet.IsProcessTracing()) {
55*81ad6265SDimitry Andric     if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) ||
56*81ad6265SDimitry Andric         !o.map("perCpuTracing", packet.per_cpu_tracing))
57fe6060f1SDimitry Andric       return false;
58fe6060f1SDimitry Andric   }
59fe6060f1SDimitry Andric   return true;
60fe6060f1SDimitry Andric }
61fe6060f1SDimitry Andric 
62fe6060f1SDimitry Andric json::Value toJSON(const TraceIntelPTStartRequest &packet) {
63fe6060f1SDimitry Andric   json::Value base = toJSON((const TraceStartRequest &)packet);
64*81ad6265SDimitry Andric   json::Object &obj = *base.getAsObject();
65*81ad6265SDimitry Andric   obj.try_emplace("iptTraceSize", packet.ipt_trace_size);
66*81ad6265SDimitry Andric   obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit);
67*81ad6265SDimitry Andric   obj.try_emplace("psbPeriod", packet.psb_period);
68*81ad6265SDimitry Andric   obj.try_emplace("enableTsc", packet.enable_tsc);
69*81ad6265SDimitry Andric   obj.try_emplace("perCpuTracing", packet.per_cpu_tracing);
70*81ad6265SDimitry Andric   return base;
71*81ad6265SDimitry Andric }
72*81ad6265SDimitry Andric 
73*81ad6265SDimitry Andric uint64_t LinuxPerfZeroTscConversion::ToNanos(uint64_t tsc) const {
74*81ad6265SDimitry Andric   uint64_t quot = tsc >> time_shift;
75*81ad6265SDimitry Andric   uint64_t rem_flag = (((uint64_t)1 << time_shift) - 1);
76*81ad6265SDimitry Andric   uint64_t rem = tsc & rem_flag;
77*81ad6265SDimitry Andric   return time_zero.value + quot * time_mult + ((rem * time_mult) >> time_shift);
78*81ad6265SDimitry Andric }
79*81ad6265SDimitry Andric 
80*81ad6265SDimitry Andric uint64_t LinuxPerfZeroTscConversion::ToTSC(uint64_t nanos) const {
81*81ad6265SDimitry Andric   uint64_t time = nanos - time_zero.value;
82*81ad6265SDimitry Andric   uint64_t quot = time / time_mult;
83*81ad6265SDimitry Andric   uint64_t rem = time % time_mult;
84*81ad6265SDimitry Andric   return (quot << time_shift) + (rem << time_shift) / time_mult;
85*81ad6265SDimitry Andric }
86*81ad6265SDimitry Andric 
87*81ad6265SDimitry Andric json::Value toJSON(const LinuxPerfZeroTscConversion &packet) {
88*81ad6265SDimitry Andric   return json::Value(json::Object{
89*81ad6265SDimitry Andric       {"timeMult", packet.time_mult},
90*81ad6265SDimitry Andric       {"timeShift", packet.time_shift},
91*81ad6265SDimitry Andric       {"timeZero", toJSON(packet.time_zero, /*hex=*/false)},
92*81ad6265SDimitry Andric   });
93*81ad6265SDimitry Andric }
94*81ad6265SDimitry Andric 
95*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, LinuxPerfZeroTscConversion &packet,
96*81ad6265SDimitry Andric               json::Path path) {
97*81ad6265SDimitry Andric   ObjectMapper o(value, path);
98*81ad6265SDimitry Andric   uint64_t time_mult, time_shift;
99*81ad6265SDimitry Andric   if (!(o && o.map("timeMult", time_mult) && o.map("timeShift", time_shift) &&
100*81ad6265SDimitry Andric         o.map("timeZero", packet.time_zero)))
101*81ad6265SDimitry Andric     return false;
102*81ad6265SDimitry Andric   packet.time_mult = time_mult;
103*81ad6265SDimitry Andric   packet.time_shift = time_shift;
104*81ad6265SDimitry Andric   return true;
105*81ad6265SDimitry Andric }
106*81ad6265SDimitry Andric 
107*81ad6265SDimitry Andric bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet,
108*81ad6265SDimitry Andric               json::Path path) {
109*81ad6265SDimitry Andric   ObjectMapper o(value, path);
110*81ad6265SDimitry Andric   return o && fromJSON(value, (TraceGetStateResponse &)packet, path) &&
111*81ad6265SDimitry Andric          o.map("tscPerfZeroConversion", packet.tsc_perf_zero_conversion);
112*81ad6265SDimitry Andric }
113*81ad6265SDimitry Andric 
114*81ad6265SDimitry Andric json::Value toJSON(const TraceIntelPTGetStateResponse &packet) {
115*81ad6265SDimitry Andric   json::Value base = toJSON((const TraceGetStateResponse &)packet);
116*81ad6265SDimitry Andric   base.getAsObject()->insert(
117*81ad6265SDimitry Andric       {"tscPerfZeroConversion", packet.tsc_perf_zero_conversion});
118fe6060f1SDimitry Andric   return base;
119fe6060f1SDimitry Andric }
120fe6060f1SDimitry Andric 
121fe6060f1SDimitry Andric } // namespace lldb_private
122