Commit 47e89feb authored by Marc Zyngier's avatar Marc Zyngier
Browse files

Merge branch kvm-arm64/gicv5-prologue into kvmarm-master/next



* kvm-arm64/gicv5-prologue:
  : .
  : Prologue to GICv5 support, courtesy of Sascha Bischoff.
  :
  : This is preliminary work that sets the scene for the full-blow
  : support.
  : .
  irqchip/gic-v5: Check if impl is virt capable
  KVM: arm64: gic: Set vgic_model before initing private IRQs
  arm64/sysreg: Drop ICH_HFGRTR_EL2.ICC_HAPR_EL1 and make RES1
  KVM: arm64: gic-v3: Switch vGIC-v3 to use generated ICH_VMCR_EL2

Signed-off-by: default avatarMarc Zyngier <maz@kernel.org>
parents 1c880ea3 3227c3a8
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -235,7 +235,6 @@
		     ICH_HFGRTR_EL2_ICC_ICSR_EL1		| \
		     ICH_HFGRTR_EL2_ICC_PCR_EL1			| \
		     ICH_HFGRTR_EL2_ICC_HPPIR_EL1		| \
		     ICH_HFGRTR_EL2_ICC_HAPR_EL1		| \
		     ICH_HFGRTR_EL2_ICC_CR0_EL1			| \
		     ICH_HFGRTR_EL2_ICC_IDRn_EL1		| \
		     ICH_HFGRTR_EL2_ICC_APR_EL1)
+0 −21
Original line number Diff line number Diff line
@@ -560,7 +560,6 @@
#define SYS_ICC_SRE_EL2			sys_reg(3, 4, 12, 9, 5)
#define SYS_ICH_EISR_EL2		sys_reg(3, 4, 12, 11, 3)
#define SYS_ICH_ELRSR_EL2		sys_reg(3, 4, 12, 11, 5)
#define SYS_ICH_VMCR_EL2		sys_reg(3, 4, 12, 11, 7)

#define __SYS__LR0_EL2(x)		sys_reg(3, 4, 12, 12, x)
#define SYS_ICH_LR0_EL2			__SYS__LR0_EL2(0)
@@ -988,26 +987,6 @@
#define ICH_LR_PRIORITY_SHIFT	48
#define ICH_LR_PRIORITY_MASK	(0xffULL << ICH_LR_PRIORITY_SHIFT)

/* ICH_VMCR_EL2 bit definitions */
#define ICH_VMCR_ACK_CTL_SHIFT	2
#define ICH_VMCR_ACK_CTL_MASK	(1 << ICH_VMCR_ACK_CTL_SHIFT)
#define ICH_VMCR_FIQ_EN_SHIFT	3
#define ICH_VMCR_FIQ_EN_MASK	(1 << ICH_VMCR_FIQ_EN_SHIFT)
#define ICH_VMCR_CBPR_SHIFT	4
#define ICH_VMCR_CBPR_MASK	(1 << ICH_VMCR_CBPR_SHIFT)
#define ICH_VMCR_EOIM_SHIFT	9
#define ICH_VMCR_EOIM_MASK	(1 << ICH_VMCR_EOIM_SHIFT)
#define ICH_VMCR_BPR1_SHIFT	18
#define ICH_VMCR_BPR1_MASK	(7 << ICH_VMCR_BPR1_SHIFT)
#define ICH_VMCR_BPR0_SHIFT	21
#define ICH_VMCR_BPR0_MASK	(7 << ICH_VMCR_BPR0_SHIFT)
#define ICH_VMCR_PMR_SHIFT	24
#define ICH_VMCR_PMR_MASK	(0xffUL << ICH_VMCR_PMR_SHIFT)
#define ICH_VMCR_ENG0_SHIFT	0
#define ICH_VMCR_ENG0_MASK	(1 << ICH_VMCR_ENG0_SHIFT)
#define ICH_VMCR_ENG1_SHIFT	1
#define ICH_VMCR_ENG1_MASK	(1 << ICH_VMCR_ENG1_SHIFT)

/*
 * Permission Indirection Extension (PIE) permission encodings.
 * Encodings with the _O suffix, have overlays applied (Permission Overlay Extension).
+25 −44
Original line number Diff line number Diff line
@@ -569,11 +569,11 @@ static int __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu, u32 vmcr,
			continue;

		/* Group-0 interrupt, but Group-0 disabled? */
		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_EL2_VENG0_MASK))
			continue;

		/* Group-1 interrupt, but Group-1 disabled? */
		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_EL2_VENG1_MASK))
			continue;

		/* Not the highest priority? */
@@ -646,19 +646,19 @@ static int __vgic_v3_get_highest_active_priority(void)

static unsigned int __vgic_v3_get_bpr0(u32 vmcr)
{
	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
	return FIELD_GET(ICH_VMCR_EL2_VBPR0, vmcr);
}

static unsigned int __vgic_v3_get_bpr1(u32 vmcr)
{
	unsigned int bpr;

	if (vmcr & ICH_VMCR_CBPR_MASK) {
	if (vmcr & ICH_VMCR_EL2_VCBPR_MASK) {
		bpr = __vgic_v3_get_bpr0(vmcr);
		if (bpr < 7)
			bpr++;
	} else {
		bpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
		bpr = FIELD_GET(ICH_VMCR_EL2_VBPR1, vmcr);
	}

	return bpr;
@@ -758,7 +758,7 @@ static void __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	if (grp != !!(lr_val & ICH_LR_GROUP))
		goto spurious;

	pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
	pmr = FIELD_GET(ICH_VMCR_EL2_VPMR, vmcr);
	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
	if (pmr <= lr_prio)
		goto spurious;
@@ -806,7 +806,7 @@ static int ___vgic_v3_write_dir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	int lr;

	/* EOImode == 0, nothing to be done here */
	if (!(vmcr & ICH_VMCR_EOIM_MASK))
	if (!(vmcr & ICH_VMCR_EL2_VEOIM_MASK))
		return 1;

	/* No deactivate to be performed on an LPI */
@@ -849,7 +849,7 @@ static void __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	}

	/* EOImode == 1 and not an LPI, nothing to be done here */
	if ((vmcr & ICH_VMCR_EOIM_MASK) && !(vid >= VGIC_MIN_LPI))
	if ((vmcr & ICH_VMCR_EL2_VEOIM_MASK) && !(vid >= VGIC_MIN_LPI))
		return;

	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
@@ -865,22 +865,19 @@ static void __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)

static void __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK));
	vcpu_set_reg(vcpu, rt, FIELD_GET(ICH_VMCR_EL2_VENG0, vmcr));
}

static void __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
	vcpu_set_reg(vcpu, rt, FIELD_GET(ICH_VMCR_EL2_VENG1, vmcr));
}

static void __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	u64 val = vcpu_get_reg(vcpu, rt);

	if (val & 1)
		vmcr |= ICH_VMCR_ENG0_MASK;
	else
		vmcr &= ~ICH_VMCR_ENG0_MASK;
	FIELD_MODIFY(ICH_VMCR_EL2_VENG0, &vmcr, val & 1);

	__vgic_v3_write_vmcr(vmcr);
}
@@ -889,10 +886,7 @@ static void __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	u64 val = vcpu_get_reg(vcpu, rt);

	if (val & 1)
		vmcr |= ICH_VMCR_ENG1_MASK;
	else
		vmcr &= ~ICH_VMCR_ENG1_MASK;
	FIELD_MODIFY(ICH_VMCR_EL2_VENG1, &vmcr, val & 1);

	__vgic_v3_write_vmcr(vmcr);
}
@@ -916,10 +910,7 @@ static void __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	if (val < bpr_min)
		val = bpr_min;

	val <<= ICH_VMCR_BPR0_SHIFT;
	val &= ICH_VMCR_BPR0_MASK;
	vmcr &= ~ICH_VMCR_BPR0_MASK;
	vmcr |= val;
	FIELD_MODIFY(ICH_VMCR_EL2_VBPR0, &vmcr, val);

	__vgic_v3_write_vmcr(vmcr);
}
@@ -929,17 +920,14 @@ static void __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	u64 val = vcpu_get_reg(vcpu, rt);
	u8 bpr_min = __vgic_v3_bpr_min();

	if (vmcr & ICH_VMCR_CBPR_MASK)
	if (FIELD_GET(ICH_VMCR_EL2_VCBPR, val))
		return;

	/* Enforce BPR limiting */
	if (val < bpr_min)
		val = bpr_min;

	val <<= ICH_VMCR_BPR1_SHIFT;
	val &= ICH_VMCR_BPR1_MASK;
	vmcr &= ~ICH_VMCR_BPR1_MASK;
	vmcr |= val;
	FIELD_MODIFY(ICH_VMCR_EL2_VBPR1, &vmcr, val);

	__vgic_v3_write_vmcr(vmcr);
}
@@ -1029,19 +1017,14 @@ static void __vgic_v3_read_hppir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)

static void __vgic_v3_read_pmr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	vmcr &= ICH_VMCR_PMR_MASK;
	vmcr >>= ICH_VMCR_PMR_SHIFT;
	vcpu_set_reg(vcpu, rt, vmcr);
	vcpu_set_reg(vcpu, rt, FIELD_GET(ICH_VMCR_EL2_VPMR, vmcr));
}

static void __vgic_v3_write_pmr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	u32 val = vcpu_get_reg(vcpu, rt);

	val <<= ICH_VMCR_PMR_SHIFT;
	val &= ICH_VMCR_PMR_MASK;
	vmcr &= ~ICH_VMCR_PMR_MASK;
	vmcr |= val;
	FIELD_MODIFY(ICH_VMCR_EL2_VPMR, &vmcr, val);

	write_gicreg(vmcr, ICH_VMCR_EL2);
}
@@ -1064,9 +1047,11 @@ static void __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
	/* A3V */
	val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
	/* EOImode */
	val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
	val |= FIELD_PREP(ICC_CTLR_EL1_EOImode_MASK,
			  FIELD_GET(ICH_VMCR_EL2_VEOIM, vmcr));
	/* CBPR */
	val |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
	val |= FIELD_PREP(ICC_CTLR_EL1_CBPR_MASK,
			FIELD_GET(ICH_VMCR_EL2_VCBPR, vmcr));

	vcpu_set_reg(vcpu, rt, val);
}
@@ -1075,15 +1060,11 @@ static void __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
{
	u32 val = vcpu_get_reg(vcpu, rt);

	if (val & ICC_CTLR_EL1_CBPR_MASK)
		vmcr |= ICH_VMCR_CBPR_MASK;
	else
		vmcr &= ~ICH_VMCR_CBPR_MASK;
	FIELD_MODIFY(ICH_VMCR_EL2_VCBPR, &vmcr,
		     FIELD_GET(ICC_CTLR_EL1_CBPR_MASK, val));

	if (val & ICC_CTLR_EL1_EOImode_MASK)
		vmcr |= ICH_VMCR_EOIM_MASK;
	else
		vmcr &= ~ICH_VMCR_EOIM_MASK;
	FIELD_MODIFY(ICH_VMCR_EL2_VEOIM, &vmcr,
		     FIELD_GET(ICC_CTLR_EL1_EOImode_MASK, val));

	write_gicreg(vmcr, ICH_VMCR_EL2);
}
+4 −4
Original line number Diff line number Diff line
@@ -140,6 +140,10 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
		goto out_unlock;
	}

	kvm->arch.vgic.in_kernel = true;
	kvm->arch.vgic.vgic_model = type;
	kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST;

	kvm_for_each_vcpu(i, vcpu, kvm) {
		ret = vgic_allocate_private_irqs_locked(vcpu, type);
		if (ret)
@@ -156,10 +160,6 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
		goto out_unlock;
	}

	kvm->arch.vgic.in_kernel = true;
	kvm->arch.vgic.vgic_model = type;
	kvm->arch.vgic.implementation_rev = KVM_VGIC_IMP_REV_LATEST;

	kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;

	aa64pfr0 = kvm_read_vm_id_reg(kvm, SYS_ID_AA64PFR0_EL1) & ~ID_AA64PFR0_EL1_GIC;
+4 −4
Original line number Diff line number Diff line
@@ -202,16 +202,16 @@ u64 vgic_v3_get_misr(struct kvm_vcpu *vcpu)
	if ((hcr & ICH_HCR_EL2_NPIE) && !mi_state.pend)
		reg |= ICH_MISR_EL2_NP;

	if ((hcr & ICH_HCR_EL2_VGrp0EIE) && (vmcr & ICH_VMCR_ENG0_MASK))
	if ((hcr & ICH_HCR_EL2_VGrp0EIE) && (vmcr & ICH_VMCR_EL2_VENG0_MASK))
		reg |= ICH_MISR_EL2_VGrp0E;

	if ((hcr & ICH_HCR_EL2_VGrp0DIE) && !(vmcr & ICH_VMCR_ENG0_MASK))
	if ((hcr & ICH_HCR_EL2_VGrp0DIE) && !(vmcr & ICH_VMCR_EL2_VENG0_MASK))
		reg |= ICH_MISR_EL2_VGrp0D;

	if ((hcr & ICH_HCR_EL2_VGrp1EIE) && (vmcr & ICH_VMCR_ENG1_MASK))
	if ((hcr & ICH_HCR_EL2_VGrp1EIE) && (vmcr & ICH_VMCR_EL2_VENG1_MASK))
		reg |= ICH_MISR_EL2_VGrp1E;

	if ((hcr & ICH_HCR_EL2_VGrp1DIE) && !(vmcr & ICH_VMCR_ENG1_MASK))
	if ((hcr & ICH_HCR_EL2_VGrp1DIE) && !(vmcr & ICH_VMCR_EL2_VENG1_MASK))
		reg |= ICH_MISR_EL2_VGrp1D;

	return reg;
Loading