Commit 938309b0 authored by Oliver Upton's avatar Oliver Upton
Browse files

Merge branch 'kvm-arm64/vgic-lr-overflow' into kvmarm/next



* kvm-arm64/vgic-lr-overflow: (50 commits)
  : Support for VGIC LR overflows, courtesy of Marc Zyngier
  :
  : Address deficiencies in KVM's GIC emulation when a vCPU has more active
  : IRQs than can be represented in the VGIC list registers. Sort the AP
  : list to prioritize inactive and pending IRQs, potentially spilling
  : active IRQs outside of the LRs.
  :
  : Handle deactivation of IRQs outside of the LRs for both EOImode=0/1,
  : which involves special consideration for SPIs being deactivated from a
  : different vCPU than the one that acked it.
  KVM: arm64: Convert ICH_HCR_EL2_TDIR cap to EARLY_LOCAL_CPU_FEATURE
  KVM: arm64: selftests: vgic_irq: Add timer deactivation test
  KVM: arm64: selftests: vgic_irq: Add Group-0 enable test
  KVM: arm64: selftests: vgic_irq: Add asymmetric SPI deaectivation test
  KVM: arm64: selftests: vgic_irq: Perform EOImode==1 deactivation in ack order
  KVM: arm64: selftests: vgic_irq: Remove LR-bound limitation
  KVM: arm64: selftests: vgic_irq: Exclude timer-controlled interrupts
  KVM: arm64: selftests: vgic_irq: Change configuration before enabling interrupt
  KVM: arm64: selftests: vgic_irq: Fix GUEST_ASSERT_IAR_EMPTY() helper
  KVM: arm64: selftests: gic_v3: Disable Group-0 interrupts by default
  KVM: arm64: selftests: gic_v3: Add irq group setting helper
  KVM: arm64: GICv2: Always trap GICV_DIR register
  KVM: arm64: GICv2: Handle deactivation via GICV_DIR traps
  KVM: arm64: GICv2: Handle LR overflow when EOImode==0
  KVM: arm64: GICv3: Force exit to sync ICH_HCR_EL2.En
  KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive
  KVM: arm64: GICv3: nv: Resync LRs/VMCR/HCR early for better MI emulation
  KVM: arm64: GICv3: Avoid broadcast kick on CPUs lacking TDIR
  KVM: arm64: GICv3: Handle in-LR deactivation when possible
  KVM: arm64: GICv3: Add SPI tracking to handle asymmetric deactivation
  ...

Signed-off-by: default avatarOliver Upton <oupton@kernel.org>
parents 11b8e6ed 64d67e7a
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -79,7 +79,7 @@ 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___vgic_v3_save_vmcr_aprs,
	__KVM_HOST_SMCCC_FUNC___vgic_v3_save_aprs,
	__KVM_HOST_SMCCC_FUNC___vgic_v3_restore_vmcr_aprs,
	__KVM_HOST_SMCCC_FUNC___pkvm_reserve_vm,
	__KVM_HOST_SMCCC_FUNC___pkvm_unreserve_vm,
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@
#define KVM_REQ_NESTED_S2_UNMAP		KVM_ARCH_REQ(8)
#define KVM_REQ_GUEST_HYP_IRQ_PENDING	KVM_ARCH_REQ(9)
#define KVM_REQ_MAP_L1_VNCR_EL2		KVM_ARCH_REQ(10)
#define KVM_REQ_VGIC_PROCESS_UPDATE	KVM_ARCH_REQ(11)

#define KVM_DIRTY_LOG_MANUAL_CAPS   (KVM_DIRTY_LOG_MANUAL_PROTECT_ENABLE | \
				     KVM_DIRTY_LOG_INITIALLY_SET)
+2 −1
Original line number Diff line number Diff line
@@ -77,12 +77,13 @@ DECLARE_PER_CPU(struct kvm_nvhe_init_params, kvm_init_params);
int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);

u64 __gic_v3_get_lr(unsigned int lr);
void __gic_v3_set_lr(u64 val, int lr);

void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if);
void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if);
void __vgic_v3_activate_traps(struct vgic_v3_cpu_if *cpu_if);
void __vgic_v3_deactivate_traps(struct vgic_v3_cpu_if *cpu_if);
void __vgic_v3_save_vmcr_aprs(struct vgic_v3_cpu_if *cpu_if);
void __vgic_v3_save_aprs(struct vgic_v3_cpu_if *cpu_if);
void __vgic_v3_restore_vmcr_aprs(struct vgic_v3_cpu_if *cpu_if);
int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);

+6 −1
Original line number Diff line number Diff line
@@ -40,8 +40,13 @@
 */
#define HVC_FINALISE_EL2	3

/*
 * HVC_GET_ICH_VTR_EL2 - Retrieve the ICH_VTR_EL2 value
 */
#define HVC_GET_ICH_VTR_EL2	4

/* Max number of HYP stub hypercalls */
#define HVC_STUB_HCALL_NR 4
#define HVC_STUB_HCALL_NR 5

/* Error returned when an invalid stub number is passed into x0 */
#define HVC_STUB_ERR	0xbadca11
+52 −0
Original line number Diff line number Diff line
@@ -2303,6 +2303,49 @@ static bool has_gic_prio_relaxed_sync(const struct arm64_cpu_capabilities *entry
}
#endif

static bool can_trap_icv_dir_el1(const struct arm64_cpu_capabilities *entry,
				 int scope)
{
	static const struct midr_range has_vgic_v3[] = {
		MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_PRO),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_PRO),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M1_ICESTORM_MAX),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M1_FIRESTORM_MAX),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_PRO),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_PRO),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M2_BLIZZARD_MAX),
		MIDR_ALL_VERSIONS(MIDR_APPLE_M2_AVALANCHE_MAX),
		{},
	};
	struct arm_smccc_res res = {};

	BUILD_BUG_ON(ARM64_HAS_ICH_HCR_EL2_TDIR <= ARM64_HAS_GICV3_CPUIF);
	BUILD_BUG_ON(ARM64_HAS_ICH_HCR_EL2_TDIR <= ARM64_HAS_GICV5_LEGACY);
	if (!this_cpu_has_cap(ARM64_HAS_GICV3_CPUIF) &&
	    !is_midr_in_range_list(has_vgic_v3))
		return false;

	if (!is_hyp_mode_available())
		return false;

	if (this_cpu_has_cap(ARM64_HAS_GICV5_LEGACY))
		return true;

	if (is_kernel_in_hyp_mode())
		res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2);
	else
		arm_smccc_1_1_hvc(HVC_GET_ICH_VTR_EL2, &res);

	if (res.a0 == HVC_STUB_ERR)
		return false;

	return res.a1 & ICH_VTR_EL2_TDS;
}

#ifdef CONFIG_ARM64_BTI
static void bti_enable(const struct arm64_cpu_capabilities *__unused)
{
@@ -2814,6 +2857,15 @@ static const struct arm64_cpu_capabilities arm64_features[] = {
		.matches = has_gic_prio_relaxed_sync,
	},
#endif
	{
		/*
		 * Depends on having GICv3
		 */
		.desc = "ICV_DIR_EL1 trapping",
		.capability = ARM64_HAS_ICH_HCR_EL2_TDIR,
		.type = ARM64_CPUCAP_EARLY_LOCAL_CPU_FEATURE,
		.matches = can_trap_icv_dir_el1,
	},
#ifdef CONFIG_ARM64_E0PD
	{
		.desc = "E0PD",
Loading