Commit 08344cd9 authored by Zenghui Yu's avatar Zenghui Yu Committed by Dongxu Sun
Browse files

KVM: arm64: arch_timer: Make vtimer_irqbypass a Distributor attr

virt inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/I8K89F


CVE: NA

------------------------------------------------------------------

Having the vtimer_irqbypass flag in the per-vcpu structure is actually
pointless, as we will keep the vtimer interrupt delivery capability the
same among all vcpus (either direct injection via MBIGEN-ITS-RDist, or
purely emulated by KVM).

Let's instead make it a Distributor attribute. This way, we configure the
vtimer information for *all* vcpus in kvm_vtimer_config(), in one go.
Otherwise we need to configure it for each vcpu in its first run (we may
end-up missing the activation of vtimer interrupt for some vcpus whose
vtimer_info hasn't been configures yet, and bad things will happen...).

Signed-off-by: default avatarZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: default avatarKunkun Jiang <jiangkunkun@huawei.com>
Signed-off-by: default avatarDongxu Sun <sundongxu3@huawei.com>
parent 3ad7c505
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -90,7 +90,7 @@ static inline void vcpu_clear_wfx_traps(struct kvm_vcpu *vcpu)
{
	vcpu->arch.hcr_el2 &= ~HCR_TWE;
	if (atomic_read(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe.vlpi_count) ||
	    vcpu->arch.vgic_cpu.vtimer_irqbypass ||
	    vcpu->kvm->arch.vgic.vtimer_irqbypass ||
	    vcpu->kvm->arch.vgic.nassgireq)
		vcpu->arch.hcr_el2 &= ~HCR_TWI;
	else
+29 −11
Original line number Diff line number Diff line
@@ -1283,24 +1283,42 @@ static bool vtimer_get_active_stat(struct kvm_vcpu *vcpu, int vintid)
		return vtimer_mbigen_get_active(vcpu->cpu);
}

int kvm_vtimer_config(struct kvm_vcpu *vcpu)
int kvm_vtimer_config(struct kvm *kvm)
{
	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
	int intid;
	struct vgic_dist *dist = &kvm->arch.vgic;
	struct kvm_vcpu *vcpu;
	int ret = 0;
	int c;

	if (!vtimer_is_irqbypass())
		return 0;

	if (timer->enabled)
		return 0;

	if (!irqchip_in_kernel(vcpu->kvm))
	if (!irqchip_in_kernel(kvm))
		return -EINVAL;

	mutex_lock(&kvm->lock);
	if (dist->vtimer_irqbypass)
		goto out;

	kvm_for_each_vcpu(c, vcpu, kvm) {
		struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
		int intid;

		WARN_ON(timer->enabled);

		intid = vcpu_vtimer(vcpu)->irq.irq;
	return kvm_vgic_config_vtimer_irqbypass(vcpu, intid,
		ret = kvm_vgic_config_vtimer_irqbypass(vcpu, intid,
						       vtimer_get_active_stat,
						       vtimer_set_active_stat);
		if (ret)
			goto out;
	}

	dist->vtimer_irqbypass = true;

out:
	mutex_unlock(&kvm->lock);
	return ret;
}

int kvm_timer_enable(struct kvm_vcpu *vcpu)
+1 −1
Original line number Diff line number Diff line
@@ -639,7 +639,7 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)

	kvm_arm_vcpu_init_debug(vcpu);

	ret = kvm_vtimer_config(vcpu);
	ret = kvm_vtimer_config(kvm);
	if (ret)
		return ret;

+4 −3
Original line number Diff line number Diff line
@@ -212,9 +212,6 @@ static void vgic_v4_enable_vtimer(struct kvm_vcpu *vcpu)
	struct irq_desc *desc;
	int ret;

	if (!vgic_cpu->vtimer_irqbypass)
		return;

	irq = vgic_get_irq(vcpu->kvm, vcpu, vtimer->intid);
	irq->host_irq = irq_find_mapping(vpe->sgi_domain, vtimer->intid);

@@ -242,9 +239,13 @@ static void vgic_v4_enable_vtimer(struct kvm_vcpu *vcpu)
/* Must be called with the kvm lock held */
void vgic_v4_configure_vtimer(struct kvm *kvm)
{
	struct vgic_dist *dist = &kvm->arch.vgic;
	struct kvm_vcpu *vcpu;
	int i;

	if (!dist->vtimer_irqbypass)
		return;

	kvm_for_each_vcpu(i, vcpu, kvm)
		vgic_v4_enable_vtimer(vcpu);
}
+0 −2
Original line number Diff line number Diff line
@@ -585,8 +585,6 @@ int kvm_vgic_config_vtimer_irqbypass(struct kvm_vcpu *vcpu, u32 vintid,
	if (WARN_ON_ONCE(!irq || !kvm_vgic_vtimer_irqbypass_support()))
		return -EINVAL;

	vgic_cpu->vtimer_irqbypass = true;

	vtimer->intid = vintid;
	vtimer->get_active_stat = get_as;
	vtimer->set_active_stat = set_as;
Loading