Commit 909eac68 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvmarm-fixes-7.1-1' of...

Merge tag 'kvmarm-fixes-7.1-1' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD

KVM/arm64 fixes for 7.1, take #1

- Allow tracing for non-pKVM, which was accidentally disabled when
  the series was merged

- Rationalise the way the pKVM hypercall ranges are defined by using
  the same mechanism as already used for the vcpu_sysreg enum

- Enforce that SMCCC function numbers relayed by the pKVM proxy are
  actually compliant with the specification

- Fix a couple of feature to idreg mappings which resulted in the
  wrong sanitisation being applied

- Fix the GICD_IIDR revision number field that could never been
  written correctly by userspace

- Make kvm_vcpu_initialized() correctly use its parameter instead
  of relying on the surrounding context

- Enforce correct ordering in __pkvm_init_vcpu(), plugging a
  potential pin leak at the same time

- Move __pkvm_init_finalise() to a less dangerous spot, avoiding
  future problems

- Restore functional userspace irqchip support after a four year
  breakage (last functional kernel was 5.18...). This is obviously
  ripe for garbage collection.

- ... and the usual lot of spelling fixes
parents 1101baca 4ce98bf0
Loading
Loading
Loading
Loading
+18 −10
Original line number Diff line number Diff line
@@ -50,6 +50,9 @@

#include <linux/mm.h>

#define MARKER(m)				\
	m, __after_##m = m - 1

enum __kvm_host_smccc_func {
	/* Hypercalls that are unavailable once pKVM has finalised. */
	/* __KVM_HOST_SMCCC_FUNC___kvm_hyp_init */
@@ -59,8 +62,10 @@ enum __kvm_host_smccc_func {
	__KVM_HOST_SMCCC_FUNC___kvm_enable_ssbs,
	__KVM_HOST_SMCCC_FUNC___vgic_v3_init_lrs,
	__KVM_HOST_SMCCC_FUNC___vgic_v3_get_gic_config,

	MARKER(__KVM_HOST_SMCCC_FUNC_MIN_PKVM),

	__KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize,
	__KVM_HOST_SMCCC_FUNC_MIN_PKVM = __KVM_HOST_SMCCC_FUNC___pkvm_prot_finalize,

	/* Hypercalls that are always available and common to [nh]VHE/pKVM. */
	__KVM_HOST_SMCCC_FUNC___kvm_adjust_pc,
@@ -72,11 +77,20 @@ enum __kvm_host_smccc_func {
	__KVM_HOST_SMCCC_FUNC___kvm_tlb_flush_vmid_range,
	__KVM_HOST_SMCCC_FUNC___kvm_flush_cpu_context,
	__KVM_HOST_SMCCC_FUNC___kvm_timer_set_cntvoff,
	__KVM_HOST_SMCCC_FUNC___tracing_load,
	__KVM_HOST_SMCCC_FUNC___tracing_unload,
	__KVM_HOST_SMCCC_FUNC___tracing_enable,
	__KVM_HOST_SMCCC_FUNC___tracing_swap_reader,
	__KVM_HOST_SMCCC_FUNC___tracing_update_clock,
	__KVM_HOST_SMCCC_FUNC___tracing_reset,
	__KVM_HOST_SMCCC_FUNC___tracing_enable_event,
	__KVM_HOST_SMCCC_FUNC___tracing_write_event,
	__KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs,
	__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
	__KVM_HOST_SMCCC_FUNC___vgic_v5_save_apr,
	__KVM_HOST_SMCCC_FUNC___vgic_v5_restore_vmcr_apr,
	__KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM = __KVM_HOST_SMCCC_FUNC___vgic_v5_restore_vmcr_apr,

	MARKER(__KVM_HOST_SMCCC_FUNC_PKVM_ONLY),

	/* Hypercalls that are available only when pKVM has finalised. */
	__KVM_HOST_SMCCC_FUNC___pkvm_host_share_hyp,
@@ -100,14 +114,8 @@ enum __kvm_host_smccc_func {
	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_load,
	__KVM_HOST_SMCCC_FUNC___pkvm_vcpu_put,
	__KVM_HOST_SMCCC_FUNC___pkvm_tlb_flush_vmid,
	__KVM_HOST_SMCCC_FUNC___tracing_load,
	__KVM_HOST_SMCCC_FUNC___tracing_unload,
	__KVM_HOST_SMCCC_FUNC___tracing_enable,
	__KVM_HOST_SMCCC_FUNC___tracing_swap_reader,
	__KVM_HOST_SMCCC_FUNC___tracing_update_clock,
	__KVM_HOST_SMCCC_FUNC___tracing_reset,
	__KVM_HOST_SMCCC_FUNC___tracing_enable_event,
	__KVM_HOST_SMCCC_FUNC___tracing_write_event,

	MARKER(__KVM_HOST_SMCCC_FUNC_MAX)
};

#define DECLARE_KVM_VHE_SYM(sym)	extern char sym[]
+1 −4
Original line number Diff line number Diff line
@@ -450,9 +450,6 @@ struct kvm_vcpu_fault_info {
	r = __VNCR_START__ + ((VNCR_ ## r) / 8),	\
	__after_##r = __MAX__(__before_##r - 1, r)

#define MARKER(m)				\
	m, __after_##m = m - 1

enum vcpu_sysreg {
	__INVALID_SYSREG__,   /* 0 is reserved as an invalid value */
	MPIDR_EL1,	/* MultiProcessor Affinity Register */
@@ -1548,7 +1545,7 @@ static inline bool __vcpu_has_feature(const struct kvm_arch *ka, int feature)
#define kvm_vcpu_has_feature(k, f)	__vcpu_has_feature(&(k)->arch, (f))
#define vcpu_has_feature(v, f)	__vcpu_has_feature(&(v)->kvm->arch, (f))

#define kvm_vcpu_initialized(v) vcpu_get_flag(vcpu, VCPU_INITIALIZED)
#define kvm_vcpu_initialized(v) vcpu_get_flag(v, VCPU_INITIALIZED)

int kvm_trng_call(struct kvm_vcpu *vcpu);
#ifdef CONFIG_KVM
+4 −0
Original line number Diff line number Diff line
@@ -824,6 +824,10 @@ int kvm_arch_vcpu_runnable(struct kvm_vcpu *v)
{
	bool irq_lines = *vcpu_hcr(v) & (HCR_VI | HCR_VF | HCR_VSE);

	irq_lines |= (!irqchip_in_kernel(v->kvm) &&
		      (kvm_timer_should_notify_user(v) ||
		       kvm_pmu_should_notify_user(v)));

	return ((irq_lines || kvm_vgic_vcpu_pending_irq(v))
		&& !kvm_arm_vcpu_stopped(v) && !v->arch.pause);
}
+16 −7
Original line number Diff line number Diff line
@@ -131,7 +131,6 @@ struct reg_feat_map_desc {
	}

#define FEAT_SPE		ID_AA64DFR0_EL1, PMSVer, IMP
#define FEAT_SPE_FnE		ID_AA64DFR0_EL1, PMSVer, V1P2
#define FEAT_BRBE		ID_AA64DFR0_EL1, BRBE, IMP
#define FEAT_TRC_SR		ID_AA64DFR0_EL1, TraceVer, IMP
#define FEAT_PMUv3		ID_AA64DFR0_EL1, PMUVer, IMP
@@ -192,7 +191,7 @@ struct reg_feat_map_desc {
#define FEAT_SRMASK		ID_AA64MMFR4_EL1, SRMASK, IMP
#define FEAT_PoPS		ID_AA64MMFR4_EL1, PoPS, IMP
#define FEAT_PFAR		ID_AA64PFR1_EL1, PFAR, IMP
#define FEAT_Debugv8p9		ID_AA64DFR0_EL1, PMUVer, V3P9
#define FEAT_Debugv8p9		ID_AA64DFR0_EL1, DebugVer, V8P9
#define FEAT_PMUv3_SS		ID_AA64DFR0_EL1, PMSS, IMP
#define FEAT_SEBEP		ID_AA64DFR0_EL1, SEBEP, IMP
#define FEAT_EBEP		ID_AA64DFR1_EL1, EBEP, IMP
@@ -283,7 +282,7 @@ static bool feat_anerr(struct kvm *kvm)
static bool feat_sme_smps(struct kvm *kvm)
{
	/*
	 * Revists this if KVM ever supports SME -- this really should
	 * Revisit this if KVM ever supports SME -- this really should
	 * look at the guest's view of SMIDR_EL1. Funnily enough, this
	 * is not captured in the JSON file, but only as a note in the
	 * ARM ARM.
@@ -295,17 +294,27 @@ static bool feat_sme_smps(struct kvm *kvm)
static bool feat_spe_fds(struct kvm *kvm)
{
	/*
	 * Revists this if KVM ever supports SPE -- this really should
	 * Revisit this if KVM ever supports SPE -- this really should
	 * look at the guest's view of PMSIDR_EL1.
	 */
	return (kvm_has_feat(kvm, FEAT_SPEv1p4) &&
		(read_sysreg_s(SYS_PMSIDR_EL1) & PMSIDR_EL1_FDS));
}

static bool feat_spe_fne(struct kvm *kvm)
{
	/*
	 * Revisit this if KVM ever supports SPE -- this really should
	 * look at the guest's view of PMSIDR_EL1.
	 */
	return (kvm_has_feat(kvm, FEAT_SPEv1p2) &&
		(read_sysreg_s(SYS_PMSIDR_EL1) & PMSIDR_EL1_FnE));
}

static bool feat_trbe_mpam(struct kvm *kvm)
{
	/*
	 * Revists this if KVM ever supports both MPAM and TRBE --
	 * Revisit this if KVM ever supports both MPAM and TRBE --
	 * this really should look at the guest's view of TRBIDR_EL1.
	 */
	return (kvm_has_feat(kvm, FEAT_TRBE) &&
@@ -537,7 +546,7 @@ static const struct reg_bits_to_feat_map hdfgrtr_feat_map[] = {
		   HDFGRTR_EL2_PMBPTR_EL1	|
		   HDFGRTR_EL2_PMBLIMITR_EL1,
		   FEAT_SPE),
	NEEDS_FEAT(HDFGRTR_EL2_nPMSNEVFR_EL1, FEAT_SPE_FnE),
	NEEDS_FEAT(HDFGRTR_EL2_nPMSNEVFR_EL1, feat_spe_fne),
	NEEDS_FEAT(HDFGRTR_EL2_nBRBDATA		|
		   HDFGRTR_EL2_nBRBCTL		|
		   HDFGRTR_EL2_nBRBIDR,
@@ -605,7 +614,7 @@ static const struct reg_bits_to_feat_map hdfgwtr_feat_map[] = {
		   HDFGWTR_EL2_PMBPTR_EL1	|
		   HDFGWTR_EL2_PMBLIMITR_EL1,
		   FEAT_SPE),
	NEEDS_FEAT(HDFGWTR_EL2_nPMSNEVFR_EL1, FEAT_SPE_FnE),
	NEEDS_FEAT(HDFGWTR_EL2_nPMSNEVFR_EL1, feat_spe_fne),
	NEEDS_FEAT(HDFGWTR_EL2_nBRBDATA		|
		   HDFGWTR_EL2_nBRBCTL,
		   FEAT_BRBE),
+17 −13
Original line number Diff line number Diff line
@@ -709,6 +709,14 @@ static const hcall_t host_hcall[] = {
	HANDLE_FUNC(__kvm_tlb_flush_vmid_range),
	HANDLE_FUNC(__kvm_flush_cpu_context),
	HANDLE_FUNC(__kvm_timer_set_cntvoff),
	HANDLE_FUNC(__tracing_load),
	HANDLE_FUNC(__tracing_unload),
	HANDLE_FUNC(__tracing_enable),
	HANDLE_FUNC(__tracing_swap_reader),
	HANDLE_FUNC(__tracing_update_clock),
	HANDLE_FUNC(__tracing_reset),
	HANDLE_FUNC(__tracing_enable_event),
	HANDLE_FUNC(__tracing_write_event),
	HANDLE_FUNC(__vgic_v3_save_aprs),
	HANDLE_FUNC(__vgic_v3_restore_vmcr_aprs),
	HANDLE_FUNC(__vgic_v5_save_apr),
@@ -735,22 +743,16 @@ static const hcall_t host_hcall[] = {
	HANDLE_FUNC(__pkvm_vcpu_load),
	HANDLE_FUNC(__pkvm_vcpu_put),
	HANDLE_FUNC(__pkvm_tlb_flush_vmid),
	HANDLE_FUNC(__tracing_load),
	HANDLE_FUNC(__tracing_unload),
	HANDLE_FUNC(__tracing_enable),
	HANDLE_FUNC(__tracing_swap_reader),
	HANDLE_FUNC(__tracing_update_clock),
	HANDLE_FUNC(__tracing_reset),
	HANDLE_FUNC(__tracing_enable_event),
	HANDLE_FUNC(__tracing_write_event),
};

static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
{
	DECLARE_REG(unsigned long, id, host_ctxt, 0);
	unsigned long hcall_min = 0, hcall_max = -1;
	unsigned long hcall_min = 0, hcall_max = __KVM_HOST_SMCCC_FUNC_MAX;
	hcall_t hfn;

	BUILD_BUG_ON(ARRAY_SIZE(host_hcall) != __KVM_HOST_SMCCC_FUNC_MAX);

	/*
	 * If pKVM has been initialised then reject any calls to the
	 * early "privileged" hypercalls. Note that we cannot reject
@@ -763,16 +765,14 @@ static void handle_host_hcall(struct kvm_cpu_context *host_ctxt)
	if (static_branch_unlikely(&kvm_protected_mode_initialized)) {
		hcall_min = __KVM_HOST_SMCCC_FUNC_MIN_PKVM;
	} else {
		hcall_max = __KVM_HOST_SMCCC_FUNC_MAX_NO_PKVM;
		hcall_max = __KVM_HOST_SMCCC_FUNC_PKVM_ONLY;
	}

	id &= ~ARM_SMCCC_CALL_HINTS;
	id -= KVM_HOST_SMCCC_ID(0);

	if (unlikely(id < hcall_min || id > hcall_max ||
		     id >= ARRAY_SIZE(host_hcall))) {
	if (unlikely(id < hcall_min || id >= hcall_max))
		goto inval;
	}

	hfn = host_hcall[id];
	if (unlikely(!hfn))
@@ -805,6 +805,10 @@ static void handle_host_smc(struct kvm_cpu_context *host_ctxt)
	}

	func_id &= ~ARM_SMCCC_CALL_HINTS;
	if (upper_32_bits(func_id)) {
		cpu_reg(host_ctxt, 0) = SMCCC_RET_NOT_SUPPORTED;
		goto exit_skip_instr;
	}

	handled = kvm_host_psci_handler(host_ctxt, func_id);
	if (!handled)
Loading