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