]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
perf/x86/intel/pt: Prevent redundant WRMSRs
authorAlexander Shishkin <alexander.shishkin@linux.intel.com>
Tue, 5 Nov 2019 08:27:01 +0000 (10:27 +0200)
committerIngo Molnar <mingo@kernel.org>
Wed, 13 Nov 2019 10:06:18 +0000 (11:06 +0100)
With recent optimizations to AUX and PT buffer management code (high order
AUX allocations, opportunistic Single Range Output), it is far more likely
now that the output MSRs won't need reprogramming on every sched-in.

To avoid needless WRMSRs of those registers, cache their values and only
write them when needed.

Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: David Ahern <dsahern@gmail.com>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Jiri Olsa <jolsa@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Stephane Eranian <eranian@google.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Vince Weaver <vincent.weaver@maine.edu>
Link: https://lkml.kernel.org/r/20191105082701.78442-3-alexander.shishkin@linux.intel.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/events/intel/pt.c
arch/x86/events/intel/pt.h

index c87d163c29179e2f98f0bcf9b62891187b2ee8ee..1db7a51d9792b4b6473ce49d0d2d4a90a6d45043 100644 (file)
@@ -606,6 +606,7 @@ static inline phys_addr_t topa_pfn(struct topa *topa)
 
 static void pt_config_buffer(struct pt_buffer *buf)
 {
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
        u64 reg, mask;
        void *base;
 
@@ -617,11 +618,17 @@ static void pt_config_buffer(struct pt_buffer *buf)
                mask = (u64)buf->cur_idx;
        }
 
-       wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, virt_to_phys(base));
+       reg = virt_to_phys(base);
+       if (pt->output_base != reg) {
+               pt->output_base = reg;
+               wrmsrl(MSR_IA32_RTIT_OUTPUT_BASE, reg);
+       }
 
        reg = 0x7f | (mask << 7) | ((u64)buf->output_off << 32);
-
-       wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
+       if (pt->output_mask != reg) {
+               pt->output_mask = reg;
+               wrmsrl(MSR_IA32_RTIT_OUTPUT_MASK, reg);
+       }
 }
 
 /**
@@ -930,21 +937,21 @@ static void pt_handle_status(struct pt *pt)
  */
 static void pt_read_offset(struct pt_buffer *buf)
 {
-       u64 offset, base;
+       struct pt *pt = this_cpu_ptr(&pt_ctx);
        struct topa_page *tp;
 
        if (!buf->single) {
-               rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, base);
-               tp = phys_to_virt(base);
+               rdmsrl(MSR_IA32_RTIT_OUTPUT_BASE, pt->output_base);
+               tp = phys_to_virt(pt->output_base);
                buf->cur = &tp->topa;
        }
 
-       rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, offset);
+       rdmsrl(MSR_IA32_RTIT_OUTPUT_MASK, pt->output_mask);
        /* offset within current output region */
-       buf->output_off = offset >> 32;
+       buf->output_off = pt->output_mask >> 32;
        /* index of current output region within this table */
        if (!buf->single)
-               buf->cur_idx = (offset & 0xffffff80) >> 7;
+               buf->cur_idx = (pt->output_mask & 0xffffff80) >> 7;
 }
 
 static struct topa_entry *
index 3f7818221b9535451e12b5e9ea910182c7ab4efc..96906a62aacdad2b20f56ac9e93e3be310f8f14e 100644 (file)
@@ -113,16 +113,20 @@ struct pt_filters {
 
 /**
  * struct pt - per-cpu pt context
- * @handle:    perf output handle
+ * @handle:            perf output handle
  * @filters:           last configured filters
- * @handle_nmi:        do handle PT PMI on this cpu, there's an active event
- * @vmx_on:    1 if VMX is ON on this cpu
+ * @handle_nmi:                do handle PT PMI on this cpu, there's an active event
+ * @vmx_on:            1 if VMX is ON on this cpu
+ * @output_base:       cached RTIT_OUTPUT_BASE MSR value
+ * @output_mask:       cached RTIT_OUTPUT_MASK MSR value
  */
 struct pt {
        struct perf_output_handle handle;
        struct pt_filters       filters;
        int                     handle_nmi;
        int                     vmx_on;
+       u64                     output_base;
+       u64                     output_mask;
 };
 
 #endif /* __INTEL_PT_H__ */