From: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx> Add Intel processor trace virtualization call backs to suppress host event in guest only mode. Signed-off-by: Chao Peng <chao.p.peng@xxxxxxxxxxxxxxx> Signed-off-by: Luwei Kang <luwei.kang@xxxxxxxxx> --- arch/x86/events/intel/pt.c | 21 +++++++++++++++++++++ arch/x86/include/asm/intel_pt.h | 9 +++++++++ 2 files changed, 30 insertions(+) diff --git a/arch/x86/events/intel/pt.c b/arch/x86/events/intel/pt.c index a5a7e44..ec54bba 100644 --- a/arch/x86/events/intel/pt.c +++ b/arch/x86/events/intel/pt.c @@ -36,6 +36,7 @@ static DEFINE_PER_CPU(struct pt, pt_ctx); static struct pt_pmu pt_pmu; +static struct pt_virt_ops *virt_ops; /* * Capabilities of Intel PT hardware, such as number of address bits or @@ -177,6 +178,18 @@ static ssize_t pt_cap_show(struct device *cdev, NULL, }; +void pt_register_virt_ops(struct pt_virt_ops *ops) +{ + virt_ops = ops; +} +EXPORT_SYMBOL_GPL(pt_register_virt_ops); + +void pt_unregister_virt_ops(void) +{ + virt_ops = NULL; +} +EXPORT_SYMBOL_GPL(pt_unregister_virt_ops); + static int __init pt_pmu_hw_init(void) { struct dev_ext_attribute *de_attrs; @@ -1244,6 +1257,9 @@ void intel_pt_interrupt(void) struct pt_buffer *buf; struct perf_event *event = pt->handle.event; + if (virt_ops && virt_ops->pmi && virt_ops->pmi()) + return; + /* * There may be a dangling PT bit in the interrupt status register * after PT has been disabled by pt_event_stop(). Make sure we don't @@ -1444,6 +1460,11 @@ static void pt_event_destroy(struct perf_event *event) static int pt_event_init(struct perf_event *event) { + /* suppress host event in guest only mode */ + if (virt_ops && virt_ops->get_mode && + virt_ops->get_mode() == PT_MODE_GUEST) + return -EPERM; + if (event->attr.type != pt_pmu.pmu.type) return -ENOENT; diff --git a/arch/x86/include/asm/intel_pt.h b/arch/x86/include/asm/intel_pt.h index b5dd33c..6a5d475 100644 --- a/arch/x86/include/asm/intel_pt.h +++ b/arch/x86/include/asm/intel_pt.h @@ -26,12 +26,21 @@ enum pt_capabilities { PT_CAP_psb_periods, }; +struct pt_virt_ops { + enum pt_mode (*get_mode)(void); + bool (*pmi)(void); +}; + #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) void cpu_emergency_stop_pt(void); extern u32 pt_cap_get(enum pt_capabilities cap); +extern void pt_register_virt_ops(struct pt_virt_ops *ops); +extern void pt_unregister_virt_ops(void); #else static inline void cpu_emergency_stop_pt(void) {} static inline u32 pt_cap_get(enum pt_capabilities cap) { return 0; } +static void pt_register_virt_ops(struct pt_virt_ops *ops) { } +static void pt_unregister_virt_ops(void) { } #endif #endif /* _ASM_X86_INTEL_PT_H */ -- 1.8.3.1