#include <linux/types.h>
 #include <linux/bitops.h>
 #include <linux/log2.h>
+#include <cpuid.h>
 
 #include "../../perf.h"
 #include "../../util/session.h"
        return INTEL_PT_AUXTRACE_PRIV_SIZE;
 }
 
+static void intel_pt_tsc_ctc_ratio(u32 *n, u32 *d)
+{
+       unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
+
+       __get_cpuid(0x15, &eax, &ebx, &ecx, &edx);
+       *n = ebx;
+       *d = eax;
+}
+
 static int intel_pt_info_fill(struct auxtrace_record *itr,
                              struct perf_session *session,
                              struct auxtrace_info_event *auxtrace_info,
        struct perf_event_mmap_page *pc;
        struct perf_tsc_conversion tc = { .time_mult = 0, };
        bool cap_user_time_zero = false, per_cpu_mmaps;
-       u64 tsc_bit, noretcomp_bit;
+       u64 tsc_bit, mtc_bit, mtc_freq_bits, cyc_bit, noretcomp_bit;
+       u32 tsc_ctc_ratio_n, tsc_ctc_ratio_d;
        int err;
 
        if (priv_size != INTEL_PT_AUXTRACE_PRIV_SIZE)
        intel_pt_parse_terms(&intel_pt_pmu->format, "tsc", &tsc_bit);
        intel_pt_parse_terms(&intel_pt_pmu->format, "noretcomp",
                             &noretcomp_bit);
+       intel_pt_parse_terms(&intel_pt_pmu->format, "mtc", &mtc_bit);
+       mtc_freq_bits = perf_pmu__format_bits(&intel_pt_pmu->format,
+                                             "mtc_period");
+       intel_pt_parse_terms(&intel_pt_pmu->format, "cyc", &cyc_bit);
+
+       intel_pt_tsc_ctc_ratio(&tsc_ctc_ratio_n, &tsc_ctc_ratio_d);
 
        if (!session->evlist->nr_mmaps)
                return -EINVAL;
        auxtrace_info->priv[INTEL_PT_HAVE_SCHED_SWITCH] = ptr->have_sched_switch;
        auxtrace_info->priv[INTEL_PT_SNAPSHOT_MODE] = ptr->snapshot_mode;
        auxtrace_info->priv[INTEL_PT_PER_CPU_MMAPS] = per_cpu_mmaps;
+       auxtrace_info->priv[INTEL_PT_MTC_BIT] = mtc_bit;
+       auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS] = mtc_freq_bits;
+       auxtrace_info->priv[INTEL_PT_TSC_CTC_N] = tsc_ctc_ratio_n;
+       auxtrace_info->priv[INTEL_PT_TSC_CTC_D] = tsc_ctc_ratio_d;
+       auxtrace_info->priv[INTEL_PT_CYC_BIT] = cyc_bit;
 
        return 0;
 }
 
        bool synth_needs_swap;
 
        u64 tsc_bit;
+       u64 mtc_bit;
+       u64 mtc_freq_bits;
+       u32 tsc_ctc_ratio_n;
+       u32 tsc_ctc_ratio_d;
+       u64 cyc_bit;
        u64 noretcomp_bit;
        unsigned max_non_turbo_ratio;
 };
        return true;
 }
 
+static unsigned int intel_pt_mtc_period(struct intel_pt *pt)
+{
+       struct perf_evsel *evsel;
+       unsigned int shift;
+       u64 config;
+
+       if (!pt->mtc_freq_bits)
+               return 0;
+
+       for (shift = 0, config = pt->mtc_freq_bits; !(config & 1); shift++)
+               config >>= 1;
+
+       evlist__for_each(pt->session->evlist, evsel) {
+               if (intel_pt_get_config(pt, &evsel->attr, &config))
+                       return (config & pt->mtc_freq_bits) >> shift;
+       }
+       return 0;
+}
+
 static bool intel_pt_timeless_decoding(struct intel_pt *pt)
 {
        struct perf_evsel *evsel;
        params.data = ptq;
        params.return_compression = intel_pt_return_compression(pt);
        params.max_non_turbo_ratio = pt->max_non_turbo_ratio;
+       params.mtc_period = intel_pt_mtc_period(pt);
+       params.tsc_ctc_ratio_n = pt->tsc_ctc_ratio_n;
+       params.tsc_ctc_ratio_d = pt->tsc_ctc_ratio_d;
 
        if (pt->synth_opts.instructions) {
                if (pt->synth_opts.period) {
 }
 
 static const char * const intel_pt_info_fmts[] = {
-       [INTEL_PT_PMU_TYPE]             = "  PMU Type           %"PRId64"\n",
-       [INTEL_PT_TIME_SHIFT]           = "  Time Shift         %"PRIu64"\n",
-       [INTEL_PT_TIME_MULT]            = "  Time Muliplier     %"PRIu64"\n",
-       [INTEL_PT_TIME_ZERO]            = "  Time Zero          %"PRIu64"\n",
-       [INTEL_PT_CAP_USER_TIME_ZERO]   = "  Cap Time Zero      %"PRId64"\n",
-       [INTEL_PT_TSC_BIT]              = "  TSC bit            %#"PRIx64"\n",
-       [INTEL_PT_NORETCOMP_BIT]        = "  NoRETComp bit      %#"PRIx64"\n",
-       [INTEL_PT_HAVE_SCHED_SWITCH]    = "  Have sched_switch  %"PRId64"\n",
-       [INTEL_PT_SNAPSHOT_MODE]        = "  Snapshot mode      %"PRId64"\n",
-       [INTEL_PT_PER_CPU_MMAPS]        = "  Per-cpu maps       %"PRId64"\n",
+       [INTEL_PT_PMU_TYPE]             = "  PMU Type            %"PRId64"\n",
+       [INTEL_PT_TIME_SHIFT]           = "  Time Shift          %"PRIu64"\n",
+       [INTEL_PT_TIME_MULT]            = "  Time Muliplier      %"PRIu64"\n",
+       [INTEL_PT_TIME_ZERO]            = "  Time Zero           %"PRIu64"\n",
+       [INTEL_PT_CAP_USER_TIME_ZERO]   = "  Cap Time Zero       %"PRId64"\n",
+       [INTEL_PT_TSC_BIT]              = "  TSC bit             %#"PRIx64"\n",
+       [INTEL_PT_NORETCOMP_BIT]        = "  NoRETComp bit       %#"PRIx64"\n",
+       [INTEL_PT_HAVE_SCHED_SWITCH]    = "  Have sched_switch   %"PRId64"\n",
+       [INTEL_PT_SNAPSHOT_MODE]        = "  Snapshot mode       %"PRId64"\n",
+       [INTEL_PT_PER_CPU_MMAPS]        = "  Per-cpu maps        %"PRId64"\n",
+       [INTEL_PT_MTC_BIT]              = "  MTC bit             %#"PRIx64"\n",
+       [INTEL_PT_TSC_CTC_N]            = "  TSC:CTC numerator   %"PRIu64"\n",
+       [INTEL_PT_TSC_CTC_D]            = "  TSC:CTC denominator %"PRIu64"\n",
+       [INTEL_PT_CYC_BIT]              = "  CYC bit             %#"PRIx64"\n",
 };
 
 static void intel_pt_print_info(u64 *arr, int start, int finish)
        intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_PMU_TYPE,
                            INTEL_PT_PER_CPU_MMAPS);
 
+       if (auxtrace_info->header.size >= sizeof(struct auxtrace_info_event) +
+                                       (sizeof(u64) * INTEL_PT_CYC_BIT)) {
+               pt->mtc_bit = auxtrace_info->priv[INTEL_PT_MTC_BIT];
+               pt->mtc_freq_bits = auxtrace_info->priv[INTEL_PT_MTC_FREQ_BITS];
+               pt->tsc_ctc_ratio_n = auxtrace_info->priv[INTEL_PT_TSC_CTC_N];
+               pt->tsc_ctc_ratio_d = auxtrace_info->priv[INTEL_PT_TSC_CTC_D];
+               pt->cyc_bit = auxtrace_info->priv[INTEL_PT_CYC_BIT];
+               intel_pt_print_info(&auxtrace_info->priv[0], INTEL_PT_MTC_BIT,
+                                   INTEL_PT_CYC_BIT);
+       }
+
        pt->timeless_decoding = intel_pt_timeless_decoding(pt);
        pt->have_tsc = intel_pt_have_tsc(pt);
        pt->sampling_mode = false;