17b73de9eSWalter Erquinigo //===-- IntelPTSingleBufferTrace.cpp --------------------------------------===//
27b73de9eSWalter Erquinigo //
37b73de9eSWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47b73de9eSWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
57b73de9eSWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67b73de9eSWalter Erquinigo //
77b73de9eSWalter Erquinigo //===----------------------------------------------------------------------===//
87b73de9eSWalter Erquinigo
97b73de9eSWalter Erquinigo #include "IntelPTSingleBufferTrace.h"
107b73de9eSWalter Erquinigo
117b73de9eSWalter Erquinigo #include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
127b73de9eSWalter Erquinigo #include "lldb/Utility/Status.h"
137b73de9eSWalter Erquinigo #include "lldb/Utility/StreamString.h"
147b73de9eSWalter Erquinigo
157b73de9eSWalter Erquinigo #include "llvm/Support/Host.h"
167b73de9eSWalter Erquinigo #include "llvm/Support/MemoryBuffer.h"
177b73de9eSWalter Erquinigo
187b73de9eSWalter Erquinigo #include <sstream>
197b73de9eSWalter Erquinigo
207b73de9eSWalter Erquinigo #include <linux/perf_event.h>
217b73de9eSWalter Erquinigo #include <sys/syscall.h>
227b73de9eSWalter Erquinigo #include <unistd.h>
237b73de9eSWalter Erquinigo
247b73de9eSWalter Erquinigo using namespace lldb;
257b73de9eSWalter Erquinigo using namespace lldb_private;
267b73de9eSWalter Erquinigo using namespace process_linux;
277b73de9eSWalter Erquinigo using namespace llvm;
287b73de9eSWalter Erquinigo
297b73de9eSWalter Erquinigo const char *kOSEventIntelPTTypeFile =
307b73de9eSWalter Erquinigo "/sys/bus/event_source/devices/intel_pt/type";
317b73de9eSWalter Erquinigo
327b73de9eSWalter Erquinigo const char *kPSBPeriodCapFile =
337b73de9eSWalter Erquinigo "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc";
347b73de9eSWalter Erquinigo
357b73de9eSWalter Erquinigo const char *kPSBPeriodValidValuesFile =
367b73de9eSWalter Erquinigo "/sys/bus/event_source/devices/intel_pt/caps/psb_periods";
377b73de9eSWalter Erquinigo
387b73de9eSWalter Erquinigo const char *kPSBPeriodBitOffsetFile =
397b73de9eSWalter Erquinigo "/sys/bus/event_source/devices/intel_pt/format/psb_period";
407b73de9eSWalter Erquinigo
417b73de9eSWalter Erquinigo const char *kTSCBitOffsetFile =
427b73de9eSWalter Erquinigo "/sys/bus/event_source/devices/intel_pt/format/tsc";
437b73de9eSWalter Erquinigo
447b73de9eSWalter Erquinigo enum IntelPTConfigFileType {
457b73de9eSWalter Erquinigo Hex = 0,
467b73de9eSWalter Erquinigo // 0 or 1
477b73de9eSWalter Erquinigo ZeroOne,
487b73de9eSWalter Erquinigo Decimal,
497b73de9eSWalter Erquinigo // a bit index file always starts with the prefix config: following by an int,
507b73de9eSWalter Erquinigo // which represents the offset of the perf_event_attr.config value where to
517b73de9eSWalter Erquinigo // store a given configuration.
527b73de9eSWalter Erquinigo BitOffset
537b73de9eSWalter Erquinigo };
547b73de9eSWalter Erquinigo
ReadIntelPTConfigFile(const char * file,IntelPTConfigFileType type)557b73de9eSWalter Erquinigo static Expected<uint32_t> ReadIntelPTConfigFile(const char *file,
567b73de9eSWalter Erquinigo IntelPTConfigFileType type) {
577b73de9eSWalter Erquinigo ErrorOr<std::unique_ptr<MemoryBuffer>> stream =
587b73de9eSWalter Erquinigo MemoryBuffer::getFileAsStream(file);
597b73de9eSWalter Erquinigo
607b73de9eSWalter Erquinigo if (!stream)
617b73de9eSWalter Erquinigo return createStringError(inconvertibleErrorCode(),
627b73de9eSWalter Erquinigo "Can't open the file '%s'", file);
637b73de9eSWalter Erquinigo
647b73de9eSWalter Erquinigo uint32_t value = 0;
657b73de9eSWalter Erquinigo StringRef text_buffer = stream.get()->getBuffer();
667b73de9eSWalter Erquinigo
677b73de9eSWalter Erquinigo if (type == BitOffset) {
687b73de9eSWalter Erquinigo const char *prefix = "config:";
697b73de9eSWalter Erquinigo if (!text_buffer.startswith(prefix))
707b73de9eSWalter Erquinigo return createStringError(inconvertibleErrorCode(),
717b73de9eSWalter Erquinigo "The file '%s' contents doesn't start with '%s'",
727b73de9eSWalter Erquinigo file, prefix);
737b73de9eSWalter Erquinigo text_buffer = text_buffer.substr(strlen(prefix));
747b73de9eSWalter Erquinigo }
757b73de9eSWalter Erquinigo
767b73de9eSWalter Erquinigo auto getRadix = [&]() {
777b73de9eSWalter Erquinigo switch (type) {
787b73de9eSWalter Erquinigo case Hex:
797b73de9eSWalter Erquinigo return 16;
807b73de9eSWalter Erquinigo case ZeroOne:
817b73de9eSWalter Erquinigo case Decimal:
827b73de9eSWalter Erquinigo case BitOffset:
837b73de9eSWalter Erquinigo return 10;
847b73de9eSWalter Erquinigo }
857b73de9eSWalter Erquinigo llvm_unreachable("Fully covered switch above!");
867b73de9eSWalter Erquinigo };
877b73de9eSWalter Erquinigo
887b73de9eSWalter Erquinigo auto createError = [&](const char *expected_value_message) {
897b73de9eSWalter Erquinigo return createStringError(
907b73de9eSWalter Erquinigo inconvertibleErrorCode(),
917b73de9eSWalter Erquinigo "The file '%s' has an invalid value. It should be %s.", file,
927b73de9eSWalter Erquinigo expected_value_message);
937b73de9eSWalter Erquinigo };
947b73de9eSWalter Erquinigo
957b73de9eSWalter Erquinigo if (text_buffer.trim().consumeInteger(getRadix(), value) ||
967b73de9eSWalter Erquinigo (type == ZeroOne && value != 0 && value != 1)) {
977b73de9eSWalter Erquinigo switch (type) {
987b73de9eSWalter Erquinigo case Hex:
997b73de9eSWalter Erquinigo return createError("an unsigned hexadecimal int");
1007b73de9eSWalter Erquinigo case ZeroOne:
1017b73de9eSWalter Erquinigo return createError("0 or 1");
1027b73de9eSWalter Erquinigo case Decimal:
1037b73de9eSWalter Erquinigo case BitOffset:
1047b73de9eSWalter Erquinigo return createError("an unsigned decimal int");
1057b73de9eSWalter Erquinigo }
1067b73de9eSWalter Erquinigo }
1077b73de9eSWalter Erquinigo return value;
1087b73de9eSWalter Erquinigo }
1097b73de9eSWalter Erquinigo
1107b73de9eSWalter Erquinigo /// Return the Linux perf event type for Intel PT.
GetIntelPTOSEventType()1117b73de9eSWalter Erquinigo Expected<uint32_t> process_linux::GetIntelPTOSEventType() {
1127b73de9eSWalter Erquinigo return ReadIntelPTConfigFile(kOSEventIntelPTTypeFile,
1137b73de9eSWalter Erquinigo IntelPTConfigFileType::Decimal);
1147b73de9eSWalter Erquinigo }
1157b73de9eSWalter Erquinigo
CheckPsbPeriod(size_t psb_period)1167b73de9eSWalter Erquinigo static Error CheckPsbPeriod(size_t psb_period) {
1177b73de9eSWalter Erquinigo Expected<uint32_t> cap =
1187b73de9eSWalter Erquinigo ReadIntelPTConfigFile(kPSBPeriodCapFile, IntelPTConfigFileType::ZeroOne);
1197b73de9eSWalter Erquinigo if (!cap)
1207b73de9eSWalter Erquinigo return cap.takeError();
1217b73de9eSWalter Erquinigo if (*cap == 0)
1227b73de9eSWalter Erquinigo return createStringError(inconvertibleErrorCode(),
1237b73de9eSWalter Erquinigo "psb_period is unsupported in the system.");
1247b73de9eSWalter Erquinigo
1257b73de9eSWalter Erquinigo Expected<uint32_t> valid_values = ReadIntelPTConfigFile(
1267b73de9eSWalter Erquinigo kPSBPeriodValidValuesFile, IntelPTConfigFileType::Hex);
1277b73de9eSWalter Erquinigo if (!valid_values)
1287b73de9eSWalter Erquinigo return valid_values.takeError();
1297b73de9eSWalter Erquinigo
1307b73de9eSWalter Erquinigo if (valid_values.get() & (1 << psb_period))
1317b73de9eSWalter Erquinigo return Error::success();
1327b73de9eSWalter Erquinigo
1337b73de9eSWalter Erquinigo std::ostringstream error;
1347b73de9eSWalter Erquinigo // 0 is always a valid value
1357b73de9eSWalter Erquinigo error << "Invalid psb_period. Valid values are: 0";
1367b73de9eSWalter Erquinigo uint32_t mask = valid_values.get();
1377b73de9eSWalter Erquinigo while (mask) {
1387b73de9eSWalter Erquinigo int index = __builtin_ctz(mask);
1397b73de9eSWalter Erquinigo if (index > 0)
1407b73de9eSWalter Erquinigo error << ", " << index;
1417b73de9eSWalter Erquinigo // clear the lowest bit
1427b73de9eSWalter Erquinigo mask &= mask - 1;
1437b73de9eSWalter Erquinigo }
1447b73de9eSWalter Erquinigo error << ".";
1457b73de9eSWalter Erquinigo return createStringError(inconvertibleErrorCode(), error.str().c_str());
1467b73de9eSWalter Erquinigo }
1477b73de9eSWalter Erquinigo
148909a2e3cSWalter Erquinigo #ifdef PERF_ATTR_SIZE_VER5
1497b73de9eSWalter Erquinigo static Expected<uint64_t>
GeneratePerfEventConfigValue(bool enable_tsc,Optional<uint64_t> psb_period)150b6bb9e7dSWalter Erquinigo GeneratePerfEventConfigValue(bool enable_tsc, Optional<uint64_t> psb_period) {
1517b73de9eSWalter Erquinigo uint64_t config = 0;
1527b73de9eSWalter Erquinigo // tsc is always supported
1537b73de9eSWalter Erquinigo if (enable_tsc) {
1547b73de9eSWalter Erquinigo if (Expected<uint32_t> offset = ReadIntelPTConfigFile(
1557b73de9eSWalter Erquinigo kTSCBitOffsetFile, IntelPTConfigFileType::BitOffset))
1567b73de9eSWalter Erquinigo config |= 1 << *offset;
1577b73de9eSWalter Erquinigo else
1587b73de9eSWalter Erquinigo return offset.takeError();
1597b73de9eSWalter Erquinigo }
1607b73de9eSWalter Erquinigo if (psb_period) {
1617b73de9eSWalter Erquinigo if (Error error = CheckPsbPeriod(*psb_period))
1627b73de9eSWalter Erquinigo return std::move(error);
1637b73de9eSWalter Erquinigo
1647b73de9eSWalter Erquinigo if (Expected<uint32_t> offset = ReadIntelPTConfigFile(
1657b73de9eSWalter Erquinigo kPSBPeriodBitOffsetFile, IntelPTConfigFileType::BitOffset))
1667b73de9eSWalter Erquinigo config |= *psb_period << *offset;
1677b73de9eSWalter Erquinigo else
1687b73de9eSWalter Erquinigo return offset.takeError();
1697b73de9eSWalter Erquinigo }
1707b73de9eSWalter Erquinigo return config;
1717b73de9eSWalter Erquinigo }
1727b73de9eSWalter Erquinigo
1737b73de9eSWalter Erquinigo /// Create a \a perf_event_attr configured for
1747b73de9eSWalter Erquinigo /// an IntelPT event.
1757b73de9eSWalter Erquinigo ///
1767b73de9eSWalter Erquinigo /// \return
1777b73de9eSWalter Erquinigo /// A \a perf_event_attr if successful,
1787b73de9eSWalter Erquinigo /// or an \a llvm::Error otherwise.
1797b73de9eSWalter Erquinigo static Expected<perf_event_attr>
CreateIntelPTPerfEventConfiguration(bool enable_tsc,llvm::Optional<uint64_t> psb_period)1807b73de9eSWalter Erquinigo CreateIntelPTPerfEventConfiguration(bool enable_tsc,
181c4172c75SWalter Erquinigo llvm::Optional<uint64_t> psb_period) {
1827b73de9eSWalter Erquinigo perf_event_attr attr;
1837b73de9eSWalter Erquinigo memset(&attr, 0, sizeof(attr));
1847b73de9eSWalter Erquinigo attr.size = sizeof(attr);
1857b73de9eSWalter Erquinigo attr.exclude_kernel = 1;
1867b73de9eSWalter Erquinigo attr.exclude_hv = 1;
1877b73de9eSWalter Erquinigo attr.exclude_idle = 1;
1887b73de9eSWalter Erquinigo
1897b73de9eSWalter Erquinigo if (Expected<uint64_t> config_value =
1907b73de9eSWalter Erquinigo GeneratePerfEventConfigValue(enable_tsc, psb_period))
1917b73de9eSWalter Erquinigo attr.config = *config_value;
1927b73de9eSWalter Erquinigo else
1937b73de9eSWalter Erquinigo return config_value.takeError();
1947b73de9eSWalter Erquinigo
1957b73de9eSWalter Erquinigo if (Expected<uint32_t> intel_pt_type = GetIntelPTOSEventType())
1967b73de9eSWalter Erquinigo attr.type = *intel_pt_type;
1977b73de9eSWalter Erquinigo else
1987b73de9eSWalter Erquinigo return intel_pt_type.takeError();
1997b73de9eSWalter Erquinigo
2007b73de9eSWalter Erquinigo return attr;
2017b73de9eSWalter Erquinigo }
202909a2e3cSWalter Erquinigo #endif
2037b73de9eSWalter Erquinigo
GetIptTraceSize() const2046a5355e8SWalter Erquinigo size_t IntelPTSingleBufferTrace::GetIptTraceSize() const {
2057b73de9eSWalter Erquinigo return m_perf_event.GetAuxBuffer().size();
2067b73de9eSWalter Erquinigo }
2077b73de9eSWalter Erquinigo
Pause()208a7582059SWalter Erquinigo Error IntelPTSingleBufferTrace::Pause() {
209a7582059SWalter Erquinigo return m_perf_event.DisableWithIoctl();
2101637545fSWalter Erquinigo }
211a7582059SWalter Erquinigo
Resume()212a7582059SWalter Erquinigo Error IntelPTSingleBufferTrace::Resume() {
213a7582059SWalter Erquinigo return m_perf_event.EnableWithIoctl();
2141637545fSWalter Erquinigo }
2151637545fSWalter Erquinigo
GetIptTrace()2166a5355e8SWalter Erquinigo Expected<std::vector<uint8_t>> IntelPTSingleBufferTrace::GetIptTrace() {
2177b73de9eSWalter Erquinigo // Disable the perf event to force a flush out of the CPU's internal buffer.
2187b73de9eSWalter Erquinigo // Besides, we can guarantee that the CPU won't override any data as we are
2197b73de9eSWalter Erquinigo // reading the buffer.
2207b73de9eSWalter Erquinigo // The Intel documentation says:
2217b73de9eSWalter Erquinigo //
2221637545fSWalter Erquinigo // Packets are first buffered internally and then written out
2231637545fSWalter Erquinigo // asynchronously. To collect packet output for postprocessing, a collector
2241637545fSWalter Erquinigo // needs first to ensure that all packet data has been flushed from internal
2251637545fSWalter Erquinigo // buffers. Software can ensure this by stopping packet generation by
2261637545fSWalter Erquinigo // clearing IA32_RTIT_CTL.TraceEn (see “Disabling Packet Generation” in
2277b73de9eSWalter Erquinigo // Section 35.2.7.2).
2287b73de9eSWalter Erquinigo //
2291637545fSWalter Erquinigo // This is achieved by the PERF_EVENT_IOC_DISABLE ioctl request, as
2301637545fSWalter Erquinigo // mentioned in the man page of perf_event_open.
231561a61fbSWalter Erquinigo return m_perf_event.GetReadOnlyAuxBuffer();
2327b73de9eSWalter Erquinigo }
2337b73de9eSWalter Erquinigo
Start(const TraceIntelPTStartRequest & request,Optional<lldb::tid_t> tid,Optional<cpu_id_t> cpu_id,bool disabled,Optional<int> cgroup_fd)234*d30fd5c3SGaurav Gaur Expected<IntelPTSingleBufferTrace> IntelPTSingleBufferTrace::Start(
235*d30fd5c3SGaurav Gaur const TraceIntelPTStartRequest &request, Optional<lldb::tid_t> tid,
236*d30fd5c3SGaurav Gaur Optional<cpu_id_t> cpu_id, bool disabled, Optional<int> cgroup_fd) {
237909a2e3cSWalter Erquinigo #ifndef PERF_ATTR_SIZE_VER5
238909a2e3cSWalter Erquinigo return createStringError(inconvertibleErrorCode(),
239909a2e3cSWalter Erquinigo "Intel PT Linux perf event not supported");
240909a2e3cSWalter Erquinigo #else
2417b73de9eSWalter Erquinigo Log *log = GetLog(POSIXLog::Trace);
2427b73de9eSWalter Erquinigo
2436a5355e8SWalter Erquinigo LLDB_LOG(log, "Will start tracing thread id {0} and cpu id {1}", tid, cpu_id);
2447b73de9eSWalter Erquinigo
2456a5355e8SWalter Erquinigo if (__builtin_popcount(request.ipt_trace_size) != 1 ||
2466a5355e8SWalter Erquinigo request.ipt_trace_size < 4096) {
2477b73de9eSWalter Erquinigo return createStringError(
2487b73de9eSWalter Erquinigo inconvertibleErrorCode(),
2496a5355e8SWalter Erquinigo "The intel pt trace size must be a power of 2 greater than or equal to "
2507b73de9eSWalter Erquinigo "4096 (2^12) bytes. It was %" PRIu64 ".",
2516a5355e8SWalter Erquinigo request.ipt_trace_size);
2527b73de9eSWalter Erquinigo }
2537b73de9eSWalter Erquinigo uint64_t page_size = getpagesize();
2545a92632dSWalter Erquinigo uint64_t aux_buffer_numpages = static_cast<uint64_t>(llvm::PowerOf2Floor(
2556a5355e8SWalter Erquinigo (request.ipt_trace_size + page_size - 1) / page_size));
2567b73de9eSWalter Erquinigo
2577b73de9eSWalter Erquinigo Expected<perf_event_attr> attr = CreateIntelPTPerfEventConfiguration(
2587b73de9eSWalter Erquinigo request.enable_tsc, request.psb_period.map([](int value) {
2597b73de9eSWalter Erquinigo return static_cast<uint64_t>(value);
2607b73de9eSWalter Erquinigo }));
2617b73de9eSWalter Erquinigo if (!attr)
2627b73de9eSWalter Erquinigo return attr.takeError();
263a7582059SWalter Erquinigo attr->disabled = disabled;
2647b73de9eSWalter Erquinigo
2656a5355e8SWalter Erquinigo LLDB_LOG(log, "Will create intel pt trace buffer of size {0}",
2666a5355e8SWalter Erquinigo request.ipt_trace_size);
267*d30fd5c3SGaurav Gaur unsigned long flags = 0;
268*d30fd5c3SGaurav Gaur if (cgroup_fd) {
269*d30fd5c3SGaurav Gaur tid = *cgroup_fd;
270*d30fd5c3SGaurav Gaur flags |= PERF_FLAG_PID_CGROUP;
271*d30fd5c3SGaurav Gaur }
2727b73de9eSWalter Erquinigo
273*d30fd5c3SGaurav Gaur if (Expected<PerfEvent> perf_event =
274*d30fd5c3SGaurav Gaur PerfEvent::Init(*attr, tid, cpu_id, -1, flags)) {
2755a92632dSWalter Erquinigo if (Error mmap_err = perf_event->MmapMetadataAndBuffers(
276fc5ef57cSWalter Erquinigo /*num_data_pages=*/0, aux_buffer_numpages,
277fc5ef57cSWalter Erquinigo /*data_buffer_write=*/true)) {
2787b73de9eSWalter Erquinigo return std::move(mmap_err);
2797b73de9eSWalter Erquinigo }
280a7582059SWalter Erquinigo return IntelPTSingleBufferTrace(std::move(*perf_event));
2817b73de9eSWalter Erquinigo } else {
2827b73de9eSWalter Erquinigo return perf_event.takeError();
2837b73de9eSWalter Erquinigo }
284909a2e3cSWalter Erquinigo #endif
2857b73de9eSWalter Erquinigo }
286a7582059SWalter Erquinigo
GetPerfEvent() const287a7582059SWalter Erquinigo const PerfEvent &IntelPTSingleBufferTrace::GetPerfEvent() const {
288a7582059SWalter Erquinigo return m_perf_event;
289a7582059SWalter Erquinigo }
290