Commit 097e4311 authored by Like Xu's avatar Like Xu Committed by Peter Zijlstra
Browse files

perf/x86: Add constraint to create guest LBR event without hw counter



The hypervisor may request the perf subsystem to schedule a time window
to directly access the LBR records msrs for its own use. Normally, it would
create a guest LBR event with callstack mode enabled, which is scheduled
along with other ordinary LBR events on the host but in an exclusive way.

To avoid wasting a counter for the guest LBR event, the perf tracks its
hw->idx via INTEL_PMC_IDX_FIXED_VLBR and assigns it with a fake VLBR
counter with the help of new vlbr_constraint. As with the BTS event,
there is actually no hardware counter assigned for the guest LBR event.

Signed-off-by: default avatarLike Xu <like.xu@linux.intel.com>
Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
Link: https://lkml.kernel.org/r/20200514083054.62538-5-like.xu@linux.intel.com
parent b2d65047
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1104,6 +1104,7 @@ static inline void x86_assign_hw_event(struct perf_event *event,

	switch (hwc->idx) {
	case INTEL_PMC_IDX_FIXED_BTS:
	case INTEL_PMC_IDX_FIXED_VLBR:
		hwc->config_base = 0;
		hwc->event_base	= 0;
		break;
+18 −0
Original line number Diff line number Diff line
@@ -2621,6 +2621,20 @@ intel_bts_constraints(struct perf_event *event)
	return NULL;
}

/*
 * Note: matches a fake event, like Fixed2.
 */
static struct event_constraint *
intel_vlbr_constraints(struct perf_event *event)
{
	struct event_constraint *c = &vlbr_constraint;

	if (unlikely(constraint_match(c, event->hw.config)))
		return c;

	return NULL;
}

static int intel_alt_er(int idx, u64 config)
{
	int alt_idx = idx;
@@ -2811,6 +2825,10 @@ __intel_get_event_constraints(struct cpu_hw_events *cpuc, int idx,
{
	struct event_constraint *c;

	c = intel_vlbr_constraints(event);
	if (c)
		return c;

	c = intel_bts_constraints(event);
	if (c)
		return c;
+4 −0
Original line number Diff line number Diff line
@@ -1363,3 +1363,7 @@ int x86_perf_get_lbr(struct x86_pmu_lbr *lbr)
	return 0;
}
EXPORT_SYMBOL_GPL(x86_perf_get_lbr);

struct event_constraint vlbr_constraint =
	FIXED_EVENT_CONSTRAINT(INTEL_FIXED_VLBR_EVENT,
			       (INTEL_PMC_IDX_FIXED_VLBR - INTEL_PMC_IDX_FIXED));
+1 −0
Original line number Diff line number Diff line
@@ -990,6 +990,7 @@ void release_ds_buffers(void);
void reserve_ds_buffers(void);

extern struct event_constraint bts_constraint;
extern struct event_constraint vlbr_constraint;

void intel_pmu_enable_bts(u64 config);

+21 −1
Original line number Diff line number Diff line
@@ -192,9 +192,29 @@ struct x86_pmu_capability {
#define GLOBAL_STATUS_UNC_OVF				BIT_ULL(61)
#define GLOBAL_STATUS_ASIF				BIT_ULL(60)
#define GLOBAL_STATUS_COUNTERS_FROZEN			BIT_ULL(59)
#define GLOBAL_STATUS_LBRS_FROZEN			BIT_ULL(58)
#define GLOBAL_STATUS_LBRS_FROZEN_BIT			58
#define GLOBAL_STATUS_LBRS_FROZEN			BIT_ULL(GLOBAL_STATUS_LBRS_FROZEN_BIT)
#define GLOBAL_STATUS_TRACE_TOPAPMI			BIT_ULL(55)

/*
 * We model guest LBR event tracing as another fixed-mode PMC like BTS.
 *
 * We choose bit 58 because it's used to indicate LBR stack frozen state
 * for architectural perfmon v4, also we unconditionally mask that bit in
 * the handle_pmi_common(), so it'll never be set in the overflow handling.
 *
 * With this fake counter assigned, the guest LBR event user (such as KVM),
 * can program the LBR registers on its own, and we don't actually do anything
 * with then in the host context.
 */
#define INTEL_PMC_IDX_FIXED_VLBR	(GLOBAL_STATUS_LBRS_FROZEN_BIT)

/*
 * Pseudo-encoding the guest LBR event as event=0x00,umask=0x1b,
 * since it would claim bit 58 which is effectively Fixed26.
 */
#define INTEL_FIXED_VLBR_EVENT	0x1b00

/*
 * Adaptive PEBS v4
 */