1 //===-- TraceIntelPTGDBRemotePackets.cpp ------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h" 10 11 using namespace llvm; 12 using namespace llvm::json; 13 14 namespace lldb_private { 15 16 const char *IntelPTDataKinds::kProcFsCpuInfo = "procfsCpuInfo"; 17 const char *IntelPTDataKinds::kTraceBuffer = "traceBuffer"; 18 19 bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet, 20 Path path) { 21 ObjectMapper o(value, path); 22 if (!o || !fromJSON(value, (TraceStartRequest &)packet, path) || 23 !o.map("enableTsc", packet.enable_tsc) || 24 !o.map("psbPeriod", packet.psb_period) || 25 !o.map("traceBufferSize", packet.trace_buffer_size)) 26 return false; 27 28 if (packet.IsProcessTracing()) { 29 if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) || 30 !o.map("perCoreTracing", packet.per_core_tracing)) 31 return false; 32 } 33 return true; 34 } 35 36 json::Value toJSON(const TraceIntelPTStartRequest &packet) { 37 json::Value base = toJSON((const TraceStartRequest &)packet); 38 json::Object &obj = *base.getAsObject(); 39 obj.try_emplace("traceBufferSize", packet.trace_buffer_size); 40 obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit); 41 obj.try_emplace("psbPeriod", packet.psb_period); 42 obj.try_emplace("enableTsc", packet.enable_tsc); 43 obj.try_emplace("perCoreTracing", packet.per_core_tracing); 44 return base; 45 } 46 47 std::chrono::nanoseconds 48 LinuxPerfZeroTscConversion::Convert(uint64_t raw_counter_value) { 49 uint64_t quot = raw_counter_value >> m_time_shift; 50 uint64_t rem_flag = (((uint64_t)1 << m_time_shift) - 1); 51 uint64_t rem = raw_counter_value & rem_flag; 52 return std::chrono::nanoseconds{m_time_zero + quot * m_time_mult + 53 ((rem * m_time_mult) >> m_time_shift)}; 54 } 55 56 json::Value LinuxPerfZeroTscConversion::toJSON() { 57 return json::Value(json::Object{ 58 {"kind", "tsc-perf-zero-conversion"}, 59 {"time_mult", static_cast<int64_t>(m_time_mult)}, 60 {"time_shift", static_cast<int64_t>(m_time_shift)}, 61 {"time_zero", static_cast<int64_t>(m_time_zero)}, 62 }); 63 } 64 65 bool fromJSON(const json::Value &value, TraceTscConversionUP &tsc_conversion, 66 json::Path path) { 67 ObjectMapper o(value, path); 68 69 int64_t time_mult, time_shift, time_zero; 70 if (!o || !o.map("time_mult", time_mult) || 71 !o.map("time_shift", time_shift) || !o.map("time_zero", time_zero)) 72 return false; 73 74 tsc_conversion = std::make_unique<LinuxPerfZeroTscConversion>( 75 static_cast<uint32_t>(time_mult), static_cast<uint16_t>(time_shift), 76 static_cast<uint64_t>(time_zero)); 77 78 return true; 79 } 80 81 bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet, 82 json::Path path) { 83 ObjectMapper o(value, path); 84 if (!o || !fromJSON(value, (TraceGetStateResponse &)packet, path)) 85 return false; 86 87 const Object &obj = *(value.getAsObject()); 88 if (const json::Value *counters = obj.get("counters")) { 89 json::Path subpath = path.field("counters"); 90 ObjectMapper ocounters(*counters, subpath); 91 if (!ocounters || !ocounters.mapOptional("tsc-perf-zero-conversion", 92 packet.tsc_conversion)) 93 return false; 94 } 95 return true; 96 } 97 98 json::Value toJSON(const TraceIntelPTGetStateResponse &packet) { 99 json::Value base = toJSON((const TraceGetStateResponse &)packet); 100 101 if (packet.tsc_conversion) { 102 std::vector<json::Value> counters{}; 103 base.getAsObject()->try_emplace( 104 "counters", json::Object{{"tsc-perf-zero-conversion", 105 packet.tsc_conversion->toJSON()}}); 106 } 107 108 return base; 109 } 110 111 } // namespace lldb_private 112