Commit 6e827fa2 authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvmarm-fixes-7.0-3' of...

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

KVM/arm64 fixes for 7.0, take #3

- Correctly handle deeactivation of out-of-LRs interrupts by
  starting the EOIcount deactivation walk *after* the last irq
  that made it into an LR. This avoids deactivating irqs that
  are in the LRs and that the vcpu hasn't deactivated yet.

- Avoid calling into the stubs to probe for ICH_VTR_EL2.TDS when
  pKVM is already enabled -- not only thhis isn't possible (pKVM
  will reject the call), but it is also useless: this can only
  happen for a CPU that has already booted once, and the capability
  will not change.
parents 94fe3e65 a79f7b4a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -784,6 +784,9 @@ struct kvm_host_data {
	/* Number of debug breakpoints/watchpoints for this CPU (minus 1) */
	unsigned int debug_brps;
	unsigned int debug_wrps;

	/* Last vgic_irq part of the AP list recorded in an LR */
	struct vgic_irq *last_lr_irq;
};

struct kvm_host_psci_config {
+9 −0
Original line number Diff line number Diff line
@@ -2345,6 +2345,15 @@ static bool can_trap_icv_dir_el1(const struct arm64_cpu_capabilities *entry,
	    !is_midr_in_range_list(has_vgic_v3))
		return false;

	/*
	 * pKVM prevents late onlining of CPUs. This means that whatever
	 * state the capability is in after deprivilege cannot be affected
	 * by a new CPU booting -- this is garanteed to be a CPU we have
	 * already seen, and the cap is therefore unchanged.
	 */
	if (system_capabilities_finalized() && is_protected_kvm_enabled())
		return cpus_have_final_cap(ARM64_HAS_ICH_HCR_EL2_TDIR);

	if (is_kernel_in_hyp_mode())
		res.a1 = read_sysreg_s(SYS_ICH_VTR_EL2);
	else
+2 −2
Original line number Diff line number Diff line
@@ -115,7 +115,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
	struct vgic_v2_cpu_if *cpuif = &vgic_cpu->vgic_v2;
	u32 eoicount = FIELD_GET(GICH_HCR_EOICOUNT, cpuif->vgic_hcr);
	struct vgic_irq *irq;
	struct vgic_irq *irq = *host_data_ptr(last_lr_irq);

	DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());

@@ -123,7 +123,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
		vgic_v2_fold_lr(vcpu, cpuif->vgic_lr[lr]);

	/* See the GICv3 equivalent for the EOIcount handling rationale */
	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
	list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
		u32 lr;

		if (!eoicount) {
+6 −6
Original line number Diff line number Diff line
@@ -148,7 +148,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
	struct vgic_v3_cpu_if *cpuif = &vgic_cpu->vgic_v3;
	u32 eoicount = FIELD_GET(ICH_HCR_EL2_EOIcount, cpuif->vgic_hcr);
	struct vgic_irq *irq;
	struct vgic_irq *irq = *host_data_ptr(last_lr_irq);

	DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());

@@ -158,12 +158,12 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
	/*
	 * EOIMode=0: use EOIcount to emulate deactivation. We are
	 * guaranteed to deactivate in reverse order of the activation, so
	 * just pick one active interrupt after the other in the ap_list,
	 * and replay the deactivation as if the CPU was doing it. We also
	 * rely on priority drop to have taken place, and the list to be
	 * sorted by priority.
	 * just pick one active interrupt after the other in the tail part
	 * of the ap_list, past the LRs, and replay the deactivation as if
	 * the CPU was doing it. We also rely on priority drop to have taken
	 * place, and the list to be sorted by priority.
	 */
	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
	list_for_each_entry_continue(irq, &vgic_cpu->ap_list_head, ap_list) {
		u64 lr;

		/*
+6 −0
Original line number Diff line number Diff line
@@ -814,6 +814,9 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)

static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
{
	if (!*host_data_ptr(last_lr_irq))
		return;

	if (kvm_vgic_global_state.type == VGIC_V2)
		vgic_v2_fold_lr_state(vcpu);
	else
@@ -960,10 +963,13 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
	if (irqs_outside_lrs(&als))
		vgic_sort_ap_list(vcpu);

	*host_data_ptr(last_lr_irq) = NULL;

	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
		scoped_guard(raw_spinlock,  &irq->irq_lock) {
			if (likely(vgic_target_oracle(irq) == vcpu)) {
				vgic_populate_lr(vcpu, irq, count++);
				*host_data_ptr(last_lr_irq) = irq;
			}
		}