Commit ba88649d authored by Marc Zyngier's avatar Marc Zyngier Committed by chenxiang
Browse files

KVM: arm64: vgic-v3: Add userspace selection for GICv3.3 NMI

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

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/commit/?h=arm64/nmi&id=ce431bbdd68bd0f445c88f59fb11e3a16a6e1526



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

In order to allow the GIC NMI support to be selected from userspace,
add userspace access to GICD_TYPER, which allows the NMI support bit
to be set.

This is gated by a global capability that nobody can set yet, so
no observable change is expected. Again.

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
Signed-off-by: default avatarXiang Chen <chenxiang66@hisilicon.com>
Signed-off-by: default avatarcaijian <caijian11@h-partners.com>
parent 620365f7
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -353,8 +353,16 @@ int vgic_init(struct kvm *kvm)
	 * If userspace didn't set the GIC implementation revision,
	 * default to the latest and greatest. You know want it.
	 */
	if (!dist->implementation_rev)
	if (!dist->implementation_rev) {
		dist->implementation_rev = KVM_VGIC_IMP_REV_LATEST;
		/*
		 * Advertise NMI if available. Userspace that explicitly
		 * doesn't want NMI will have written to GICD_{IIDR,TYPER}
		 * to set the implementation and the NMI support status.
		 */
		dist->has_nmi = kvm_vgic_global_state.has_nmi;
	}

	dist->initialized = true;

out:
+1 −0
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ static int vgic_mmio_uaccess_write_v2_misc(struct kvm_vcpu *vcpu,
		switch (reg) {
		case KVM_VGIC_IMP_REV_2:
		case KVM_VGIC_IMP_REV_3:
		case KVM_VGIC_IMP_REV_4:
			vcpu->kvm->arch.vgic.v2_groups_user_writable = true;
			dist->implementation_rev = reg;
			return 0;
+14 −1
Original line number Diff line number Diff line
@@ -78,6 +78,8 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
	case GICD_TYPER:
		value = vgic->nr_spis + VGIC_NR_PRIVATE_IRQS;
		value = (value >> 5) - 1;
		if (vgic->has_nmi)
			value |= GICD_TYPER_NMI;
		if (vgic_has_its(vcpu->kvm)) {
			value |= (INTERRUPT_ID_BITS_ITS - 1) << 19;
			value |= GICD_TYPER_LPIS;
@@ -158,6 +160,13 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
	u32 reg;

	switch (addr & 0x0c) {
	case GICD_TYPER:
		if (dist->implementation_rev >= KVM_VGIC_IMP_REV_4 &&
		    kvm_vgic_global_state.has_nmi)
			dist->has_nmi = val & GICD_TYPER_NMI;
		else if (val & GICD_TYPER_NMI)
			return -EINVAL;
		return 0;
	case GICD_TYPER2:
		if (val != vgic_mmio_read_v3_misc(vcpu, addr, len))
			return -EINVAL;
@@ -171,6 +180,10 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
		switch (reg) {
		case KVM_VGIC_IMP_REV_2:
		case KVM_VGIC_IMP_REV_3:
			/* Disable NMI on selecting an older revision */
			dist->has_nmi = false;
			fallthrough;
		case KVM_VGIC_IMP_REV_4:
			dist->implementation_rev = reg;
			return 0;
		default:
@@ -186,7 +199,7 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
		return 0;
	}

	vgic_mmio_write_v3_misc(vcpu, addr, len, val);
	/* Not reachable... */
	return 0;
}

+5 −1
Original line number Diff line number Diff line
@@ -108,6 +108,9 @@ struct vgic_global {
	bool			has_gicv4;
	bool			has_gicv4_1;

	/* NMI */
	bool			has_nmi;

	/* Pseudo GICv3 from outer space */
	bool			no_hw_deactivation;

@@ -288,7 +291,8 @@ struct vgic_dist {
	u32			implementation_rev;
#define KVM_VGIC_IMP_REV_2	2 /* GICv2 restorable groups */
#define KVM_VGIC_IMP_REV_3	3 /* GICv3 GICR_CTLR.{IW,CES,RWP} */
#define KVM_VGIC_IMP_REV_LATEST	KVM_VGIC_IMP_REV_3
#define KVM_VGIC_IMP_REV_4	4 /* GICv3 NMI */
#define KVM_VGIC_IMP_REV_LATEST	KVM_VGIC_IMP_REV_4

	/* Userspace can write to GICv2 IGROUPR */
	bool			v2_groups_user_writable;