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