The LBR stack MSRs are architecturally specific. The perf subsystem has
already assigned the abstracted MSR values based on the CPU architecture.

This patch enables a caller outside the perf subsystem to get the LBR
stack info. This is useful for hyperviosrs to prepare the lbr feature
for the guest.

Signed-off-by: Like Xu <like...@intel.com>
Signed-off-by: Wei Wang <wei.w.w...@intel.com>
Cc: Paolo Bonzini <pbonz...@redhat.com>
Cc: Andi Kleen <a...@linux.intel.com>
---
 arch/x86/events/intel/lbr.c       | 23 +++++++++++++++++++++++
 arch/x86/include/asm/perf_event.h | 14 ++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/x86/events/intel/lbr.c b/arch/x86/events/intel/lbr.c
index f3e006b..7c3958e 100644
--- a/arch/x86/events/intel/lbr.c
+++ b/arch/x86/events/intel/lbr.c
@@ -1273,3 +1273,26 @@ void intel_pmu_lbr_init_knl(void)
        x86_pmu.lbr_sel_mask = LBR_SEL_MASK;
        x86_pmu.lbr_sel_map  = snb_lbr_sel_map;
 }
+
+/**
+ * perf_get_lbr_stack - get the lbr stack related MSRs
+ *
+ * @stack: the caller's memory to get the lbr stack
+ *
+ * Returns: 0 indicates that the lbr stack has been successfully obtained.
+ */
+int perf_get_lbr_stack(struct perf_lbr_stack *stack)
+{
+       stack->lbr_nr = x86_pmu.lbr_nr;
+       stack->lbr_tos = x86_pmu.lbr_tos;
+       stack->lbr_from = x86_pmu.lbr_from;
+       stack->lbr_to = x86_pmu.lbr_to;
+
+       if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_INFO)
+               stack->lbr_info = MSR_LBR_INFO_0;
+       else
+               stack->lbr_info = 0;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(perf_get_lbr_stack);
diff --git a/arch/x86/include/asm/perf_event.h 
b/arch/x86/include/asm/perf_event.h
index 12f5408..f40e80a 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -267,7 +267,16 @@ struct perf_guest_switch_msr {
        u64 host, guest;
 };
 
+struct perf_lbr_stack {
+       int             lbr_nr;
+       unsigned long   lbr_tos;
+       unsigned long   lbr_from;
+       unsigned long   lbr_to;
+       unsigned long   lbr_info;
+};
+
 extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
+extern int perf_get_lbr_stack(struct perf_lbr_stack *stack);
 extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
 extern void perf_check_microcode(void);
 #else
@@ -277,6 +286,11 @@ static inline struct perf_guest_switch_msr 
*perf_guest_get_msrs(int *nr)
        return NULL;
 }
 
+static inline int perf_get_lbr_stack(struct perf_lbr_stack *stack)
+{
+       return -1;
+}
+
 static inline void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap)
 {
        memset(cap, 0, sizeof(*cap));
-- 
2.7.4

Reply via email to