Commit b2d65047 authored by Like Xu's avatar Like Xu Committed by Peter Zijlstra

perf/x86/lbr: Add interface to get LBR information

The LBR records msrs are model specific. The perf subsystem has already
obtained the base addresses of LBR records based on the cpu model.

Therefore, an interface is added to allow callers outside the perf
subsystem to obtain these LBR information. It's useful for hypervisors
to emulate the LBR feature for guests with less code.
Signed-off-by: default avatarLike Xu <like.xu@linux.intel.com>
Signed-off-by: default avatarWei Wang <wei.w.wang@intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20200613080958.132489-4-like.xu@linux.intel.com
parent 027440b5
...@@ -1343,3 +1343,23 @@ void intel_pmu_lbr_init_knl(void) ...@@ -1343,3 +1343,23 @@ void intel_pmu_lbr_init_knl(void)
if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_LIP) if (x86_pmu.intel_cap.lbr_format == LBR_FORMAT_LIP)
x86_pmu.intel_cap.lbr_format = LBR_FORMAT_EIP_FLAGS; x86_pmu.intel_cap.lbr_format = LBR_FORMAT_EIP_FLAGS;
} }
/**
* x86_perf_get_lbr - get the LBR records information
*
* @lbr: the caller's memory to store the LBR records information
*
* Returns: 0 indicates the LBR info has been successfully obtained
*/
int x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
{
int lbr_fmt = x86_pmu.intel_cap.lbr_format;
lbr->nr = x86_pmu.lbr_nr;
lbr->from = x86_pmu.lbr_from;
lbr->to = x86_pmu.lbr_to;
lbr->info = (lbr_fmt == LBR_FORMAT_INFO) ? MSR_LBR_INFO_0 : 0;
return 0;
}
EXPORT_SYMBOL_GPL(x86_perf_get_lbr);
...@@ -333,6 +333,13 @@ struct perf_guest_switch_msr { ...@@ -333,6 +333,13 @@ struct perf_guest_switch_msr {
u64 host, guest; u64 host, guest;
}; };
struct x86_pmu_lbr {
unsigned int nr;
unsigned int from;
unsigned int to;
unsigned int info;
};
extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap); extern void perf_get_x86_pmu_capability(struct x86_pmu_capability *cap);
extern void perf_check_microcode(void); extern void perf_check_microcode(void);
extern int x86_perf_rdpmc_index(struct perf_event *event); extern int x86_perf_rdpmc_index(struct perf_event *event);
...@@ -348,12 +355,17 @@ static inline void perf_check_microcode(void) { } ...@@ -348,12 +355,17 @@ static inline void perf_check_microcode(void) { }
#if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL)
extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr); extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr);
extern int x86_perf_get_lbr(struct x86_pmu_lbr *lbr);
#else #else
static inline struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr) static inline struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr)
{ {
*nr = 0; *nr = 0;
return NULL; return NULL;
} }
static inline int x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
{
return -1;
}
#endif #endif
#ifdef CONFIG_CPU_SUP_INTEL #ifdef CONFIG_CPU_SUP_INTEL
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment