Commit 946904e7 authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch kvm-arm64/coresight-6.14 into kvmarm-master/next



* kvm-arm64/coresight-6.14:
  : .
  : Trace filtering update from James Clark. From the cover letter:
  :
  : "The guest filtering rules from the Perf session are now honored for both
  : nVHE and VHE modes. This is done by either writing to TRFCR_EL12 at the
  : start of the Perf session and doing nothing else further, or caching the
  : guest value and writing it at guest switch for nVHE. In pKVM, trace is
  : now be disabled for both protected and unprotected guests."
  : .
  KVM: arm64: Fix selftests after sysreg field name update
  coresight: Pass guest TRFCR value to KVM
  KVM: arm64: Support trace filtering for guests
  KVM: arm64: coresight: Give TRBE enabled state to KVM
  coresight: trbe: Remove redundant disable call
  arm64/sysreg/tools: Move TRFCR definitions to sysreg
  tools: arm64: Update sysreg.h header files

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 5e68d2ee 9fb4267a
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -617,6 +617,8 @@ struct kvm_host_data {
#define KVM_HOST_DATA_FLAG_HAS_TRBE			1
#define KVM_HOST_DATA_FLAG_HOST_SVE_ENABLED		2
#define KVM_HOST_DATA_FLAG_HOST_SME_ENABLED		3
#define KVM_HOST_DATA_FLAG_TRBE_ENABLED			4
#define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED	5
	unsigned long flags;

	struct kvm_cpu_context host_ctxt;
@@ -662,6 +664,9 @@ struct kvm_host_data {
		u64 mdcr_el2;
	} host_debug_state;

	/* Guest trace filter value */
	u64 trfcr_while_in_guest;

	/* Number of programmable event counters (PMCR_EL0.N) for this CPU */
	unsigned int nr_event_counters;

@@ -1389,6 +1394,9 @@ static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr)
void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr);
void kvm_clr_pmu_events(u64 clr);
bool kvm_set_pmuserenr(u64 val);
void kvm_enable_trbe(void);
void kvm_disable_trbe(void);
void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest);
#else
static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr) {}
static inline void kvm_clr_pmu_events(u64 clr) {}
@@ -1396,6 +1404,9 @@ static inline bool kvm_set_pmuserenr(u64 val)
{
	return false;
}
static inline void kvm_enable_trbe(void) {}
static inline void kvm_disable_trbe(void) {}
static inline void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest) {}
#endif

void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
+0 −12
Original line number Diff line number Diff line
@@ -283,8 +283,6 @@
#define SYS_RGSR_EL1			sys_reg(3, 0, 1, 0, 5)
#define SYS_GCR_EL1			sys_reg(3, 0, 1, 0, 6)

#define SYS_TRFCR_EL1			sys_reg(3, 0, 1, 2, 1)

#define SYS_TCR_EL1			sys_reg(3, 0, 2, 0, 2)

#define SYS_APIAKEYLO_EL1		sys_reg(3, 0, 2, 1, 0)
@@ -523,7 +521,6 @@
#define SYS_VTTBR_EL2			sys_reg(3, 4, 2, 1, 0)
#define SYS_VTCR_EL2			sys_reg(3, 4, 2, 1, 2)

#define SYS_TRFCR_EL2			sys_reg(3, 4, 1, 2, 1)
#define SYS_VNCR_EL2			sys_reg(3, 4, 2, 2, 0)
#define SYS_HAFGRTR_EL2			sys_reg(3, 4, 3, 1, 6)
#define SYS_SPSR_EL2			sys_reg(3, 4, 4, 0, 0)
@@ -987,15 +984,6 @@
/* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
#define SYS_MPIDR_SAFE_VAL	(BIT(31))

#define TRFCR_ELx_TS_SHIFT		5
#define TRFCR_ELx_TS_MASK		((0x3UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_ELx_TS_VIRTUAL		((0x1UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_ELx_TS_GUEST_PHYSICAL	((0x2UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_ELx_TS_PHYSICAL		((0x3UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_EL2_CX			BIT(3)
#define TRFCR_ELx_ExTRE			BIT(1)
#define TRFCR_ELx_E0TRE			BIT(0)

/* GIC Hypervisor interface registers */
/* ICH_MISR_EL2 bit definitions */
#define ICH_MISR_EOI		(1 << 0)
+47 −3
Original line number Diff line number Diff line
@@ -81,10 +81,16 @@ void kvm_init_host_debug_data(void)
	    !(read_sysreg_s(SYS_PMBIDR_EL1) & PMBIDR_EL1_P))
		host_data_set_flag(HAS_SPE);

	if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) {
		/* Force disable trace in protected mode in case of no TRBE */
		if (is_protected_kvm_enabled())
			host_data_set_flag(EL1_TRACING_CONFIGURED);

		if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) &&
		    !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P))
			host_data_set_flag(HAS_TRBE);
	}
}

/*
 * Configures the 'external' MDSCR_EL1 value for the guest, i.e. when the host
@@ -219,3 +225,41 @@ void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val)
	kvm_arch_vcpu_load(vcpu, smp_processor_id());
	preempt_enable();
}

void kvm_enable_trbe(void)
{
	if (has_vhe() || is_protected_kvm_enabled() ||
	    WARN_ON_ONCE(preemptible()))
		return;

	host_data_set_flag(TRBE_ENABLED);
}
EXPORT_SYMBOL_GPL(kvm_enable_trbe);

void kvm_disable_trbe(void)
{
	if (has_vhe() || is_protected_kvm_enabled() ||
	    WARN_ON_ONCE(preemptible()))
		return;

	host_data_clear_flag(TRBE_ENABLED);
}
EXPORT_SYMBOL_GPL(kvm_disable_trbe);

void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest)
{
	if (is_protected_kvm_enabled() || WARN_ON_ONCE(preemptible()))
		return;

	if (has_vhe()) {
		write_sysreg_s(trfcr_while_in_guest, SYS_TRFCR_EL12);
		return;
	}

	*host_data_ptr(trfcr_while_in_guest) = trfcr_while_in_guest;
	if (read_sysreg_s(SYS_TRFCR_EL1) != trfcr_while_in_guest)
		host_data_set_flag(EL1_TRACING_CONFIGURED);
	else
		host_data_clear_flag(EL1_TRACING_CONFIGURED);
}
EXPORT_SYMBOL_GPL(kvm_tracing_set_el1_configuration);
+38 −25
Original line number Diff line number Diff line
@@ -51,32 +51,45 @@ static void __debug_restore_spe(u64 pmscr_el1)
	write_sysreg_el1(pmscr_el1, SYS_PMSCR);
}

static void __debug_save_trace(u64 *trfcr_el1)
static void __trace_do_switch(u64 *saved_trfcr, u64 new_trfcr)
{
	*trfcr_el1 = 0;
	*saved_trfcr = read_sysreg_el1(SYS_TRFCR);
	write_sysreg_el1(new_trfcr, SYS_TRFCR);
}

	/* Check if the TRBE is enabled */
	if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E))
		return;
	/*
	 * Prohibit trace generation while we are in guest.
	 * Since access to TRFCR_EL1 is trapped, the guest can't
	 * modify the filtering set by the host.
	 */
	*trfcr_el1 = read_sysreg_el1(SYS_TRFCR);
	write_sysreg_el1(0, SYS_TRFCR);
static bool __trace_needs_drain(void)
{
	if (is_protected_kvm_enabled() && host_data_test_flag(HAS_TRBE))
		return read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E;

	return host_data_test_flag(TRBE_ENABLED);
}

static bool __trace_needs_switch(void)
{
	return host_data_test_flag(TRBE_ENABLED) ||
	       host_data_test_flag(EL1_TRACING_CONFIGURED);
}

static void __trace_switch_to_guest(void)
{
	/* Unsupported with TRBE so disable */
	if (host_data_test_flag(TRBE_ENABLED))
		*host_data_ptr(trfcr_while_in_guest) = 0;

	__trace_do_switch(host_data_ptr(host_debug_state.trfcr_el1),
			  *host_data_ptr(trfcr_while_in_guest));

	if (__trace_needs_drain()) {
		isb();
	/* Drain the trace buffer to memory */
		tsb_csync();
	}
}

static void __debug_restore_trace(u64 trfcr_el1)
static void __trace_switch_to_host(void)
{
	if (!trfcr_el1)
		return;

	/* Restore trace filter controls */
	write_sysreg_el1(trfcr_el1, SYS_TRFCR);
	__trace_do_switch(host_data_ptr(trfcr_while_in_guest),
			  *host_data_ptr(host_debug_state.trfcr_el1));
}

void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
@@ -84,9 +97,9 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
	/* Disable and flush SPE data generation */
	if (host_data_test_flag(HAS_SPE))
		__debug_save_spe(host_data_ptr(host_debug_state.pmscr_el1));
	/* Disable and flush Self-Hosted Trace generation */
	if (host_data_test_flag(HAS_TRBE))
		__debug_save_trace(host_data_ptr(host_debug_state.trfcr_el1));

	if (__trace_needs_switch())
		__trace_switch_to_guest();
}

void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
@@ -98,8 +111,8 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
{
	if (host_data_test_flag(HAS_SPE))
		__debug_restore_spe(*host_data_ptr(host_debug_state.pmscr_el1));
	if (host_data_test_flag(HAS_TRBE))
		__debug_restore_trace(*host_data_ptr(host_debug_state.trfcr_el1));
	if (__trace_needs_switch())
		__trace_switch_to_host();
}

void __debug_switch_to_host(struct kvm_vcpu *vcpu)
+36 −0
Original line number Diff line number Diff line
@@ -1999,6 +1999,22 @@ Field 17:16 ZEN
Res0	15:0
EndSysreg

SysregFields TRFCR_ELx
Res0	63:7
UnsignedEnum	6:5	TS
	0b0001	VIRTUAL
	0b0010	GUEST_PHYSICAL
	0b0011	PHYSICAL
EndEnum
Res0	4:2
Field	1	ExTRE
Field	0	E0TRE
EndSysregFields

Sysreg	TRFCR_EL1	3	0	1	2	1
Fields	TRFCR_ELx
EndSysreg

Sysreg	SMPRI_EL1	3	0	1	2	4
Res0	63:4
Field	3:0	PRIORITY
@@ -2548,6 +2564,22 @@ Field 1 ICIALLU
Field	0	ICIALLUIS
EndSysreg

Sysreg TRFCR_EL2	3	4	1	2	1
Res0	63:7
UnsignedEnum	6:5	TS
	0b0000	USE_TRFCR_EL1_TS
	0b0001	VIRTUAL
	0b0010	GUEST_PHYSICAL
	0b0011	PHYSICAL
EndEnum
Res0	4
Field	3	CX
Res0	2
Field	1	E2TRE
Field	0	E0HTRE
EndSysreg


Sysreg HDFGRTR_EL2	3	4	3	1	4
Field	63	PMBIDR_EL1
Field	62	nPMSNEVFR_EL1
@@ -2958,6 +2990,10 @@ Sysreg ZCR_EL12 3 5 1 2 0
Mapping	ZCR_EL1
EndSysreg

Sysreg	TRFCR_EL12	3	5	1	2	1
Fields	TRFCR_ELx
EndSysreg

Sysreg	SMCR_EL12	3	5	1	2	6
Mapping	SMCR_EL1
EndSysreg
Loading