Commit 19339c51 authored by Shenming Lu's avatar Shenming Lu Committed by Zheng Zengkai
Browse files

KVM: arm64: Delay the polling of the GICR_VPENDBASER.Dirty bit

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


CVE: NA

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

In order to reduce the impact of the VPT parsing happening on the GIC,
we can split the vcpu reseidency in two phases:

- programming GICR_VPENDBASER: this still happens in vcpu_load()
- checking for the VPT parsing to be complete: this can happen
  on vcpu entry (in kvm_vgic_flush_hwstate())

This allows the GIC and the CPU to work in parallel, rewmoving some
of the entry overhead.

Suggested-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarShenming Lu <lushenming@huawei.com>
Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20201128141857.983-3-lushenming@huawei.com


Reviewed-by: default avatarKeqian Zhu <zhukeqian1@huawei.com>
Signed-off-by: default avatarZheng Zengkai <zhengzengkai@huawei.com>
parent 9c8b91e8
Loading
Loading
Loading
Loading
+12 −0
Original line number Diff line number Diff line
@@ -353,6 +353,18 @@ int vgic_v4_load(struct kvm_vcpu *vcpu)
	return err;
}

void vgic_v4_commit(struct kvm_vcpu *vcpu)
{
	struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;

	/*
	 * No need to wait for the vPE to be ready across a shallow guest
	 * exit, as only a vcpu_put will invalidate it.
	 */
	if (!vpe->ready)
		its_commit_vpe(vpe);
}

static struct vgic_its *vgic_get_its(struct kvm *kvm,
				     struct kvm_kernel_irq_routing_entry *irq_entry)
{
+3 −0
Original line number Diff line number Diff line
@@ -915,6 +915,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)

	if (can_access_vgic_from_kernel())
		vgic_restore_state(vcpu);

	if (vgic_supports_direct_msis(vcpu->kvm))
		vgic_v4_commit(vcpu);
}

void kvm_vgic_load(struct kvm_vcpu *vcpu)
+8 −4
Original line number Diff line number Diff line
@@ -3841,8 +3841,6 @@ static void its_vpe_schedule(struct its_vpe *vpe)
	val |= vpe->idai ? GICR_VPENDBASER_IDAI : 0;
	val |= GICR_VPENDBASER_Valid;
	gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);

	its_wait_vpt_parse_complete();
}

static void its_vpe_deschedule(struct its_vpe *vpe)
@@ -3890,6 +3888,10 @@ static int its_vpe_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
		its_vpe_deschedule(vpe);
		return 0;

	case COMMIT_VPE:
		its_wait_vpt_parse_complete();
		return 0;

	case INVALL_VPE:
		its_vpe_invall(vpe);
		return 0;
@@ -4051,8 +4053,6 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe,
	val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id);

	gicr_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);

	its_wait_vpt_parse_complete();
}

static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
@@ -4127,6 +4127,10 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
		its_vpe_4_1_deschedule(vpe, info);
		return 0;

	case COMMIT_VPE:
		its_wait_vpt_parse_complete();
		return 0;

	case INVALL_VPE:
		its_vpe_4_1_invall(vpe);
		return 0;
+19 −0
Original line number Diff line number Diff line
@@ -232,6 +232,8 @@ int its_make_vpe_non_resident(struct its_vpe *vpe, bool db)
	if (!ret)
		vpe->resident = false;

	vpe->ready = false;

	return ret;
}

@@ -258,6 +260,23 @@ int its_make_vpe_resident(struct its_vpe *vpe, bool g0en, bool g1en)
	return ret;
}

int its_commit_vpe(struct its_vpe *vpe)
{
	struct its_cmd_info info = {
		.cmd_type = COMMIT_VPE,
	};
	int ret;

	WARN_ON(preemptible());

	ret = its_send_vpe_cmd(vpe, &info);
	if (!ret)
		vpe->ready = true;

	return ret;
}


int its_invall_vpe(struct its_vpe *vpe)
{
	struct its_cmd_info info = {
+1 −0
Original line number Diff line number Diff line
@@ -402,6 +402,7 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
				 struct kvm_kernel_irq_routing_entry *irq_entry);

int vgic_v4_load(struct kvm_vcpu *vcpu);
void vgic_v4_commit(struct kvm_vcpu *vcpu);
int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db);

#endif /* __KVM_ARM_VGIC_H */
Loading