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 TraceIntelPTStartRequest::IsPerCoreTracing() const { 20 return per_core_tracing.getValueOr(false); 21 } 22 23 bool fromJSON(const json::Value &value, TraceIntelPTStartRequest &packet, 24 Path path) { 25 ObjectMapper o(value, path); 26 if (!o || !fromJSON(value, (TraceStartRequest &)packet, path) || 27 !o.map("enableTsc", packet.enable_tsc) || 28 !o.map("psbPeriod", packet.psb_period) || 29 !o.map("traceBufferSize", packet.trace_buffer_size)) 30 return false; 31 32 if (packet.IsProcessTracing()) { 33 if (!o.map("processBufferSizeLimit", packet.process_buffer_size_limit) || 34 !o.map("perCoreTracing", packet.per_core_tracing)) 35 return false; 36 } 37 return true; 38 } 39 40 json::Value toJSON(const TraceIntelPTStartRequest &packet) { 41 json::Value base = toJSON((const TraceStartRequest &)packet); 42 json::Object &obj = *base.getAsObject(); 43 obj.try_emplace("traceBufferSize", packet.trace_buffer_size); 44 obj.try_emplace("processBufferSizeLimit", packet.process_buffer_size_limit); 45 obj.try_emplace("psbPeriod", packet.psb_period); 46 obj.try_emplace("enableTsc", packet.enable_tsc); 47 obj.try_emplace("perCoreTracing", packet.per_core_tracing); 48 return base; 49 } 50 51 std::chrono::nanoseconds 52 LinuxPerfZeroTscConversion::Convert(uint64_t raw_counter_value) { 53 uint64_t quot = raw_counter_value >> m_time_shift; 54 uint64_t rem_flag = (((uint64_t)1 << m_time_shift) - 1); 55 uint64_t rem = raw_counter_value & rem_flag; 56 return std::chrono::nanoseconds{m_time_zero + quot * m_time_mult + 57 ((rem * m_time_mult) >> m_time_shift)}; 58 } 59 60 json::Value LinuxPerfZeroTscConversion::toJSON() { 61 return json::Value(json::Object{ 62 {"kind", "tsc-perf-zero-conversion"}, 63 {"time_mult", m_time_mult}, 64 {"time_shift", m_time_shift}, 65 {"time_zero", m_time_zero}, 66 }); 67 } 68 69 bool fromJSON(const json::Value &value, TraceTscConversionUP &tsc_conversion, 70 json::Path path) { 71 ObjectMapper o(value, path); 72 73 uint64_t time_mult, time_shift, time_zero; 74 if (!o || !o.map("time_mult", time_mult) || 75 !o.map("time_shift", time_shift) || !o.map("time_zero", time_zero)) 76 return false; 77 78 tsc_conversion = std::make_unique<LinuxPerfZeroTscConversion>( 79 static_cast<uint32_t>(time_mult), static_cast<uint16_t>(time_shift), 80 time_zero); 81 82 return true; 83 } 84 85 bool fromJSON(const json::Value &value, TraceIntelPTGetStateResponse &packet, 86 json::Path path) { 87 ObjectMapper o(value, path); 88 if (!o || !fromJSON(value, (TraceGetStateResponse &)packet, path)) 89 return false; 90 91 const Object &obj = *(value.getAsObject()); 92 if (const json::Value *counters = obj.get("counters")) { 93 json::Path subpath = path.field("counters"); 94 ObjectMapper ocounters(*counters, subpath); 95 if (!ocounters || !ocounters.mapOptional("tsc-perf-zero-conversion", 96 packet.tsc_conversion)) 97 return false; 98 } 99 return true; 100 } 101 102 json::Value toJSON(const TraceIntelPTGetStateResponse &packet) { 103 json::Value base = toJSON((const TraceGetStateResponse &)packet); 104 105 if (packet.tsc_conversion) { 106 std::vector<json::Value> counters{}; 107 base.getAsObject()->try_emplace( 108 "counters", json::Object{{"tsc-perf-zero-conversion", 109 packet.tsc_conversion->toJSON()}}); 110 } 111 112 return base; 113 } 114 115 } // namespace lldb_private 116