kvmarm.lists.cs.columbia.edu archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support
@ 2019-10-27 14:41 Marc Zyngier
  2019-10-27 14:41 ` [PATCH v2 01/36] KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by vcpu_load/put Marc Zyngier
                   ` (35 more replies)
  0 siblings, 36 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:41 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

This rather long series expands the existing GICv4 support to deal with the
new GICv4.1 architecture, which comes with a set of major improvements
compared to v4.0:

- One architectural doorbell per vcpu, instead of one doorbell per VLPI

- Doorbell entirely managed by the HW, with an "at most once" delivery
  guarantee per non-residency phase and only when requested by the
  hypervisor

- A shared memory scheme between ITSs and redistributors, allowing for an
  optimised residency sequence (the use of VMOVP becomes less frequent)

- Support for direct virtual SGI delivery (the injection path still involves
  the hypervisor), at the cost of losing the active state on SGIs. It
  shouldn't be a big deal, but some guest operating systems might notice
  (Linux definitely won't care)

On the other hand, public documentation is not available yet, so that's a
bit annoying...

The series is roughly organised in 5 parts:

(1) A bunch of reworks to make the checking of some features more
    straightforward,
(2) VPE table allocation, new flavours of VMAPP/VMOVP commands
(3) v4.1 doorbell management
(4) Virtual SGI support
(5) Plumbing of virtual SGIs in KVM

Notes:

  - This series has uncovered a behaviour that looks like a HW bug on
    the Cavium ThunderX (aka TX1) platform (see patch #10). I'd very
    much welcome some clarification from the Marvell/Cavium folks on
    Cc, as well as an official erratum number if this happens to be an
    actual bug

  - I plan to take the first seven patches into 5.5 in order to reduce
    the size of the backlog:

    * patch #1 and #3 are good performance optimisations
    * patches #4 through to #7 are nice cleanups

    Do shout if you see any issue with this.

* From v1:
  - A bunch of minor reworks after Zenghui Yu's review
  - A workaround for what looks like a new and unexpected TX1 bug
  - A subtle reorder of the series so that some patches can go in early

Marc Zyngier (36):
  KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by
    vcpu_load/put
  irqchip/gic-v3-its: Factor out wait_for_syncr primitive
  irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface
  irqchip/gic-v3-its: Make is_v4 use a TYPER copy
  irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead
  irqchip/gic-v3-its: Kill its->device_ids and use TYPER copy instead
  irqchip/gic-v3-its: Add get_vlpi_map() helper
  irqchip/gic-v3: Detect GICv4.1 supporting RVPEID
  irqchip/gic-v3: Add GICv4.1 VPEID size discovery
  irqchip/gic-v3: Workaround Cavium TX1 erratum when reading GICD_TYPER2
  irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation
  irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP
  irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set
  irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP
  irqchip/gic-v4.1: Plumb skeletal VPE irqchip
  irqchip/gic-v4.1: Add mask/unmask doorbell callbacks
  irqchip/gic-v4.1: Add VPE residency callback
  irqchip/gic-v4.1: Add VPE eviction callback
  irqchip/gic-v4.1: Add VPE INVALL callback
  irqchip/gic-v4.1: Suppress per-VLPI doorbell
  irqchip/gic-v4.1: Allow direct invalidation of VLPIs
  irqchip/gic-v4.1: Advertise support v4.1 to KVM
  irqchip/gic-v4.1: Map the ITS SGIR register page
  irqchip/gic-v4.1: Plumb skeletal VSGI irqchip
  irqchip/gic-v4.1: Add initial SGI configuration
  irqchip/gic-v4.1: Plumb mask/unmask SGI callbacks
  irqchip/gic-v4.1: Plumb get/set_irqchip_state SGI callbacks
  irqchip/gic-v4.1: Plumb set_vcpu_affinity SGI callbacks
  irqchip/gic-v4.1: Move doorbell management to the GICv4 abstraction
    layer
  irqchip/gic-v4.1: Add VSGI allocation/teardown
  irqchip/gic-v4.1: Add VSGI property setup
  irqchip/gic-v4.1: Eagerly vmap vPEs
  KVM: arm64: GICv4.1: Let doorbells be auto-enabled
  KVM: arm64: GICv4.1: Add direct injection capability to SGI registers
  KVM: arm64: GICv4.1: Configure SGIs as HW interrupts
  KVM: arm64: GICv4.1: Expose HW-based SGIs in debugfs

 arch/arm/include/asm/arch_gicv3.h      |    2 +
 arch/arm64/include/asm/arch_gicv3.h    |    1 +
 drivers/irqchip/irq-gic-v3-its.c       | 1102 +++++++++++++++++++++---
 drivers/irqchip/irq-gic-v3.c           |   46 +-
 drivers/irqchip/irq-gic-v4.c           |  143 ++-
 include/kvm/arm_vgic.h                 |    5 +-
 include/linux/irqchip/arm-gic-common.h |    2 +
 include/linux/irqchip/arm-gic-v3.h     |   75 +-
 include/linux/irqchip/arm-gic-v4.h     |   45 +-
 virt/kvm/arm/arm.c                     |   12 +-
 virt/kvm/arm/vgic/vgic-debug.c         |   14 +-
 virt/kvm/arm/vgic/vgic-mmio-v3.c       |   15 +-
 virt/kvm/arm/vgic/vgic-mmio.c          |   88 +-
 virt/kvm/arm/vgic/vgic-v3.c            |    5 +
 virt/kvm/arm/vgic/vgic-v4.c            |  106 ++-
 virt/kvm/arm/vgic/vgic.c               |    4 -
 virt/kvm/arm/vgic/vgic.h               |    2 -
 17 files changed, 1492 insertions(+), 175 deletions(-)

-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* [PATCH v2 01/36] KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by vcpu_load/put
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
@ 2019-10-27 14:41 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 02/36] irqchip/gic-v3-its: Factor out wait_for_syncr primitive Marc Zyngier
                   ` (34 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:41 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

When the VHE code was reworked, a lot of the vgic stuff was moved around,
but the GICv4 residency code did stay untouched, meaning that we come
in and out of residency on each flush/sync, which is obviously suboptimal.

To address this, let's move things around a bit:

- Residency entry (flush) moves to vcpu_load
- Residency exit (sync) moves to vcpu_put
- On blocking (entry to WFI), we "put"
- On unblocking (exit from WFI, we "load"

Because these can nest (load/block/put/load/unblock/put, for example),
we now have per-VPE tracking of the residency state.

Additionally, vgic_v4_put gains a "need doorbell" parameter, which only
gets set to true when blocking because of a WFI. This allows a finer
control of the doorbell, which now also gets disabled as soon as
it gets signaled.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v4.c       |  7 +++-
 include/kvm/arm_vgic.h             |  4 +--
 include/linux/irqchip/arm-gic-v4.h |  2 ++
 virt/kvm/arm/arm.c                 | 12 ++++---
 virt/kvm/arm/vgic/vgic-v3.c        |  4 +++
 virt/kvm/arm/vgic/vgic-v4.c        | 55 ++++++++++++++----------------
 virt/kvm/arm/vgic/vgic.c           |  4 ---
 virt/kvm/arm/vgic/vgic.h           |  2 --
 8 files changed, 48 insertions(+), 42 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index 563e87ed0766..45969927cc81 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -141,12 +141,17 @@ static int its_send_vpe_cmd(struct its_vpe *vpe, struct its_cmd_info *info)
 int its_schedule_vpe(struct its_vpe *vpe, bool on)
 {
 	struct its_cmd_info info;
+	int ret;
 
 	WARN_ON(preemptible());
 
 	info.cmd_type = on ? SCHEDULE_VPE : DESCHEDULE_VPE;
 
-	return its_send_vpe_cmd(vpe, &info);
+	ret = its_send_vpe_cmd(vpe, &info);
+	if (!ret)
+		vpe->resident = on;
+
+	return ret;
 }
 
 int its_invall_vpe(struct its_vpe *vpe)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index af4f09c02bf1..4dc58d7a0010 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -396,7 +396,7 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq,
 int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
 				 struct kvm_kernel_irq_routing_entry *irq_entry);
 
-void kvm_vgic_v4_enable_doorbell(struct kvm_vcpu *vcpu);
-void kvm_vgic_v4_disable_doorbell(struct kvm_vcpu *vcpu);
+int vgic_v4_load(struct kvm_vcpu *vcpu);
+int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db);
 
 #endif /* __KVM_ARM_VGIC_H */
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index e6b155713b47..ab1396afe08a 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -35,6 +35,8 @@ struct its_vpe {
 	/* Doorbell interrupt */
 	int			irq;
 	irq_hw_number_t		vpe_db_lpi;
+	/* VPE resident */
+	bool			resident;
 	/* VPE proxy mapping */
 	int			vpe_proxy_event;
 	/*
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 86c6aa1cb58e..bd2afcf9a13f 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -322,20 +322,24 @@ void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
 	/*
 	 * If we're about to block (most likely because we've just hit a
 	 * WFI), we need to sync back the state of the GIC CPU interface
-	 * so that we have the lastest PMR and group enables. This ensures
+	 * so that we have the latest PMR and group enables. This ensures
 	 * that kvm_arch_vcpu_runnable has up-to-date data to decide
 	 * whether we have pending interrupts.
+	 *
+	 * For the same reason, we want to tell GICv4 that we need
+	 * doorbells to be signalled, should an interrupt become pending.
 	 */
 	preempt_disable();
 	kvm_vgic_vmcr_sync(vcpu);
+	vgic_v4_put(vcpu, true);
 	preempt_enable();
-
-	kvm_vgic_v4_enable_doorbell(vcpu);
 }
 
 void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
 {
-	kvm_vgic_v4_disable_doorbell(vcpu);
+	preempt_disable();
+	vgic_v4_load(vcpu);
+	preempt_enable();
 }
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 8d69f007dd0c..48307a9eb1d8 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -664,6 +664,8 @@ void vgic_v3_load(struct kvm_vcpu *vcpu)
 
 	if (has_vhe())
 		__vgic_v3_activate_traps(vcpu);
+
+	WARN_ON(vgic_v4_load(vcpu));
 }
 
 void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
@@ -676,6 +678,8 @@ void vgic_v3_vmcr_sync(struct kvm_vcpu *vcpu)
 
 void vgic_v3_put(struct kvm_vcpu *vcpu)
 {
+	WARN_ON(vgic_v4_put(vcpu, false));
+
 	vgic_v3_vmcr_sync(vcpu);
 
 	kvm_call_hyp(__vgic_v3_save_aprs, vcpu);
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 477af6aebb97..7e1f3202968a 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -85,6 +85,10 @@ static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 {
 	struct kvm_vcpu *vcpu = info;
 
+	/* We got the message, no need to fire again */
+	if (!irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
+		disable_irq_nosync(irq);
+
 	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
 	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
 	kvm_vcpu_kick(vcpu);
@@ -192,20 +196,30 @@ void vgic_v4_teardown(struct kvm *kvm)
 	its_vm->vpes = NULL;
 }
 
-int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu)
+int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db)
 {
-	if (!vgic_supports_direct_msis(vcpu->kvm))
+	struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+	struct irq_desc *desc = irq_to_desc(vpe->irq);
+
+	if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
 		return 0;
 
-	return its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, false);
+	/*
+	 * If blocking, a doorbell is required. Undo the nested
+	 * disable_irq() calls...
+	 */
+	while (need_db && irqd_irq_disabled(&desc->irq_data))
+		enable_irq(vpe->irq);
+
+	return its_schedule_vpe(vpe, false);
 }
 
-int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
+int vgic_v4_load(struct kvm_vcpu *vcpu)
 {
-	int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
+	struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
 	int err;
 
-	if (!vgic_supports_direct_msis(vcpu->kvm))
+	if (!vgic_supports_direct_msis(vcpu->kvm) || vpe->resident)
 		return 0;
 
 	/*
@@ -214,11 +228,14 @@ int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
 	 * doc in drivers/irqchip/irq-gic-v4.c to understand how this
 	 * turns into a VMOVP command at the ITS level.
 	 */
-	err = irq_set_affinity(irq, cpumask_of(smp_processor_id()));
+	err = irq_set_affinity(vpe->irq, cpumask_of(smp_processor_id()));
 	if (err)
 		return err;
 
-	err = its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, true);
+	/* Disabled the doorbell, as we're about to enter the guest */
+	disable_irq_nosync(vpe->irq);
+
+	err = its_schedule_vpe(vpe, true);
 	if (err)
 		return err;
 
@@ -226,9 +243,7 @@ int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
 	 * Now that the VPE is resident, let's get rid of a potential
 	 * doorbell interrupt that would still be pending.
 	 */
-	err = irq_set_irqchip_state(irq, IRQCHIP_STATE_PENDING, false);
-
-	return err;
+	return irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
 }
 
 static struct vgic_its *vgic_get_its(struct kvm *kvm,
@@ -335,21 +350,3 @@ int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq,
 	mutex_unlock(&its->its_lock);
 	return ret;
 }
-
-void kvm_vgic_v4_enable_doorbell(struct kvm_vcpu *vcpu)
-{
-	if (vgic_supports_direct_msis(vcpu->kvm)) {
-		int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
-		if (irq)
-			enable_irq(irq);
-	}
-}
-
-void kvm_vgic_v4_disable_doorbell(struct kvm_vcpu *vcpu)
-{
-	if (vgic_supports_direct_msis(vcpu->kvm)) {
-		int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
-		if (irq)
-			disable_irq(irq);
-	}
-}
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 45a870cb63f5..99b02ca730a8 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -857,8 +857,6 @@ void kvm_vgic_sync_hwstate(struct kvm_vcpu *vcpu)
 {
 	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
 
-	WARN_ON(vgic_v4_sync_hwstate(vcpu));
-
 	/* An empty ap_list_head implies used_lrs == 0 */
 	if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head))
 		return;
@@ -882,8 +880,6 @@ static inline void vgic_restore_state(struct kvm_vcpu *vcpu)
 /* Flush our emulation state into the GIC hardware before entering the guest. */
 void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 {
-	WARN_ON(vgic_v4_flush_hwstate(vcpu));
-
 	/*
 	 * If there are no virtual interrupts active or pending for this
 	 * VCPU, then there is no work to do and we can bail out without
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 83066a81b16a..c7fefd6b1c80 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -316,7 +316,5 @@ void vgic_its_invalidate_cache(struct kvm *kvm);
 bool vgic_supports_direct_msis(struct kvm *kvm);
 int vgic_v4_init(struct kvm *kvm);
 void vgic_v4_teardown(struct kvm *kvm);
-int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu);
-int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu);
 
 #endif
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 02/36] irqchip/gic-v3-its: Factor out wait_for_syncr primitive
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
  2019-10-27 14:41 ` [PATCH v2 01/36] KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by vcpu_load/put Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-28  9:20   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface Marc Zyngier
                   ` (33 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Waiting for a redistributor to have performed an operation is a
common thing to do, and the idiom is already spread around.
As we're going to make even more use of this, let's have a primitive
that does just that.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 62e54f1a248b..58cb233cf138 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1075,6 +1075,12 @@ static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
 		dsb(ishst);
 }
 
+static void wait_for_syncr(void __iomem *rdbase)
+{
+	while (gic_read_lpir(rdbase + GICR_SYNCR) & 1)
+		cpu_relax();
+}
+
 static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
@@ -2757,8 +2763,7 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
 
 		rdbase = per_cpu_ptr(gic_rdists->rdist, from)->rd_base;
 		gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_CLRLPIR);
-		while (gic_read_lpir(rdbase + GICR_SYNCR) & 1)
-			cpu_relax();
+		wait_for_syncr(rdbase);
 
 		return;
 	}
@@ -2914,8 +2919,7 @@ static void its_vpe_send_inv(struct irq_data *d)
 
 		rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
 		gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_INVLPIR);
-		while (gic_read_lpir(rdbase + GICR_SYNCR) & 1)
-			cpu_relax();
+		wait_for_syncr(rdbase);
 	} else {
 		its_vpe_send_cmd(vpe, its_send_inv);
 	}
@@ -2957,8 +2961,7 @@ static int its_vpe_set_irqchip_state(struct irq_data *d,
 			gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_SETLPIR);
 		} else {
 			gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_CLRLPIR);
-			while (gic_read_lpir(rdbase + GICR_SYNCR) & 1)
-				cpu_relax();
+			wait_for_syncr(rdbase);
 		}
 	} else {
 		if (state)
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
  2019-10-27 14:41 ` [PATCH v2 01/36] KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by vcpu_load/put Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 02/36] irqchip/gic-v3-its: Factor out wait_for_syncr primitive Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-31  8:49   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy Marc Zyngier
                   ` (32 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

We currently don't make much use of the DirectLPI feature, and it would
be beneficial to do this more, if only because it becomes a mandatory
feature for GICv4.1.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 40 +++++++++++++++++++++++++-------
 1 file changed, 32 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 58cb233cf138..3e33cdc08200 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -175,6 +175,12 @@ static DEFINE_IDA(its_vpeid_ida);
 #define gic_data_rdist_rd_base()	(gic_data_rdist()->rd_base)
 #define gic_data_rdist_vlpi_base()	(gic_data_rdist_rd_base() + SZ_128K)
 
+static inline u32 its_get_event_id(struct irq_data *d)
+{
+	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	return d->hwirq - its_dev->event_map.lpi_base;
+}
+
 static struct its_collection *dev_event_to_col(struct its_device *its_dev,
 					       u32 event)
 {
@@ -183,6 +189,13 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
 	return its->collections + its_dev->event_map.col_map[event];
 }
 
+static struct its_collection *irq_to_col(struct irq_data *d)
+{
+	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+
+	return dev_event_to_col(its_dev, its_get_event_id(d));
+}
+
 static struct its_collection *valid_col(struct its_collection *col)
 {
 	if (WARN_ON_ONCE(col->target_address & GENMASK_ULL(15, 0)))
@@ -1031,12 +1044,6 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
  * irqchip functions - assumes MSI, mostly.
  */
 
-static inline u32 its_get_event_id(struct irq_data *d)
-{
-	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
-	return d->hwirq - its_dev->event_map.lpi_base;
-}
-
 static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
 {
 	irq_hw_number_t hwirq;
@@ -1081,12 +1088,28 @@ static void wait_for_syncr(void __iomem *rdbase)
 		cpu_relax();
 }
 
+static void direct_lpi_inv(struct irq_data *d)
+{
+	struct its_collection *col;
+	void __iomem *rdbase;
+
+	/* Target the redistributor this LPI is currently routed to */
+	col = irq_to_col(d);
+	rdbase = per_cpu_ptr(gic_rdists->rdist, col->col_id)->rd_base;
+	gic_write_lpir(d->hwirq, rdbase + GICR_INVLPIR);
+
+	wait_for_syncr(rdbase);
+}
+
 static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 
 	lpi_write_config(d, clr, set);
-	its_send_inv(its_dev, its_get_event_id(d));
+	if (gic_rdists->has_direct_lpi && !irqd_is_forwarded_to_vcpu(d))
+		direct_lpi_inv(d);
+	else
+		its_send_inv(its_dev, its_get_event_id(d));
 }
 
 static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)
@@ -2917,8 +2940,9 @@ static void its_vpe_send_inv(struct irq_data *d)
 	if (gic_rdists->has_direct_lpi) {
 		void __iomem *rdbase;
 
+		/* Target the redistributor this VPE is currently known on */
 		rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
-		gic_write_lpir(vpe->vpe_db_lpi, rdbase + GICR_INVLPIR);
+		gic_write_lpir(d->parent_data->hwirq, rdbase + GICR_INVLPIR);
 		wait_for_syncr(rdbase);
 	} else {
 		its_vpe_send_cmd(vpe, its_send_inv);
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (2 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-28  9:34   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 05/36] irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead Marc Zyngier
                   ` (31 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Instead of caching the GICv4 compatibility in a discrete way, cache the
TYPER register instead, which can then be used to implement the same
functionnality. This will get used more extensively in subsequent patches.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 24 +++++++++++++-----------
 1 file changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 3e33cdc08200..b3c9bc0c3ecd 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -102,6 +102,7 @@ struct its_node {
 	struct its_collection	*collections;
 	struct fwnode_handle	*fwnode_handle;
 	u64			(*get_msi_base)(struct its_device *its_dev);
+	u64			typer;
 	u64			cbaser_save;
 	u32			ctlr_save;
 	struct list_head	its_device_list;
@@ -112,10 +113,11 @@ struct its_node {
 	int			numa_node;
 	unsigned int		msi_domain_flags;
 	u32			pre_its_base; /* for Socionext Synquacer */
-	bool			is_v4;
 	int			vlpi_redist_offset;
 };
 
+#define is_v4(its)		(!!((its)->typer & GITS_TYPER_VLPIS))
+
 #define ITS_ITT_ALIGN		SZ_256
 
 /* The maximum number of VPEID bits supported by VLPI commands */
@@ -1019,7 +1021,7 @@ static void its_send_vmovp(struct its_vpe *vpe)
 
 	/* Emit VMOVPs */
 	list_for_each_entry(its, &its_nodes, entry) {
-		if (!its->is_v4)
+		if (!is_v4(its))
 			continue;
 
 		if (!vpe->its_vm->vlpi_count[its->list_nr])
@@ -1430,7 +1432,7 @@ static int its_irq_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 	struct its_cmd_info *info = vcpu_info;
 
 	/* Need a v4 ITS */
-	if (!its_dev->its->is_v4)
+	if (!is_v4(its_dev->its))
 		return -EINVAL;
 
 	/* Unmap request? */
@@ -2394,7 +2396,7 @@ static bool its_alloc_vpe_table(u32 vpe_id)
 	list_for_each_entry(its, &its_nodes, entry) {
 		struct its_baser *baser;
 
-		if (!its->is_v4)
+		if (!is_v4(its))
 			continue;
 
 		baser = its_get_baser(its, GITS_BASER_TYPE_VCPU);
@@ -2882,7 +2884,7 @@ static void its_vpe_invall(struct its_vpe *vpe)
 	struct its_node *its;
 
 	list_for_each_entry(its, &its_nodes, entry) {
-		if (!its->is_v4)
+		if (!is_v4(its))
 			continue;
 
 		if (its_list_map && !vpe->its_vm->vlpi_count[its->list_nr])
@@ -3150,7 +3152,7 @@ static int its_vpe_irq_domain_activate(struct irq_domain *domain,
 	vpe->col_idx = cpumask_first(cpu_online_mask);
 
 	list_for_each_entry(its, &its_nodes, entry) {
-		if (!its->is_v4)
+		if (!is_v4(its))
 			continue;
 
 		its_send_vmapp(its, vpe, true);
@@ -3176,7 +3178,7 @@ static void its_vpe_irq_domain_deactivate(struct irq_domain *domain,
 		return;
 
 	list_for_each_entry(its, &its_nodes, entry) {
-		if (!its->is_v4)
+		if (!is_v4(its))
 			continue;
 
 		its_send_vmapp(its, vpe, false);
@@ -3614,12 +3616,12 @@ static int __init its_probe_one(struct resource *res,
 	INIT_LIST_HEAD(&its->entry);
 	INIT_LIST_HEAD(&its->its_device_list);
 	typer = gic_read_typer(its_base + GITS_TYPER);
+	its->typer = typer;
 	its->base = its_base;
 	its->phys_base = res->start;
 	its->ite_size = GITS_TYPER_ITT_ENTRY_SIZE(typer);
 	its->device_ids = GITS_TYPER_DEVBITS(typer);
-	its->is_v4 = !!(typer & GITS_TYPER_VLPIS);
-	if (its->is_v4) {
+	if (is_v4(its)) {
 		if (!(typer & GITS_TYPER_VMOVP)) {
 			err = its_compute_its_list_map(res, its_base);
 			if (err < 0)
@@ -3686,7 +3688,7 @@ static int __init its_probe_one(struct resource *res,
 	gits_write_cwriter(0, its->base + GITS_CWRITER);
 	ctlr = readl_relaxed(its->base + GITS_CTLR);
 	ctlr |= GITS_CTLR_ENABLE;
-	if (its->is_v4)
+	if (is_v4(its))
 		ctlr |= GITS_CTLR_ImDe;
 	writel_relaxed(ctlr, its->base + GITS_CTLR);
 
@@ -4011,7 +4013,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 		return err;
 
 	list_for_each_entry(its, &its_nodes, entry)
-		has_v4 |= its->is_v4;
+		has_v4 |= is_v4(its);
 
 	if (has_v4 & rdists->has_vlpis) {
 		if (its_init_vpe_domain() ||
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 05/36] irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (3 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-28  9:40   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids " Marc Zyngier
                   ` (30 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Now that we have a copy of TYPER in the ITS structure, rely on this
to provide the same service as its->ite_size, which gets axed.
Errata workarounds are now updating the cached fields instead of
requiring a separate field in the ITS structure.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 8 ++++----
 include/linux/irqchip/arm-gic-v3.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index b3c9bc0c3ecd..3b046181ddfc 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -6,6 +6,7 @@
 
 #include <linux/acpi.h>
 #include <linux/acpi_iort.h>
+#include <linux/bitfield.h>
 #include <linux/bitmap.h>
 #include <linux/cpu.h>
 #include <linux/crash_dump.h>
@@ -108,7 +109,6 @@ struct its_node {
 	struct list_head	its_device_list;
 	u64			flags;
 	unsigned long		list_nr;
-	u32			ite_size;
 	u32			device_ids;
 	int			numa_node;
 	unsigned int		msi_domain_flags;
@@ -2435,7 +2435,7 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
 	 * sized as a power of two (and you need at least one bit...).
 	 */
 	nr_ites = max(2, nvecs);
-	sz = nr_ites * its->ite_size;
+	sz = nr_ites * (FIELD_GET(GITS_TYPER_ITT_ENTRY_SIZE, its->typer) + 1);
 	sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
 	itt = kzalloc_node(sz, GFP_KERNEL, its->numa_node);
 	if (alloc_lpis) {
@@ -3250,7 +3250,8 @@ static bool __maybe_unused its_enable_quirk_qdf2400_e0065(void *data)
 	struct its_node *its = data;
 
 	/* On QDF2400, the size of the ITE is 16Bytes */
-	its->ite_size = 16;
+	its->typer &= ~GITS_TYPER_ITT_ENTRY_SIZE;
+	its->typer |= FIELD_PREP(GITS_TYPER_ITT_ENTRY_SIZE, 16 - 1);
 
 	return true;
 }
@@ -3619,7 +3620,6 @@ static int __init its_probe_one(struct resource *res,
 	its->typer = typer;
 	its->base = its_base;
 	its->phys_base = res->start;
-	its->ite_size = GITS_TYPER_ITT_ENTRY_SIZE(typer);
 	its->device_ids = GITS_TYPER_DEVBITS(typer);
 	if (is_v4(its)) {
 		if (!(typer & GITS_TYPER_VMOVP)) {
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 5cc10cf7cb3e..4bce7a904075 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -334,7 +334,7 @@
 #define GITS_TYPER_PLPIS		(1UL << 0)
 #define GITS_TYPER_VLPIS		(1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT	4
-#define GITS_TYPER_ITT_ENTRY_SIZE(r)	((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0xf) + 1)
+#define GITS_TYPER_ITT_ENTRY_SIZE	GENMASK_ULL(7, 4)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
 #define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids and use TYPER copy instead
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (4 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 05/36] irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-31  6:33   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 07/36] irqchip/gic-v3-its: Add get_vlpi_map() helper Marc Zyngier
                   ` (29 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Now that we have a copy of TYPER in the ITS structure, rely on this
to provide the same service as its->device_ids, which gets axed.
Errata workarounds are now updating the cached fields instead of
requiring a separate field in the ITS structure.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 24 +++++++++++++-----------
 include/linux/irqchip/arm-gic-v3.h |  2 +-
 2 files changed, 14 insertions(+), 12 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 3b046181ddfc..6c91c7feadf3 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -109,7 +109,6 @@ struct its_node {
 	struct list_head	its_device_list;
 	u64			flags;
 	unsigned long		list_nr;
-	u32			device_ids;
 	int			numa_node;
 	unsigned int		msi_domain_flags;
 	u32			pre_its_base; /* for Socionext Synquacer */
@@ -117,6 +116,7 @@ struct its_node {
 };
 
 #define is_v4(its)		(!!((its)->typer & GITS_TYPER_VLPIS))
+#define device_ids(its)		(FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1)
 
 #define ITS_ITT_ALIGN		SZ_256
 
@@ -1938,9 +1938,9 @@ static bool its_parse_indirect_baser(struct its_node *its,
 	if (new_order >= MAX_ORDER) {
 		new_order = MAX_ORDER - 1;
 		ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
-		pr_warn("ITS@%pa: %s Table too large, reduce ids %u->%u\n",
+		pr_warn("ITS@%pa: %s Table too large, reduce ids %llu->%u\n",
 			&its->phys_base, its_base_type_string[type],
-			its->device_ids, ids);
+			device_ids(its), ids);
 	}
 
 	*order = new_order;
@@ -1986,7 +1986,7 @@ static int its_alloc_tables(struct its_node *its)
 		case GITS_BASER_TYPE_DEVICE:
 			indirect = its_parse_indirect_baser(its, baser,
 							    psz, &order,
-							    its->device_ids);
+							    device_ids(its));
 			break;
 
 		case GITS_BASER_TYPE_VCPU:
@@ -2377,7 +2377,7 @@ static bool its_alloc_device_table(struct its_node *its, u32 dev_id)
 
 	/* Don't allow device id that exceeds ITS hardware limit */
 	if (!baser)
-		return (ilog2(dev_id) < its->device_ids);
+		return (ilog2(dev_id) < device_ids(its));
 
 	return its_alloc_table_entry(its, baser, dev_id);
 }
@@ -3229,8 +3229,9 @@ static bool __maybe_unused its_enable_quirk_cavium_22375(void *data)
 {
 	struct its_node *its = data;
 
-	/* erratum 22375: only alloc 8MB table size */
-	its->device_ids = 0x14;		/* 20 bits, 8MB */
+	/* erratum 22375: only alloc 8MB table size (20 bits) */
+	its->typer &= ~GITS_TYPER_DEVBITS;
+	its->typer |= FIELD_PREP(GITS_TYPER_DEVBITS, 20 - 1);
 	its->flags |= ITS_FLAGS_WORKAROUND_CAVIUM_22375;
 
 	return true;
@@ -3285,8 +3286,10 @@ static bool __maybe_unused its_enable_quirk_socionext_synquacer(void *data)
 		its->get_msi_base = its_irq_get_msi_base_pre_its;
 
 		ids = ilog2(pre_its_window[1]) - 2;
-		if (its->device_ids > ids)
-			its->device_ids = ids;
+		if (device_ids(its) > ids) {
+			its->typer &= ~GITS_TYPER_DEVBITS;
+			its->typer |= FIELD_PREP(GITS_TYPER_DEVBITS, ids - 1);
+		}
 
 		/* the pre-ITS breaks isolation, so disable MSI remapping */
 		its->msi_domain_flags &= ~IRQ_DOMAIN_FLAG_MSI_REMAP;
@@ -3519,7 +3522,7 @@ static int its_init_vpe_domain(void)
 	}
 
 	/* Use the last possible DevID */
-	devid = GENMASK(its->device_ids - 1, 0);
+	devid = GENMASK(device_ids(its) - 1, 0);
 	vpe_proxy.dev = its_create_device(its, devid, entries, false);
 	if (!vpe_proxy.dev) {
 		kfree(vpe_proxy.vpes);
@@ -3620,7 +3623,6 @@ static int __init its_probe_one(struct resource *res,
 	its->typer = typer;
 	its->base = its_base;
 	its->phys_base = res->start;
-	its->device_ids = GITS_TYPER_DEVBITS(typer);
 	if (is_v4(its)) {
 		if (!(typer & GITS_TYPER_VMOVP)) {
 			err = its_compute_its_list_map(res, its_base);
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 4bce7a904075..b6514e8893bf 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -337,7 +337,7 @@
 #define GITS_TYPER_ITT_ENTRY_SIZE	GENMASK_ULL(7, 4)
 #define GITS_TYPER_IDBITS_SHIFT		8
 #define GITS_TYPER_DEVBITS_SHIFT	13
-#define GITS_TYPER_DEVBITS(r)		((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
+#define GITS_TYPER_DEVBITS		GENMASK_ULL(17, 13)
 #define GITS_TYPER_PTA			(1UL << 19)
 #define GITS_TYPER_HCC_SHIFT		24
 #define GITS_TYPER_HCC(r)		(((r) >> GITS_TYPER_HCC_SHIFT) & 0xff)
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 07/36] irqchip/gic-v3-its: Add get_vlpi_map() helper
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (5 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids " Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-31  3:54   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 08/36] irqchip/gic-v3: Detect GICv4.1 supporting RVPEID Marc Zyngier
                   ` (28 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Obtaining the mapping information for a VLPI is something quite common,
and the GICv4.1 code is going to make even more use of it. Expose it as
a separate helper.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 27 ++++++++++++++++-----------
 1 file changed, 16 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6c91c7feadf3..94c9c2e9f917 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1045,20 +1045,26 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
 /*
  * irqchip functions - assumes MSI, mostly.
  */
+static struct its_vlpi_map *get_vlpi_map(struct irq_data *d)
+{
+	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	u32 event = its_get_event_id(d);
+
+	if (!irqd_is_forwarded_to_vcpu(d))
+		return NULL;
+
+	return &its_dev->event_map.vlpi_maps[event];
+}
 
 static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
 {
+	struct its_vlpi_map *map = get_vlpi_map(d);
 	irq_hw_number_t hwirq;
 	void *va;
 	u8 *cfg;
 
-	if (irqd_is_forwarded_to_vcpu(d)) {
-		struct its_device *its_dev = irq_data_get_irq_chip_data(d);
-		u32 event = its_get_event_id(d);
-		struct its_vlpi_map *map;
-
-		va = page_address(its_dev->event_map.vm->vprop_page);
-		map = &its_dev->event_map.vlpi_maps[event];
+	if (map) {
+		va = page_address(map->vm->vprop_page);
 		hwirq = map->vintid;
 
 		/* Remember the updated property */
@@ -1351,19 +1357,18 @@ static int its_vlpi_map(struct irq_data *d, struct its_cmd_info *info)
 static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
-	u32 event = its_get_event_id(d);
+	struct its_vlpi_map *map = get_vlpi_map(d);
 	int ret = 0;
 
 	mutex_lock(&its_dev->event_map.vlpi_lock);
 
-	if (!its_dev->event_map.vm ||
-	    !its_dev->event_map.vlpi_maps[event].vm) {
+	if (!its_dev->event_map.vm || !map->vm) {
 		ret = -EINVAL;
 		goto out;
 	}
 
 	/* Copy our mapping information to the incoming request */
-	*info->map = its_dev->event_map.vlpi_maps[event];
+	*info->map = *map;
 
 out:
 	mutex_unlock(&its_dev->event_map.vlpi_lock);
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 08/36] irqchip/gic-v3: Detect GICv4.1 supporting RVPEID
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (6 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 07/36] irqchip/gic-v3-its: Add get_vlpi_map() helper Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-31 11:34   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery Marc Zyngier
                   ` (27 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

GICv4.1 supports the RVPEID ("Residency per vPE ID"), which allows for
a much efficient way of making virtual CPUs resident (to allow direct
injection of interrupts).

The functionnality needs to be discovered on each and every redistributor
in the system, and disabled if the settings are inconsistent.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c       | 21 ++++++++++++++++++---
 include/linux/irqchip/arm-gic-v3.h |  2 ++
 2 files changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 1edc99335a94..4f20caf9bc88 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -849,8 +849,21 @@ static int __gic_update_rdist_properties(struct redist_region *region,
 					 void __iomem *ptr)
 {
 	u64 typer = gic_read_typer(ptr + GICR_TYPER);
+
 	gic_data.rdists.has_vlpis &= !!(typer & GICR_TYPER_VLPIS);
-	gic_data.rdists.has_direct_lpi &= !!(typer & GICR_TYPER_DirectLPIS);
+
+	/* RVPEID implies some form of DirectLPI, no matter what the doc says... :-/ */
+	gic_data.rdists.has_rvpeid &= !!(typer & GICR_TYPER_RVPEID);
+	gic_data.rdists.has_direct_lpi &= (!!(typer & GICR_TYPER_DirectLPIS) |
+					   gic_data.rdists.has_rvpeid);
+
+	/* Detect non-sensical configurations */
+	if (WARN_ON_ONCE(gic_data.rdists.has_rvpeid && !gic_data.rdists.has_vlpis)) {
+		gic_data.rdists.has_direct_lpi = false;
+		gic_data.rdists.has_vlpis = false;
+		gic_data.rdists.has_rvpeid = false;
+	}
+
 	gic_data.ppi_nr = min(GICR_TYPER_NR_PPIS(typer), gic_data.ppi_nr);
 
 	return 1;
@@ -863,9 +876,10 @@ static void gic_update_rdist_properties(void)
 	if (WARN_ON(gic_data.ppi_nr == UINT_MAX))
 		gic_data.ppi_nr = 0;
 	pr_info("%d PPIs implemented\n", gic_data.ppi_nr);
-	pr_info("%sVLPI support, %sdirect LPI support\n",
+	pr_info("%sVLPI support, %sdirect LPI support, %sRVPEID support\n",
 		!gic_data.rdists.has_vlpis ? "no " : "",
-		!gic_data.rdists.has_direct_lpi ? "no " : "");
+		!gic_data.rdists.has_direct_lpi ? "no " : "",
+		!gic_data.rdists.has_rvpeid ? "no " : "");
 }
 
 /* Check whether it's single security state view */
@@ -1546,6 +1560,7 @@ static int __init gic_init_bases(void __iomem *dist_base,
 						 &gic_data);
 	irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
 	gic_data.rdists.rdist = alloc_percpu(typeof(*gic_data.rdists.rdist));
+	gic_data.rdists.has_rvpeid = true;
 	gic_data.rdists.has_vlpis = true;
 	gic_data.rdists.has_direct_lpi = true;
 
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index b6514e8893bf..c98f34296599 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -234,6 +234,7 @@
 #define GICR_TYPER_VLPIS		(1U << 1)
 #define GICR_TYPER_DirectLPIS		(1U << 3)
 #define GICR_TYPER_LAST			(1U << 4)
+#define GICR_TYPER_RVPEID		(1U << 7)
 
 #define GIC_V3_REDIST_SIZE		0x20000
 
@@ -613,6 +614,7 @@ struct rdists {
 	u64			flags;
 	u32			gicd_typer;
 	bool			has_vlpis;
+	bool			has_rvpeid;
 	bool			has_direct_lpi;
 };
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (7 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 08/36] irqchip/gic-v3: Detect GICv4.1 supporting RVPEID Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-31 12:02   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 10/36] irqchip/gic-v3: Workaround Cavium TX1 erratum when reading GICD_TYPER2 Marc Zyngier
                   ` (26 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

While GICv4.0 mandates 16 bit worth of VPEIDs, GICv4.1 allows smaller
implementations to be built. Add the required glue to dynamically
compute the limit.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 11 ++++++++++-
 drivers/irqchip/irq-gic-v3.c       |  3 +++
 include/linux/irqchip/arm-gic-v3.h |  5 +++++
 3 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 94c9c2e9f917..40912b3fb0e1 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -121,7 +121,16 @@ struct its_node {
 #define ITS_ITT_ALIGN		SZ_256
 
 /* The maximum number of VPEID bits supported by VLPI commands */
-#define ITS_MAX_VPEID_BITS	(16)
+#define ITS_MAX_VPEID_BITS						\
+	({								\
+		int nvpeid = 16;					\
+		if (gic_rdists->has_rvpeid &&				\
+		    gic_rdists->gicd_typer2 & GICD_TYPER2_VIL)		\
+			nvpeid = 1 + (gic_rdists->gicd_typer2 &		\
+				      GICD_TYPER2_VID);			\
+									\
+		nvpeid;							\
+	})
 #define ITS_MAX_VPEID		(1 << (ITS_MAX_VPEID_BITS))
 
 /* Convert page order to size in bytes */
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 4f20caf9bc88..50538709bd49 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1556,6 +1556,9 @@ static int __init gic_init_bases(void __iomem *dist_base,
 
 	pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
 	pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
+
+	gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2);
+
 	gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
 						 &gic_data);
 	irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c98f34296599..8c6be56da7e9 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -13,6 +13,7 @@
 #define GICD_CTLR			0x0000
 #define GICD_TYPER			0x0004
 #define GICD_IIDR			0x0008
+#define GICD_TYPER2			0x000C
 #define GICD_STATUSR			0x0010
 #define GICD_SETSPI_NSR			0x0040
 #define GICD_CLRSPI_NSR			0x0048
@@ -89,6 +90,9 @@
 #define GICD_TYPER_ESPIS(typer)						\
 	(((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
 
+#define GICD_TYPER2_VIL			(1U << 7)
+#define GICD_TYPER2_VID			GENMASK(4, 0)
+
 #define GICD_IROUTER_SPI_MODE_ONE	(0U << 31)
 #define GICD_IROUTER_SPI_MODE_ANY	(1U << 31)
 
@@ -613,6 +617,7 @@ struct rdists {
 	void			*prop_table_va;
 	u64			flags;
 	u32			gicd_typer;
+	u32			gicd_typer2;
 	bool			has_vlpis;
 	bool			has_rvpeid;
 	bool			has_direct_lpi;
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 10/36] irqchip/gic-v3: Workaround Cavium TX1 erratum when reading GICD_TYPER2
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (8 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation Marc Zyngier
                   ` (25 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Despite the architecture spec being extremely clear about the fact
that reserved registers in the GIC distributor memory map are RES0
(and thus are not allowed to generate an exception), the Cavium
ThunderX (aka TX1) SoC explodes as such:

[    0.000000] GICv3: GIC: Using split EOI/Deactivate mode
[    0.000000] GICv3: 128 SPIs implemented
[    0.000000] GICv3: 0 Extended SPIs implemented
[    0.000000] Internal error: synchronous external abort: 96000210 [#1] SMP
[    0.000000] Modules linked in:
[    0.000000] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.4.0-rc4-00035-g3cf6a3d5725f #7956
[    0.000000] Hardware name: cavium,thunder-88xx (DT)
[    0.000000] pstate: 60000085 (nZCv daIf -PAN -UAO)
[    0.000000] pc : __raw_readl+0x0/0x8
[    0.000000] lr : gic_init_bases+0x110/0x560
[    0.000000] sp : ffff800011243d90
[    0.000000] x29: ffff800011243d90 x28: 0000000000000000
[    0.000000] x27: 0000000000000018 x26: 0000000000000002
[    0.000000] x25: ffff8000116f0000 x24: ffff000fbe6a2c80
[    0.000000] x23: 0000000000000000 x22: ffff010fdc322b68
[    0.000000] x21: ffff800010a7a208 x20: 00000000009b0404
[    0.000000] x19: ffff80001124dad0 x18: 0000000000000010
[    0.000000] x17: 000000004d8d492b x16: 00000000f67eb9af
[    0.000000] x15: ffffffffffffffff x14: ffff800011249908
[    0.000000] x13: ffff800091243ae7 x12: ffff800011243af4
[    0.000000] x11: ffff80001126e000 x10: ffff800011243a70
[    0.000000] x9 : 00000000ffffffd0 x8 : ffff80001069c828
[    0.000000] x7 : 0000000000000059 x6 : ffff8000113fb4d1
[    0.000000] x5 : 0000000000000001 x4 : 0000000000000000
[    0.000000] x3 : 0000000000000000 x2 : 0000000000000000
[    0.000000] x1 : 0000000000000000 x0 : ffff8000116f000c
[    0.000000] Call trace:
[    0.000000]  __raw_readl+0x0/0x8
[    0.000000]  gic_of_init+0x188/0x224
[    0.000000]  of_irq_init+0x200/0x3cc
[    0.000000]  irqchip_init+0x1c/0x40
[    0.000000]  init_IRQ+0x160/0x1d0
[    0.000000]  start_kernel+0x2ec/0x4b8
[    0.000000] Code: a8c47bfd d65f03c0 d538d080 d65f03c0 (b9400000)

when reading the GICv4.1 GICD_TYPER2 register, which is unexpected...

Work around it by adding a new quirk flagging all the A1 revisions
of the distributor, but it remains unknown whether this could affect
other revisions of this SoC (or even other SoCs from the same silicon
vendor).

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 50538709bd49..f0d33ac64a99 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -34,6 +34,7 @@
 #define GICD_INT_NMI_PRI	(GICD_INT_DEF_PRI & ~0x80)
 
 #define FLAGS_WORKAROUND_GICR_WAKER_MSM8996	(1ULL << 0)
+#define FLAGS_WORKAROUND_GICD_TYPER2_TX1	(1ULL << 1)
 
 struct redist_region {
 	void __iomem		*redist_base;
@@ -1455,6 +1456,15 @@ static bool gic_enable_quirk_msm8996(void *data)
 	return true;
 }
 
+static bool gic_enable_quirk_tx1(void *data)
+{
+	struct gic_chip_data *d = data;
+
+	d->flags |= FLAGS_WORKAROUND_GICD_TYPER2_TX1;
+
+	return true;
+}
+
 static bool gic_enable_quirk_hip06_07(void *data)
 {
 	struct gic_chip_data *d = data;
@@ -1493,6 +1503,12 @@ static const struct gic_quirk gic_quirks[] = {
 		.mask	= 0xffffffff,
 		.init	= gic_enable_quirk_hip06_07,
 	},
+	{
+		.desc	= "GICv3: Cavium TX1 GICD_TYPER2 erratum",
+		.iidr	= 0xa100034c,
+		.mask	= 0xfff00fff,
+		.init	= gic_enable_quirk_tx1,
+	},
 	{
 	}
 };
@@ -1557,7 +1573,12 @@ static int __init gic_init_bases(void __iomem *dist_base,
 	pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
 	pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
 
-	gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2);
+	/*
+	 * ThunderX1 explodes on reading GICD_TYPER2, in total violation
+	 * of the spec (which says that reserved addresses are RES0).
+	 */
+	if (!(gic_data.flags & FLAGS_WORKAROUND_GICD_TYPER2_TX1))
+		gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2);
 
 	gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
 						 &gic_data);
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (9 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 10/36] irqchip/gic-v3: Workaround Cavium TX1 erratum when reading GICD_TYPER2 Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-12-24  7:10   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP Marc Zyngier
                   ` (24 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

GICv4.1 defines a new VPE table that is potentially shared between
both the ITSs and the redistributors, following complicated affinity
rules.

To make things more confusing, the programming of this table at
the redistributor level is reusing the GICv4.0 GICR_VPROPBASER register
for something completely different.

The code flow is somewhat complexified by the need to respect the
affinities required by the HW, meaning that tables can either be
inherited from a previously discovered ITS or redistributor.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 arch/arm/include/asm/arch_gicv3.h   |   2 +
 arch/arm64/include/asm/arch_gicv3.h |   1 +
 drivers/irqchip/irq-gic-v3-its.c    | 305 +++++++++++++++++++++++++++-
 include/linux/irqchip/arm-gic-v3.h  |  33 ++-
 4 files changed, 334 insertions(+), 7 deletions(-)

diff --git a/arch/arm/include/asm/arch_gicv3.h b/arch/arm/include/asm/arch_gicv3.h
index 0555f14cc8be..20bacab1d791 100644
--- a/arch/arm/include/asm/arch_gicv3.h
+++ b/arch/arm/include/asm/arch_gicv3.h
@@ -10,6 +10,7 @@
 #ifndef __ASSEMBLY__
 
 #include <linux/io.h>
+#include <linux/io-64-nonatomic-lo-hi.h>
 #include <asm/barrier.h>
 #include <asm/cacheflush.h>
 #include <asm/cp15.h>
@@ -327,6 +328,7 @@ static inline u64 __gic_readq_nonatomic(const volatile void __iomem *addr)
 /*
  * GITS_VPROPBASER - hi and lo bits may be accessed independently.
  */
+#define gits_read_vpropbaser(c)		__gic_readq_nonatomic(c)
 #define gits_write_vpropbaser(v, c)	__gic_writeq_nonatomic(v, c)
 
 /*
diff --git a/arch/arm64/include/asm/arch_gicv3.h b/arch/arm64/include/asm/arch_gicv3.h
index 89e4c8b79349..4750fc8030c3 100644
--- a/arch/arm64/include/asm/arch_gicv3.h
+++ b/arch/arm64/include/asm/arch_gicv3.h
@@ -141,6 +141,7 @@ static inline u32 gic_read_rpr(void)
 #define gicr_read_pendbaser(c)		readq_relaxed(c)
 
 #define gits_write_vpropbaser(v, c)	writeq_relaxed(v, c)
+#define gits_read_vpropbaser(c)		readq_relaxed(c)
 
 #define gits_write_vpendbaser(v, c)	writeq_relaxed(v, c)
 #define gits_read_vpendbaser(c)		readq_relaxed(c)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 40912b3fb0e1..478d3678850c 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -45,6 +45,7 @@
 
 #define RDIST_FLAGS_PROPBASE_NEEDS_FLUSHING	(1 << 0)
 #define RDIST_FLAGS_RD_TABLES_PREALLOCATED	(1 << 1)
+#define RDIST_FLAGS_VPE_INDIRECT		(1 << 2)
 
 static u32 lpi_id_bits;
 
@@ -106,6 +107,7 @@ struct its_node {
 	u64			typer;
 	u64			cbaser_save;
 	u32			ctlr_save;
+	u32			mpidr;
 	struct list_head	its_device_list;
 	u64			flags;
 	unsigned long		list_nr;
@@ -116,6 +118,7 @@ struct its_node {
 };
 
 #define is_v4(its)		(!!((its)->typer & GITS_TYPER_VLPIS))
+#define is_v4_1(its)		(!!((its)->typer & GITS_TYPER_VMAPP))
 #define device_ids(its)		(FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1)
 
 #define ITS_ITT_ALIGN		SZ_256
@@ -1962,6 +1965,65 @@ static bool its_parse_indirect_baser(struct its_node *its,
 	return indirect;
 }
 
+static u32 compute_common_aff(u64 val)
+{
+	u32 aff, clpiaff;
+
+	aff = FIELD_GET(GICR_TYPER_AFFINITY, val);
+	clpiaff = FIELD_GET(GICR_TYPER_COMMON_LPI_AFF, val);
+
+	return aff & ~(GENMASK(31, 0) >> (clpiaff * 8));
+}
+
+static u32 compute_its_aff(struct its_node *its)
+{
+	u64 val;
+	u32 svpet;
+
+	/*
+	 * Reencode the ITS SVPET and MPIDR as a GICR_TYPER, and compute
+	 * the resulting affinity. We then use that to see if this match
+	 * our own affinity.
+	 */
+	svpet = FIELD_GET(GITS_TYPER_SVPET, its->typer);
+	val  = FIELD_PREP(GICR_TYPER_COMMON_LPI_AFF, svpet);
+	val |= FIELD_PREP(GICR_TYPER_AFFINITY, its->mpidr);
+	return compute_common_aff(val);
+}
+
+static struct its_node *find_sibling_its(struct its_node *cur_its)
+{
+	struct its_node *its;
+	u32 aff;
+
+	if (!FIELD_GET(GITS_TYPER_SVPET, cur_its->typer))
+		return NULL;
+
+	aff = compute_its_aff(cur_its);
+
+	list_for_each_entry(its, &its_nodes, entry) {
+		u64 baser;
+
+		if (!is_v4_1(its) || its == cur_its)
+			continue;
+
+		if (!FIELD_GET(GITS_TYPER_SVPET, its->typer))
+			continue;
+
+		if (aff != compute_its_aff(its))
+			continue;
+
+		/* GICv4.1 guarantees that the vPE table is GITS_BASER2 */
+		baser = its->tables[2].val;
+		if (!(baser & GITS_BASER_VALID))
+			continue;
+
+		return its;
+	}
+
+	return NULL;
+}
+
 static void its_free_tables(struct its_node *its)
 {
 	int i;
@@ -2004,6 +2066,17 @@ static int its_alloc_tables(struct its_node *its)
 			break;
 
 		case GITS_BASER_TYPE_VCPU:
+			if (is_v4_1(its)) {
+				struct its_node *sibling;
+
+				WARN_ON(i != 2);
+				if ((sibling = find_sibling_its(its))) {
+					*baser = sibling->tables[2];
+					its_write_baser(its, baser, baser->val);
+					continue;
+				}
+			}
+
 			indirect = its_parse_indirect_baser(its, baser,
 							    psz, &order,
 							    ITS_MAX_VPEID_BITS);
@@ -2025,6 +2098,214 @@ static int its_alloc_tables(struct its_node *its)
 	return 0;
 }
 
+static u64 inherit_vpe_l1_table_from_its(void)
+{
+	struct its_node *its;
+	u64 val;
+	u32 aff;
+
+	val = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
+	aff = compute_common_aff(val);
+
+	list_for_each_entry(its, &its_nodes, entry) {
+		u64 baser;
+
+		if (!is_v4_1(its))
+			continue;
+
+		if (!FIELD_GET(GITS_TYPER_SVPET, its->typer))
+			continue;
+
+		if (aff != compute_its_aff(its))
+			continue;
+
+		/* GICv4.1 guarantees that the vPE table is GITS_BASER2 */
+		baser = its->tables[2].val;
+		if (!(baser & GITS_BASER_VALID))
+			continue;
+
+		/* We have a winner! */
+		val  = GICR_VPROPBASER_4_1_VALID;
+		if (baser & GITS_BASER_INDIRECT)
+			val |= GICR_VPROPBASER_4_1_INDIRECT;
+		val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE,
+				  FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser));
+		val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR,
+				  GITS_BASER_ADDR_48_to_52(baser) >> 12);
+		val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK,
+				  FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser));
+		val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK,
+				  FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser));
+		val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, GITS_BASER_NR_PAGES(baser) - 1);
+
+		return val;
+	}
+
+	return 0;
+}
+
+static u64 inherit_vpe_l1_table_from_rd(cpumask_t **mask)
+{
+	u32 aff;
+	u64 val;
+	int cpu;
+
+	val = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
+	aff = compute_common_aff(val);
+
+	for_each_possible_cpu(cpu) {
+		void __iomem *base = gic_data_rdist_cpu(cpu)->rd_base;
+		u32 tmp;
+
+		if (!base || cpu == smp_processor_id())
+			continue;
+
+		val = gic_read_typer(base + GICR_TYPER);
+		tmp = compute_common_aff(val);
+		if (tmp != aff)
+			continue;
+
+		/*
+		 * At this point, we have a victim. This particular CPU
+		 * has already booted, and has an affinity that matches
+		 * ours wrt CommonLPIAff. Let's use its own VPROPBASER.
+		 * Make sure we don't write the Z bit in that case.
+		 */
+		val = gits_read_vpropbaser(base + SZ_128K + GICR_VPROPBASER);
+		val &= ~GICR_VPROPBASER_4_1_Z;
+
+		*mask = gic_data_rdist_cpu(cpu)->vpe_table_mask;
+
+		return val;
+	}
+
+	return 0;
+}
+
+static int allocate_vpe_l1_table(void)
+{
+	void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+	u64 val, gpsz, npg, pa;
+	unsigned int psz = SZ_64K;
+	unsigned int np, epp, esz;
+	struct page *page;
+
+	if (!gic_rdists->has_rvpeid)
+		return 0;
+
+	/*
+	 * if VPENDBASER.Valid is set, disable any previously programmed
+	 * VPE by setting PendingLast while clearing Valid. This has the
+	 * effect of making sure no doorbell will be generated and we can
+	 * then safely clear VPROPBASER.Valid.
+	 */
+	if (gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER) & GICR_VPENDBASER_Valid)
+		gits_write_vpendbaser(GICR_VPENDBASER_PendingLast,
+				      vlpi_base + GICR_VPENDBASER);
+
+	/*
+	 * If we can inherit the configuration from another RD, let's do
+	 * so. Otherwise, we have to go through the allocation process. We
+	 * assume that all RDs have the exact same requirements, as
+	 * nothing will work otherwise.
+	 */
+	val = inherit_vpe_l1_table_from_rd(&gic_data_rdist()->vpe_table_mask);
+	if (val & GICR_VPROPBASER_4_1_VALID)
+		goto out;
+
+	gic_data_rdist()->vpe_table_mask = kzalloc(sizeof(cpumask_t), GFP_KERNEL);
+	if (!gic_data_rdist()->vpe_table_mask)
+		return -ENOMEM;
+
+	val = inherit_vpe_l1_table_from_its();
+	if (val & GICR_VPROPBASER_4_1_VALID)
+		goto out;
+
+	/* First probe the page size */
+	val = FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE, GIC_PAGE_SIZE_64K);
+	gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
+	val = gits_read_vpropbaser(vlpi_base + GICR_VPROPBASER);
+	gpsz = FIELD_GET(GICR_VPROPBASER_4_1_PAGE_SIZE, val);
+	esz = FIELD_GET(GICR_VPROPBASER_4_1_ENTRY_SIZE, val);
+
+	switch (gpsz) {
+	default:
+		gpsz = GIC_PAGE_SIZE_4K;
+		/* fall through */
+	case GIC_PAGE_SIZE_4K:
+		psz = SZ_4K;
+		break;
+	case GIC_PAGE_SIZE_16K:
+		psz = SZ_16K;
+		break;
+	case GIC_PAGE_SIZE_64K:
+		psz = SZ_64K;
+		break;
+	}
+
+	/*
+	 * Start populating the register from scratch, including RO fields
+	 * (which we want to print in debug cases...)
+	 */
+	val = 0;
+	val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE, gpsz);
+	val |= FIELD_PREP(GICR_VPROPBASER_4_1_ENTRY_SIZE, esz);
+
+	/* How many entries per GIC page? */
+	esz++;
+	epp = psz / (esz * SZ_8);
+
+	/*
+	 * If we need more than just a single L1 page, flag the table
+	 * as indirect and compute the number of required L1 pages.
+	 */
+	if (epp < ITS_MAX_VPEID) {
+		int nl2;
+
+		gic_rdists->flags |= RDIST_FLAGS_VPE_INDIRECT;
+		val |= GICR_VPROPBASER_4_1_INDIRECT;
+
+		/* Number of L2 pages required to cover the VPEID space */
+		nl2 = DIV_ROUND_UP(ITS_MAX_VPEID, epp);
+
+		/* Number of L1 pages to point to the L2 pages */
+		npg = DIV_ROUND_UP(nl2 * SZ_8, psz);
+	} else {
+		npg = 1;
+	}
+
+	val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, npg);
+
+	/* Right, that's the number of CPU pages we need for L1 */
+	np = DIV_ROUND_UP(npg * psz, PAGE_SIZE);
+
+	pr_debug("np = %d, npg = %lld, psz = %d, epp = %d, esz = %d\n",
+		 np, npg, psz, epp, esz);
+	page = alloc_pages(GFP_KERNEL | __GFP_ZERO, get_order(np * PAGE_SIZE));
+	if (!page)
+		return -ENOMEM;
+
+	gic_data_rdist()->vpe_l1_page = page;
+	pa = virt_to_phys(page_address(page));
+	WARN_ON(!IS_ALIGNED(pa, psz));
+
+	val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, pa >> 12);
+	val |= GICR_VPROPBASER_RaWb;
+	val |= GICR_VPROPBASER_InnerShareable;
+	val |= GICR_VPROPBASER_4_1_Z;
+	val |= GICR_VPROPBASER_4_1_VALID;
+
+out:
+	gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
+	cpumask_set_cpu(smp_processor_id(), gic_data_rdist()->vpe_table_mask);
+
+	pr_debug("CPU%d: VPROPBASER = %llx %*pbl\n",
+		 smp_processor_id(), val,
+		 cpumask_pr_args(gic_data_rdist()->vpe_table_mask));
+
+	return 0;
+}
+
 static int its_alloc_collections(struct its_node *its)
 {
 	int i;
@@ -2224,7 +2505,7 @@ static void its_cpu_init_lpis(void)
 	val |= GICR_CTLR_ENABLE_LPIS;
 	writel_relaxed(val, rbase + GICR_CTLR);
 
-	if (gic_rdists->has_vlpis) {
+	if (gic_rdists->has_vlpis && !gic_rdists->has_rvpeid) {
 		void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
 
 		/*
@@ -2248,6 +2529,16 @@ static void its_cpu_init_lpis(void)
 		WARN_ON(val & GICR_VPENDBASER_Dirty);
 	}
 
+	if (allocate_vpe_l1_table()) {
+		/*
+		 * If the allocation has failed, we're in massive trouble.
+		 * Disable direct injection, and pray that no VM was
+		 * already running...
+		 */
+		gic_rdists->has_rvpeid = false;
+		gic_rdists->has_vlpis = false;
+	}
+
 	/* Make sure the GIC has seen the above */
 	dsb(sy);
 out:
@@ -3650,6 +3941,14 @@ static int __init its_probe_one(struct resource *res,
 		} else {
 			pr_info("ITS@%pa: Single VMOVP capable\n", &res->start);
 		}
+
+		if (is_v4_1(its)) {
+			u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
+			its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
+
+			pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
+				&res->start, its->mpidr, svpet);
+		}
 	}
 
 	its->numa_node = numa_node;
@@ -4010,6 +4309,8 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	bool has_v4 = false;
 	int err;
 
+	gic_rdists = rdists;
+
 	its_parent = parent_domain;
 	of_node = to_of_node(handle);
 	if (of_node)
@@ -4022,8 +4323,6 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 		return -ENXIO;
 	}
 
-	gic_rdists = rdists;
-
 	err = allocate_lpi_tables();
 	if (err)
 		return err;
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 8c6be56da7e9..f1d6de53e09b 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -102,6 +102,11 @@
 
 #define GIC_V3_DIST_SIZE		0x10000
 
+#define GIC_PAGE_SIZE_4K		0ULL
+#define GIC_PAGE_SIZE_16K		1ULL
+#define GIC_PAGE_SIZE_64K		2ULL
+#define GIC_PAGE_SIZE_MASK		3ULL
+
 /*
  * Re-Distributor registers, offsets from RD_base
  */
@@ -239,6 +244,8 @@
 #define GICR_TYPER_DirectLPIS		(1U << 3)
 #define GICR_TYPER_LAST			(1U << 4)
 #define GICR_TYPER_RVPEID		(1U << 7)
+#define GICR_TYPER_COMMON_LPI_AFF	GENMASK_ULL(25, 24)
+#define GICR_TYPER_AFFINITY		GENMASK_ULL(63, 32)
 
 #define GIC_V3_REDIST_SIZE		0x20000
 
@@ -277,6 +284,18 @@
 #define GICR_VPROPBASER_RaWaWt	GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWt)
 #define GICR_VPROPBASER_RaWaWb	GIC_BASER_CACHEABILITY(GICR_VPROPBASER, INNER, RaWaWb)
 
+/*
+ * GICv4.1 VPROPBASER reinvention. A subtle mix between the old
+ * VPROPBASER and ITS_BASER. Just not quite any of the two.
+ */
+#define GICR_VPROPBASER_4_1_VALID	(1ULL << 63)
+#define GICR_VPROPBASER_4_1_ENTRY_SIZE	GENMASK_ULL(61, 59)
+#define GICR_VPROPBASER_4_1_INDIRECT	(1ULL << 55)
+#define GICR_VPROPBASER_4_1_PAGE_SIZE	GENMASK_ULL(54, 53)
+#define GICR_VPROPBASER_4_1_Z		(1ULL << 52)
+#define GICR_VPROPBASER_4_1_ADDR	GENMASK_ULL(51, 12)
+#define GICR_VPROPBASER_4_1_SIZE	GENMASK_ULL(6, 0)
+
 #define GICR_VPENDBASER			0x0078
 
 #define GICR_VPENDBASER_SHAREABILITY_SHIFT		(10)
@@ -314,6 +333,7 @@
 #define GITS_CTLR			0x0000
 #define GITS_IIDR			0x0004
 #define GITS_TYPER			0x0008
+#define GITS_MPIDR			0x0018
 #define GITS_CBASER			0x0080
 #define GITS_CWRITER			0x0088
 #define GITS_CREADR			0x0090
@@ -347,6 +367,8 @@
 #define GITS_TYPER_HCC_SHIFT		24
 #define GITS_TYPER_HCC(r)		(((r) >> GITS_TYPER_HCC_SHIFT) & 0xff)
 #define GITS_TYPER_VMOVP		(1ULL << 37)
+#define GITS_TYPER_VMAPP		(1ULL << 40)
+#define GITS_TYPER_SVPET		GENMASK_ULL(42, 41)
 
 #define GITS_IIDR_REV_SHIFT		12
 #define GITS_IIDR_REV_MASK		(0xf << GITS_IIDR_REV_SHIFT)
@@ -417,10 +439,11 @@
 #define GITS_BASER_InnerShareable					\
 	GIC_BASER_SHAREABILITY(GITS_BASER, InnerShareable)
 #define GITS_BASER_PAGE_SIZE_SHIFT	(8)
-#define GITS_BASER_PAGE_SIZE_4K		(0ULL << GITS_BASER_PAGE_SIZE_SHIFT)
-#define GITS_BASER_PAGE_SIZE_16K	(1ULL << GITS_BASER_PAGE_SIZE_SHIFT)
-#define GITS_BASER_PAGE_SIZE_64K	(2ULL << GITS_BASER_PAGE_SIZE_SHIFT)
-#define GITS_BASER_PAGE_SIZE_MASK	(3ULL << GITS_BASER_PAGE_SIZE_SHIFT)
+#define __GITS_BASER_PSZ(sz)		(GIC_PAGE_SIZE_ ## sz << GITS_BASER_PAGE_SIZE_SHIFT)
+#define GITS_BASER_PAGE_SIZE_4K		__GITS_BASER_PSZ(4K)
+#define GITS_BASER_PAGE_SIZE_16K	__GITS_BASER_PSZ(16K)
+#define GITS_BASER_PAGE_SIZE_64K	__GITS_BASER_PSZ(64K)
+#define GITS_BASER_PAGE_SIZE_MASK	__GITS_BASER_PSZ(MASK)
 #define GITS_BASER_PAGES_MAX		256
 #define GITS_BASER_PAGES_SHIFT		(0)
 #define GITS_BASER_NR_PAGES(r)		(((r) & 0xff) + 1)
@@ -610,8 +633,10 @@ struct rdists {
 	struct {
 		void __iomem	*rd_base;
 		struct page	*pend_page;
+		struct page	*vpe_l1_page;
 		phys_addr_t	phys_base;
 		bool		lpi_enabled;
+		cpumask_t	*vpe_table_mask;
 	} __percpu		*rdist;
 	phys_addr_t		prop_table_pa;
 	void			*prop_table_va;
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (10 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 10:58   ` Zenghui Yu
  2019-11-13  8:02   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set Marc Zyngier
                   ` (23 subsequent siblings)
  35 siblings, 2 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

The ITS VMAPP command gains some new fields with GICv4.1:
- a default doorbell, which allows a single doorbell to be used for
  all the VLPIs routed to a given VPE
- a pointer to the configuration table (instead of having it in a register
  that gets context switched)
- a flag indicating whether this is the first map or the last unmap for
  this particulat VPE
- a flag indicating whether the pending table is known to be zeroed, or not

Plumb in the new fields in the VMAPP builder, and add the map/unmap
refcounting so that the ITS can do the right thing.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 60 +++++++++++++++++++++++++++---
 include/linux/irqchip/arm-gic-v4.h | 18 +++++++--
 2 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 478d3678850c..220d490d516e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -422,6 +422,27 @@ static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size)
 	its_mask_encode(&cmd->raw_cmd[3], vpt_size, 4, 0);
 }
 
+static void its_encode_vconf_addr(struct its_cmd_block *cmd, u64 vconf_pa)
+{
+	its_mask_encode(&cmd->raw_cmd[0], vconf_pa >> 16, 51, 16);
+}
+
+static void its_encode_alloc(struct its_cmd_block *cmd, bool alloc)
+{
+	its_mask_encode(&cmd->raw_cmd[0], alloc, 8, 8);
+}
+
+static void its_encode_ptz(struct its_cmd_block *cmd, bool ptz)
+{
+	its_mask_encode(&cmd->raw_cmd[0], ptz, 9, 9);
+}
+
+static void its_encode_vmapp_default_db(struct its_cmd_block *cmd,
+					u32 vpe_db_lpi)
+{
+	its_mask_encode(&cmd->raw_cmd[1], vpe_db_lpi, 31, 0);
+}
+
 static inline void its_fixup_cmd(struct its_cmd_block *cmd)
 {
 	/* Let's fixup BE commands */
@@ -605,19 +626,45 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
 					   struct its_cmd_block *cmd,
 					   struct its_cmd_desc *desc)
 {
-	unsigned long vpt_addr;
+	unsigned long vpt_addr, vconf_addr;
 	u64 target;
-
-	vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
-	target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
+	bool alloc;
 
 	its_encode_cmd(cmd, GITS_CMD_VMAPP);
 	its_encode_vpeid(cmd, desc->its_vmapp_cmd.vpe->vpe_id);
 	its_encode_valid(cmd, desc->its_vmapp_cmd.valid);
+
+	if (!desc->its_vmapp_cmd.valid) {
+		if (is_v4_1(its)) {
+			alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
+			its_encode_alloc(cmd, alloc);
+		}
+
+		goto out;
+	}
+
+	vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
+	target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
+
 	its_encode_target(cmd, target);
 	its_encode_vpt_addr(cmd, vpt_addr);
 	its_encode_vpt_size(cmd, LPI_NRBITS - 1);
 
+	if (!is_v4_1(its))
+		goto out;
+
+	vconf_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page));
+
+	alloc = atomic_inc_and_test(&desc->its_vmapp_cmd.vpe->vmapp_count);
+
+	its_encode_alloc(cmd, alloc);
+
+	/* We can only signal PTZ when alloc==1. Why do we have two bits? */
+	its_encode_ptz(cmd, alloc);
+	its_encode_vconf_addr(cmd, vconf_addr);
+	its_encode_vmapp_default_db(cmd, desc->its_vmapp_cmd.vpe->vpe_db_lpi);
+
+out:
 	its_fixup_cmd(cmd);
 
 	return valid_vpe(its, desc->its_vmapp_cmd.vpe);
@@ -3349,7 +3396,10 @@ static int its_vpe_init(struct its_vpe *vpe)
 
 	vpe->vpe_id = vpe_id;
 	vpe->vpt_page = vpt_page;
-	vpe->vpe_proxy_event = -1;
+	if (gic_rdists->has_rvpeid)
+		atomic_set(&vpe->vmapp_count, 0);
+	else
+		vpe->vpe_proxy_event = -1;
 
 	return 0;
 }
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index ab1396afe08a..6213ced6f199 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -37,8 +37,20 @@ struct its_vpe {
 	irq_hw_number_t		vpe_db_lpi;
 	/* VPE resident */
 	bool			resident;
-	/* VPE proxy mapping */
-	int			vpe_proxy_event;
+	union {
+		/* GICv4.0 implementations */
+		struct {
+			/* VPE proxy mapping */
+			int	vpe_proxy_event;
+			/* Implementation Defined Area Invalid */
+			bool	idai;
+		};
+		/* GICv4.1 implementations */
+		struct {
+			atomic_t vmapp_count;
+		};
+	};
+
 	/*
 	 * This collection ID is used to indirect the target
 	 * redistributor for this VPE. The ID itself isn't involved in
@@ -47,8 +59,6 @@ struct its_vpe {
 	u16			col_idx;
 	/* Unique (system-wide) VPE identifier */
 	u16			vpe_id;
-	/* Implementation Defined Area Invalid */
-	bool			idai;
 	/* Pending VLPIs on schedule out? */
 	bool			pending_last;
 };
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (11 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:05   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 14/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP Marc Zyngier
                   ` (22 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

The infamous VPE proxy device isn't used with GICv4.1 because:
- we can invalidate any LPI from the DirectLPI MMIO interface
- the ITS and redistributors understand the life cycle of
  the doorbell, so we don't need to enable/disable it all
  the time

So let's escape early from the proxy related functions.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 220d490d516e..999e61a9b2c3 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3069,7 +3069,7 @@ static const struct irq_domain_ops its_domain_ops = {
 /*
  * This is insane.
  *
- * If a GICv4 doesn't implement Direct LPIs (which is extremely
+ * If a GICv4.0 doesn't implement Direct LPIs (which is extremely
  * likely), the only way to perform an invalidate is to use a fake
  * device to issue an INV command, implying that the LPI has first
  * been mapped to some event on that device. Since this is not exactly
@@ -3077,9 +3077,18 @@ static const struct irq_domain_ops its_domain_ops = {
  * only issue an UNMAP if we're short on available slots.
  *
  * Broken by design(tm).
+ *
+ * GICv4.1 actually mandates that we're able to invalidate by writing to a
+ * MMIO register. It doesn't implement the whole of DirectLPI, but that's
+ * good enough. And most of the time, we don't even have to invalidate
+ * anything, so that's actually pretty good!
  */
 static void its_vpe_db_proxy_unmap_locked(struct its_vpe *vpe)
 {
+	/* GICv4.1 doesn't use a proxy, so nothing to do here */
+	if (gic_rdists->has_rvpeid)
+		return;
+
 	/* Already unmapped? */
 	if (vpe->vpe_proxy_event == -1)
 		return;
@@ -3102,6 +3111,10 @@ static void its_vpe_db_proxy_unmap_locked(struct its_vpe *vpe)
 
 static void its_vpe_db_proxy_unmap(struct its_vpe *vpe)
 {
+	/* GICv4.1 doesn't use a proxy, so nothing to do here */
+	if (gic_rdists->has_rvpeid)
+		return;
+
 	if (!gic_rdists->has_direct_lpi) {
 		unsigned long flags;
 
@@ -3113,6 +3126,10 @@ static void its_vpe_db_proxy_unmap(struct its_vpe *vpe)
 
 static void its_vpe_db_proxy_map_locked(struct its_vpe *vpe)
 {
+	/* GICv4.1 doesn't use a proxy, so nothing to do here */
+	if (gic_rdists->has_rvpeid)
+		return;
+
 	/* Already mapped? */
 	if (vpe->vpe_proxy_event != -1)
 		return;
@@ -3135,6 +3152,10 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
 	unsigned long flags;
 	struct its_collection *target_col;
 
+	/* GICv4.1 doesn't use a proxy, so nothing to do here */
+	if (gic_rdists->has_rvpeid)
+		return;
+
 	if (gic_rdists->has_direct_lpi) {
 		void __iomem *rdbase;
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 14/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (12 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:10   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 15/36] irqchip/gic-v4.1: Plumb skeletal VPE irqchip Marc Zyngier
                   ` (21 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

With GICv4.1, VMOVP is extended to allow a default doorbell to be
specified, as well as a validity bit for this doorbell. As an added
bonus, VMOPVP isn't required anymore of moving a VPE between
redistributors that share the same affinity.

Let's add this support to the VMOVP builder, and make sure we don't
issuer the command if we don't really need to.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 40 ++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 7 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 999e61a9b2c3..b5a122093a46 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -443,6 +443,17 @@ static void its_encode_vmapp_default_db(struct its_cmd_block *cmd,
 	its_mask_encode(&cmd->raw_cmd[1], vpe_db_lpi, 31, 0);
 }
 
+static void its_encode_vmovp_default_db(struct its_cmd_block *cmd,
+					u32 vpe_db_lpi)
+{
+	its_mask_encode(&cmd->raw_cmd[3], vpe_db_lpi, 31, 0);
+}
+
+static void its_encode_db(struct its_cmd_block *cmd, bool db)
+{
+	its_mask_encode(&cmd->raw_cmd[2], db, 63, 63);
+}
+
 static inline void its_fixup_cmd(struct its_cmd_block *cmd)
 {
 	/* Let's fixup BE commands */
@@ -729,6 +740,11 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
 	its_encode_vpeid(cmd, desc->its_vmovp_cmd.vpe->vpe_id);
 	its_encode_target(cmd, target);
 
+	if (is_v4_1(its)) {
+		its_encode_db(cmd, true);
+		its_encode_vmovp_default_db(cmd, desc->its_vmovp_cmd.vpe->vpe_db_lpi);
+	}
+
 	its_fixup_cmd(cmd);
 
 	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
@@ -3182,7 +3198,7 @@ static int its_vpe_set_affinity(struct irq_data *d,
 				bool force)
 {
 	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
-	int cpu = cpumask_first(mask_val);
+	int from, cpu = cpumask_first(mask_val);
 
 	/*
 	 * Changing affinity is mega expensive, so let's be as lazy as
@@ -3190,14 +3206,24 @@ static int its_vpe_set_affinity(struct irq_data *d,
 	 * into the proxy device, we need to move the doorbell
 	 * interrupt to its new location.
 	 */
-	if (vpe->col_idx != cpu) {
-		int from = vpe->col_idx;
+	if (vpe->col_idx == cpu)
+		goto out;
 
-		vpe->col_idx = cpu;
-		its_send_vmovp(vpe);
-		its_vpe_db_proxy_move(vpe, from, cpu);
-	}
+	from = vpe->col_idx;
+	vpe->col_idx = cpu;
+
+	/*
+	 * GICv4.1 allows us to skip VMOVP if moving to a cpu whose RD
+	 * is sharing its VPE table with the current one.
+	 */
+	if (gic_data_rdist_cpu(cpu)->vpe_table_mask &&
+	    cpumask_test_cpu(from, gic_data_rdist_cpu(cpu)->vpe_table_mask))
+		goto out;
 
+	its_send_vmovp(vpe);
+	its_vpe_db_proxy_move(vpe, from, cpu);
+
+out:
 	irq_data_update_effective_affinity(d, cpumask_of(cpu));
 
 	return IRQ_SET_MASK_OK_DONE;
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 15/36] irqchip/gic-v4.1: Plumb skeletal VPE irqchip
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (13 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 14/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:13   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks Marc Zyngier
                   ` (20 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Just like for GICv4.0, each VPE has its own doorbell interrupt, and
thus an irqchip that manages them. Since the doorbell management is
quite different on GICv4.1, let's introduce an almost empty irqchip
the will get populated over the next new patches.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 32 +++++++++++++++++++++++++++++++-
 1 file changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index b5a122093a46..dcc7227af5f1 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3408,6 +3408,32 @@ static struct irq_chip its_vpe_irq_chip = {
 	.irq_set_vcpu_affinity	= its_vpe_set_vcpu_affinity,
 };
 
+static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
+{
+	struct its_cmd_info *info = vcpu_info;
+
+	switch (info->cmd_type) {
+	case SCHEDULE_VPE:
+		return 0;
+
+	case DESCHEDULE_VPE:
+		return 0;
+
+	case INVALL_VPE:
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static struct irq_chip its_vpe_4_1_irq_chip = {
+	.name			= "GICv4.1-vpe",
+	.irq_eoi		= irq_chip_eoi_parent,
+	.irq_set_affinity	= its_vpe_set_affinity,
+	.irq_set_vcpu_affinity	= its_vpe_4_1_set_vcpu_affinity,
+};
+
 static int its_vpe_id_alloc(void)
 {
 	return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
@@ -3488,6 +3514,7 @@ static void its_vpe_irq_domain_free(struct irq_domain *domain,
 static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
 				    unsigned int nr_irqs, void *args)
 {
+	struct irq_chip *irqchip = &its_vpe_irq_chip;
 	struct its_vm *vm = args;
 	unsigned long *bitmap;
 	struct page *vprop_page;
@@ -3515,6 +3542,9 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
 	vm->nr_db_lpis = nr_ids;
 	vm->vprop_page = vprop_page;
 
+	if (gic_rdists->has_rvpeid)
+		irqchip = &its_vpe_4_1_irq_chip;
+
 	for (i = 0; i < nr_irqs; i++) {
 		vm->vpes[i]->vpe_db_lpi = base + i;
 		err = its_vpe_init(vm->vpes[i]);
@@ -3525,7 +3555,7 @@ static int its_vpe_irq_domain_alloc(struct irq_domain *domain, unsigned int virq
 		if (err)
 			break;
 		irq_domain_set_hwirq_and_chip(domain, virq + i, i,
-					      &its_vpe_irq_chip, vm->vpes[i]);
+					      irqchip, vm->vpes[i]);
 		set_bit(i, bitmap);
 	}
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (14 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 15/36] irqchip/gic-v4.1: Plumb skeletal VPE irqchip Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:23   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 17/36] irqchip/gic-v4.1: Add VPE residency callback Marc Zyngier
                   ` (19 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

masking/unmasking doorbells on GICv4.1 relies on a new INVDB command,
which broadcasts the invalidation to all RDs.

Implement the new command as well as the masking callbacks, and plug
the whole thing into the v4.1 VPE irqchip.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 60 ++++++++++++++++++++++++++++++
 include/linux/irqchip/arm-gic-v3.h |  3 +-
 2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index dcc7227af5f1..3c34bef70bdd 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -309,6 +309,10 @@ struct its_cmd_desc {
 			u16 seq_num;
 			u16 its_list;
 		} its_vmovp_cmd;
+
+		struct {
+			struct its_vpe *vpe;
+		} its_invdb_cmd;
 	};
 };
 
@@ -750,6 +754,21 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
 	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
 }
 
+static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
+					   struct its_cmd_block *cmd,
+					   struct its_cmd_desc *desc)
+{
+	if (WARN_ON(!is_v4_1(its)))
+		return NULL;
+
+	its_encode_cmd(cmd, GITS_CMD_INVDB);
+	its_encode_vpeid(cmd, desc->its_invdb_cmd.vpe->vpe_id);
+
+	its_fixup_cmd(cmd);
+
+	return valid_vpe(its, desc->its_invdb_cmd.vpe);
+}
+
 static u64 its_cmd_ptr_to_offset(struct its_node *its,
 				 struct its_cmd_block *ptr)
 {
@@ -1117,6 +1136,14 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
 	its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
 }
 
+static void its_send_invdb(struct its_node *its, struct its_vpe *vpe)
+{
+	struct its_cmd_desc desc;
+
+	desc.its_invdb_cmd.vpe = vpe;
+	its_send_single_vcommand(its, its_build_invdb_cmd, &desc);
+}
+
 /*
  * irqchip functions - assumes MSI, mostly.
  */
@@ -3408,6 +3435,37 @@ static struct irq_chip its_vpe_irq_chip = {
 	.irq_set_vcpu_affinity	= its_vpe_set_vcpu_affinity,
 };
 
+static void its_vpe_4_1_send_inv(struct irq_data *d)
+{
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+	struct its_node *its;
+
+	/*
+	 * GICv4.1 wants doorbells to be invalidated using the
+	 * INVDB command in order to be broadcast to all RDs. Send
+	 * it to the first valid ITS, and let the HW do its magic.
+	 */
+	list_for_each_entry(its, &its_nodes, entry) {
+		if (!is_v4_1(its))
+			continue;
+
+		its_send_invdb(its, vpe);
+		break;
+	}
+}
+
+static void its_vpe_4_1_mask_irq(struct irq_data *d)
+{
+	lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0);
+	its_vpe_4_1_send_inv(d);
+}
+
+static void its_vpe_4_1_unmask_irq(struct irq_data *d)
+{
+	lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED);
+	its_vpe_4_1_send_inv(d);
+}
+
 static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
 	struct its_cmd_info *info = vcpu_info;
@@ -3429,6 +3487,8 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 
 static struct irq_chip its_vpe_4_1_irq_chip = {
 	.name			= "GICv4.1-vpe",
+	.irq_mask		= its_vpe_4_1_mask_irq,
+	.irq_unmask		= its_vpe_4_1_unmask_irq,
 	.irq_eoi		= irq_chip_eoi_parent,
 	.irq_set_affinity	= its_vpe_set_affinity,
 	.irq_set_vcpu_affinity	= its_vpe_4_1_set_vcpu_affinity,
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index f1d6de53e09b..8157737053e4 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -484,8 +484,9 @@
 #define GITS_CMD_VMAPTI			GITS_CMD_GICv4(GITS_CMD_MAPTI)
 #define GITS_CMD_VMOVI			GITS_CMD_GICv4(GITS_CMD_MOVI)
 #define GITS_CMD_VSYNC			GITS_CMD_GICv4(GITS_CMD_SYNC)
-/* VMOVP is the odd one, as it doesn't have a physical counterpart */
+/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
 #define GITS_CMD_VMOVP			GITS_CMD_GICv4(2)
+#define GITS_CMD_INVDB			GITS_CMD_GICv4(0xe)
 
 /*
  * ITS error numbers
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 17/36] irqchip/gic-v4.1: Add VPE residency callback
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (15 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:34   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 18/36] irqchip/gic-v4.1: Add VPE eviction callback Marc Zyngier
                   ` (18 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Making a VPE resident on GICv4.1 is pretty simple, as it is just a
single write to the local redistributor. We just need extra information
about which groups to enable, which the KVM code will have to provide.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 17 +++++++++++++++++
 include/linux/irqchip/arm-gic-v3.h |  9 +++++++++
 include/linux/irqchip/arm-gic-v4.h |  5 +++++
 3 files changed, 31 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 3c34bef70bdd..d45e9b4e5622 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3466,12 +3466,29 @@ static void its_vpe_4_1_unmask_irq(struct irq_data *d)
 	its_vpe_4_1_send_inv(d);
 }
 
+static void its_vpe_4_1_schedule(struct its_vpe *vpe,
+				 struct its_cmd_info *info)
+{
+	void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+	u64 val = 0;
+
+	/* Schedule the VPE */
+	val |= GICR_VPENDBASER_Valid;
+	val |= info->g0en ? GICR_VPENDBASER_4_1_VGRP0EN : 0;
+	val |= info->g1en ? GICR_VPENDBASER_4_1_VGRP1EN : 0;
+	val |= FIELD_PREP(GICR_VPENDBASER_4_1_VPEID, vpe->vpe_id);
+
+	gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+}
+
 static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
 	struct its_cmd_info *info = vcpu_info;
 
 	switch (info->cmd_type) {
 	case SCHEDULE_VPE:
+		its_vpe_4_1_schedule(vpe, info);
 		return 0;
 
 	case DESCHEDULE_VPE:
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 8157737053e4..6fd89d77b2b2 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -327,6 +327,15 @@
 #define GICR_VPENDBASER_IDAI		(1ULL << 62)
 #define GICR_VPENDBASER_Valid		(1ULL << 63)
 
+/*
+ * GICv4.1 VPENDBASER, used for VPE residency. On top of these fields,
+ * also use the above Valid, PendingLast and Dirty.
+ */
+#define GICR_VPENDBASER_4_1_DB		(1ULL << 62)
+#define GICR_VPENDBASER_4_1_VGRP0EN	(1ULL << 59)
+#define GICR_VPENDBASER_4_1_VGRP1EN	(1ULL << 58)
+#define GICR_VPENDBASER_4_1_VPEID	GENMASK_ULL(15, 0)
+
 /*
  * ITS registers, offsets from ITS_base
  */
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index 6213ced6f199..edbaa37fd3f1 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -98,6 +98,11 @@ struct its_cmd_info {
 	union {
 		struct its_vlpi_map	*map;
 		u8			config;
+		bool			req_db;
+		struct {
+			bool		g0en;
+			bool		g1en;
+		};
 	};
 };
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 18/36] irqchip/gic-v4.1: Add VPE eviction callback
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (16 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 17/36] irqchip/gic-v4.1: Add VPE residency callback Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:39   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback Marc Zyngier
                   ` (17 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

When descheduling a VPE, special care must be taken to tell the GIC
about whether we want to receive a doorbell or not. This is a
major improvement on GICv4.0, where the doorbell had to be separately
enabled/disabled.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 53 +++++++++++++++++++++++++-------
 1 file changed, 42 insertions(+), 11 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index d45e9b4e5622..f7effd453729 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -2487,7 +2487,7 @@ static int __init allocate_lpi_tables(void)
 	return 0;
 }
 
-static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
+static u64 its_clear_vpend_valid(void __iomem *vlpi_base, u64 clr, u64 set)
 {
 	u32 count = 1000000;	/* 1s! */
 	bool clean;
@@ -2495,6 +2495,8 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
 
 	val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
 	val &= ~GICR_VPENDBASER_Valid;
+	val &= ~clr;
+	val |= set;
 	gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
 
 	do {
@@ -2507,6 +2509,11 @@ static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
 		}
 	} while (!clean && count);
 
+	if (unlikely(val & GICR_VPENDBASER_Dirty)) {
+		pr_err_ratelimited("ITS virtual pending table not cleaning\n");
+		val |= GICR_VPENDBASER_PendingLast;
+	}
+
 	return val;
 }
 
@@ -2615,7 +2622,7 @@ static void its_cpu_init_lpis(void)
 		 * ancient programming gets left in and has possibility of
 		 * corrupting memory.
 		 */
-		val = its_clear_vpend_valid(vlpi_base);
+		val = its_clear_vpend_valid(vlpi_base, 0, 0);
 		WARN_ON(val & GICR_VPENDBASER_Dirty);
 	}
 
@@ -3293,16 +3300,10 @@ static void its_vpe_deschedule(struct its_vpe *vpe)
 	void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
 	u64 val;
 
-	val = its_clear_vpend_valid(vlpi_base);
+	val = its_clear_vpend_valid(vlpi_base, 0, 0);
 
-	if (unlikely(val & GICR_VPENDBASER_Dirty)) {
-		pr_err_ratelimited("ITS virtual pending table not cleaning\n");
-		vpe->idai = false;
-		vpe->pending_last = true;
-	} else {
-		vpe->idai = !!(val & GICR_VPENDBASER_IDAI);
-		vpe->pending_last = !!(val & GICR_VPENDBASER_PendingLast);
-	}
+	vpe->idai = !!(val & GICR_VPENDBASER_IDAI);
+	vpe->pending_last = !!(val & GICR_VPENDBASER_PendingLast);
 }
 
 static void its_vpe_invall(struct its_vpe *vpe)
@@ -3481,6 +3482,35 @@ static void its_vpe_4_1_schedule(struct its_vpe *vpe,
 	gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
 }
 
+static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
+				   struct its_cmd_info *info)
+{
+	void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+	u64 val;
+
+	if (info->req_db) {
+		/*
+		 * vPE is going to block: make the vPE non-resident with
+		 * PendingLast clear and DB set. The GIC guarantees that if
+		 * we read-back PendingLast clear, then a doorbell will be
+		 * delivered when an interrupt comes.
+		 */
+		val = its_clear_vpend_valid(vlpi_base,
+					    GICR_VPENDBASER_PendingLast,
+					    GICR_VPENDBASER_4_1_DB);
+		vpe->pending_last = !!(val & GICR_VPENDBASER_PendingLast);
+	} else {
+		/*
+		 * We're not blocking, so just make the vPE non-resident
+		 * with PendingLast set, indicating that we'll be back.
+		 */
+		val = its_clear_vpend_valid(vlpi_base,
+					    0,
+					    GICR_VPENDBASER_PendingLast);
+		vpe->pending_last = true;
+	}
+}
+
 static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
 	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
@@ -3492,6 +3522,7 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 		return 0;
 
 	case DESCHEDULE_VPE:
+		its_vpe_4_1_deschedule(vpe, info);
 		return 0;
 
 	case INVALL_VPE:
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (17 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 18/36] irqchip/gic-v4.1: Add VPE eviction callback Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 11:51   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 20/36] irqchip/gic-v4.1: Suppress per-VLPI doorbell Marc Zyngier
                   ` (16 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

GICv4.1 redistributors have a VPE-aware INVALL register. Progress!
We can now emulate a guest-requested INVALL without emiting a
VINVALL command.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 14 ++++++++++++++
 include/linux/irqchip/arm-gic-v3.h |  3 +++
 2 files changed, 17 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index f7effd453729..10bd156aa042 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3511,6 +3511,19 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
 	}
 }
 
+static void its_vpe_4_1_invall(struct its_vpe *vpe)
+{
+	void __iomem *rdbase;
+	u64 val;
+
+	val  = GICR_INVLPIR_V;
+	val |= FIELD_PREP(GICR_INVLPIR_VPEID, vpe->vpe_id);
+
+	/* Target the redistributor this vPE is currently known on */
+	rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
+	gic_write_lpir(val, rdbase + GICR_INVALLR);
+}
+
 static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 {
 	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
@@ -3526,6 +3539,7 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
 		return 0;
 
 	case INVALL_VPE:
+		its_vpe_4_1_invall(vpe);
 		return 0;
 
 	default:
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 6fd89d77b2b2..b69f60792554 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -247,6 +247,9 @@
 #define GICR_TYPER_COMMON_LPI_AFF	GENMASK_ULL(25, 24)
 #define GICR_TYPER_AFFINITY		GENMASK_ULL(63, 32)
 
+#define GICR_INVLPIR_VPEID		GENMASK_ULL(47, 32)
+#define GICR_INVLPIR_V			GENMASK_ULL(63, 63)
+
 #define GIC_V3_REDIST_SIZE		0x20000
 
 #define LPI_PROP_GROUP1			(1 << 1)
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 20/36] irqchip/gic-v4.1: Suppress per-VLPI doorbell
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (18 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 12:17   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 21/36] irqchip/gic-v4.1: Allow direct invalidation of VLPIs Marc Zyngier
                   ` (15 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Since GICv4.1 gives us a per-VPE doorbell, avoid programming anything
else on VMOVI/VMAPI/VMAPTI and on any other action that would have
otherwise resulted in a per-VLPI doorbell to be programmed.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 10bd156aa042..75c4d1a6f20d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -691,7 +691,7 @@ static struct its_vpe *its_build_vmapti_cmd(struct its_node *its,
 {
 	u32 db;
 
-	if (desc->its_vmapti_cmd.db_enabled)
+	if (!is_v4_1(its) && desc->its_vmapti_cmd.db_enabled)
 		db = desc->its_vmapti_cmd.vpe->vpe_db_lpi;
 	else
 		db = 1023;
@@ -714,7 +714,7 @@ static struct its_vpe *its_build_vmovi_cmd(struct its_node *its,
 {
 	u32 db;
 
-	if (desc->its_vmovi_cmd.db_enabled)
+	if (!is_v4_1(its) && desc->its_vmovi_cmd.db_enabled)
 		db = desc->its_vmovi_cmd.vpe->vpe_db_lpi;
 	else
 		db = 1023;
@@ -1227,6 +1227,13 @@ static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 	u32 event = its_get_event_id(d);
 
+	/*
+	 * GICv4.1 does away with the per-LPI nonsense, nothing to do
+	 * here.
+	 */
+	if (is_v4_1(its_dev->its))
+		return;
+
 	if (its_dev->event_map.vlpi_maps[event].db_enabled == enable)
 		return;
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 21/36] irqchip/gic-v4.1: Allow direct invalidation of VLPIs
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (19 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 20/36] irqchip/gic-v4.1: Suppress per-VLPI doorbell Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 12:30   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM Marc Zyngier
                   ` (14 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Just like for INVALL, GICv4.1 has grown a VPE-aware INVLPI register.
Let's plumb it in and make use of the DirectLPI code in that case.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 53 ++++++++++++++++++++----------
 include/linux/irqchip/arm-gic-v3.h |  1 +
 2 files changed, 36 insertions(+), 18 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 75c4d1a6f20d..df259e202482 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -203,11 +203,26 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
 	return its->collections + its_dev->event_map.col_map[event];
 }
 
-static struct its_collection *irq_to_col(struct irq_data *d)
+static struct its_vlpi_map *get_vlpi_map(struct irq_data *d)
 {
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	u32 event = its_get_event_id(d);
+
+	if (!irqd_is_forwarded_to_vcpu(d))
+		return NULL;
 
-	return dev_event_to_col(its_dev, its_get_event_id(d));
+	return &its_dev->event_map.vlpi_maps[event];
+}
+
+static int irq_to_cpuid(struct irq_data *d)
+{
+	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+	struct its_vlpi_map *map = get_vlpi_map(d);
+
+	if (map)
+		return map->vpe->col_idx;
+
+	return its_dev->event_map.col_map[its_get_event_id(d)];
 }
 
 static struct its_collection *valid_col(struct its_collection *col)
@@ -1147,17 +1162,6 @@ static void its_send_invdb(struct its_node *its, struct its_vpe *vpe)
 /*
  * irqchip functions - assumes MSI, mostly.
  */
-static struct its_vlpi_map *get_vlpi_map(struct irq_data *d)
-{
-	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
-	u32 event = its_get_event_id(d);
-
-	if (!irqd_is_forwarded_to_vcpu(d))
-		return NULL;
-
-	return &its_dev->event_map.vlpi_maps[event];
-}
-
 static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
 {
 	struct its_vlpi_map *map = get_vlpi_map(d);
@@ -1200,13 +1204,25 @@ static void wait_for_syncr(void __iomem *rdbase)
 
 static void direct_lpi_inv(struct irq_data *d)
 {
-	struct its_collection *col;
+	struct its_vlpi_map *map = get_vlpi_map(d);
 	void __iomem *rdbase;
+	u64 val;
+
+	if (map) {
+		struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+
+		WARN_ON(!is_v4_1(its_dev->its));
+
+		val  = GICR_INVLPIR_V;
+		val |= FIELD_PREP(GICR_INVLPIR_VPEID, map->vpe->vpe_id);
+		val |= FIELD_PREP(GICR_INVLPIR_INTID, map->vintid);
+	} else {
+		val = d->hwirq;
+	}
 
 	/* Target the redistributor this LPI is currently routed to */
-	col = irq_to_col(d);
-	rdbase = per_cpu_ptr(gic_rdists->rdist, col->col_id)->rd_base;
-	gic_write_lpir(d->hwirq, rdbase + GICR_INVLPIR);
+	rdbase = per_cpu_ptr(gic_rdists->rdist, irq_to_cpuid(d))->rd_base;
+	gic_write_lpir(val, rdbase + GICR_INVLPIR);
 
 	wait_for_syncr(rdbase);
 }
@@ -1216,7 +1232,8 @@ static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
 	struct its_device *its_dev = irq_data_get_irq_chip_data(d);
 
 	lpi_write_config(d, clr, set);
-	if (gic_rdists->has_direct_lpi && !irqd_is_forwarded_to_vcpu(d))
+	if (gic_rdists->has_direct_lpi &&
+	    (is_v4_1(its_dev->its) || !irqd_is_forwarded_to_vcpu(d)))
 		direct_lpi_inv(d);
 	else
 		its_send_inv(its_dev, its_get_event_id(d));
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index b69f60792554..5f3278cbf247 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -247,6 +247,7 @@
 #define GICR_TYPER_COMMON_LPI_AFF	GENMASK_ULL(25, 24)
 #define GICR_TYPER_AFFINITY		GENMASK_ULL(63, 32)
 
+#define GICR_INVLPIR_INTID		GENMASK_ULL(31, 0)
 #define GICR_INVLPIR_VPEID		GENMASK_ULL(47, 32)
 #define GICR_INVLPIR_V			GENMASK_ULL(63, 63)
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (20 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 21/36] irqchip/gic-v4.1: Allow direct invalidation of VLPIs Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-11-01 12:55   ` Zenghui Yu
  2019-10-27 14:42 ` [PATCH v2 23/36] irqchip/gic-v4.1: Map the ITS SGIR register page Marc Zyngier
                   ` (13 subsequent siblings)
  35 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Tell KVM that we support v4.1. Nothing uses this information so far.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c       | 9 ++++++++-
 drivers/irqchip/irq-gic-v3.c           | 1 +
 include/linux/irqchip/arm-gic-common.h | 2 ++
 3 files changed, 11 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index df259e202482..6483f8051b3e 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -4580,6 +4580,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	struct device_node *of_node;
 	struct its_node *its;
 	bool has_v4 = false;
+	bool has_v4_1 = false;
 	int err;
 
 	gic_rdists = rdists;
@@ -4600,8 +4601,14 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 	if (err)
 		return err;
 
-	list_for_each_entry(its, &its_nodes, entry)
+	list_for_each_entry(its, &its_nodes, entry) {
 		has_v4 |= is_v4(its);
+		has_v4_1 |= is_v4_1(its);
+	}
+
+	/* Don't bother with inconsistent systems */
+	if (WARN_ON(!has_v4_1 && rdists->has_rvpeid))
+		rdists->has_rvpeid = false;
 
 	if (has_v4 & rdists->has_vlpis) {
 		if (its_init_vpe_domain() ||
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index f0d33ac64a99..94dddfb21076 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -1758,6 +1758,7 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
 		gic_v3_kvm_info.vcpu = r;
 
 	gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
+	gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;
 	gic_set_kvm_info(&gic_v3_kvm_info);
 }
 
diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h
index b9850f5f1906..fa8c0455c352 100644
--- a/include/linux/irqchip/arm-gic-common.h
+++ b/include/linux/irqchip/arm-gic-common.h
@@ -32,6 +32,8 @@ struct gic_kvm_info {
 	struct resource vctrl;
 	/* vlpi support */
 	bool		has_v4;
+	/* rvpeid support */
+	bool		has_v4_1;
 };
 
 const struct gic_kvm_info *gic_get_kvm_info(void);
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 23/36] irqchip/gic-v4.1: Map the ITS SGIR register page
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (21 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 24/36] irqchip/gic-v4.1: Plumb skeletal VSGI irqchip Marc Zyngier
                   ` (12 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

One of the new features of GICv4.1 is to allow virtual SGIs to be
directly signaled to a VPE. For that, the ITS has grown a new
64kB page containing only a single register that is used to
signal a SGI to a given VPE.

Add a second mapping covering this new 64kB range, and take this
opportunity to limit the original mapping to 64kB, which is enough
to cover the span of the ITS registers.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 15 +++++++++++++--
 1 file changed, 13 insertions(+), 2 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6483f8051b3e..991a70b457b4 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -97,6 +97,7 @@ struct its_node {
 	struct mutex		dev_alloc_lock;
 	struct list_head	entry;
 	void __iomem		*base;
+	void __iomem		*sgir_base;
 	phys_addr_t		phys_base;
 	struct its_cmd_block	*cmd_base;
 	struct its_cmd_block	*cmd_write;
@@ -4166,7 +4167,7 @@ static int __init its_probe_one(struct resource *res,
 	struct page *page;
 	int err;
 
-	its_base = ioremap(res->start, resource_size(res));
+	its_base = ioremap(res->start, SZ_64K);
 	if (!its_base) {
 		pr_warn("ITS@%pa: Unable to map ITS registers\n", &res->start);
 		return -ENOMEM;
@@ -4217,6 +4218,13 @@ static int __init its_probe_one(struct resource *res,
 
 		if (is_v4_1(its)) {
 			u32 svpet = FIELD_GET(GITS_TYPER_SVPET, typer);
+
+			its->sgir_base = ioremap(res->start + SZ_128K, SZ_64K);
+			if (!its->sgir_base) {
+				err = -ENOMEM;
+				goto out_free_its;
+			}
+
 			its->mpidr = readl_relaxed(its_base + GITS_MPIDR);
 
 			pr_info("ITS@%pa: Using GICv4.1 mode %08x %08x\n",
@@ -4230,7 +4238,7 @@ static int __init its_probe_one(struct resource *res,
 				get_order(ITS_CMD_QUEUE_SZ));
 	if (!page) {
 		err = -ENOMEM;
-		goto out_free_its;
+		goto out_unmap_sgir;
 	}
 	its->cmd_base = (void *)page_address(page);
 	its->cmd_write = its->cmd_base;
@@ -4297,6 +4305,9 @@ static int __init its_probe_one(struct resource *res,
 	its_free_tables(its);
 out_free_cmd:
 	free_pages((unsigned long)its->cmd_base, get_order(ITS_CMD_QUEUE_SZ));
+out_unmap_sgir:
+	if (its->sgir_base)
+		iounmap(its->sgir_base);
 out_free_its:
 	kfree(its);
 out_unmap:
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 24/36] irqchip/gic-v4.1: Plumb skeletal VSGI irqchip
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (22 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 23/36] irqchip/gic-v4.1: Map the ITS SGIR register page Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 25/36] irqchip/gic-v4.1: Add initial SGI configuration Marc Zyngier
                   ` (11 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Since GICv4.1 has the capability to inject 16 SGIs into each VPE,
and that I'm keen not to invent too many specific interfaces to
manupulate these interrupts, let's pretend that each of these SGIs
is an actual Linux interrupt.

For that matter, let's introduce a minimal irqchip and irqdomain
setup that will get fleshed up in the following patches.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 68 +++++++++++++++++++++++++++++-
 drivers/irqchip/irq-gic-v4.c       |  8 +++-
 include/linux/irqchip/arm-gic-v4.h |  9 +++-
 3 files changed, 81 insertions(+), 4 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 991a70b457b4..6a3952d3c379 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3581,6 +3581,67 @@ static struct irq_chip its_vpe_4_1_irq_chip = {
 	.irq_set_vcpu_affinity	= its_vpe_4_1_set_vcpu_affinity,
 };
 
+static int its_sgi_set_affinity(struct irq_data *d,
+				const struct cpumask *mask_val,
+				bool force)
+{
+	return -EINVAL;
+}
+
+static struct irq_chip its_sgi_irq_chip = {
+	.name			= "GICv4.1-sgi",
+	.irq_set_affinity	= its_sgi_set_affinity,
+};
+
+static int its_sgi_irq_domain_alloc(struct irq_domain *domain,
+				    unsigned int virq, unsigned int nr_irqs,
+				    void *args)
+{
+	struct its_vpe *vpe = args;
+	int i;
+
+	/* Yes, we do want 16 SGIs */
+	WARN_ON(nr_irqs != 16);
+
+	for (i = 0; i < 16; i++) {
+		vpe->sgi_config[i].priority = 0;
+		vpe->sgi_config[i].enabled = false;
+		vpe->sgi_config[i].group = false;
+
+		irq_domain_set_hwirq_and_chip(domain, virq + i, i,
+					      &its_sgi_irq_chip, vpe);
+		irq_set_status_flags(virq + i, IRQ_DISABLE_UNLAZY);
+	}
+
+	return 0;
+}
+
+static void its_sgi_irq_domain_free(struct irq_domain *domain,
+				    unsigned int virq,
+				    unsigned int nr_irqs)
+{
+	/* Nothing to do */
+}
+
+static int its_sgi_irq_domain_activate(struct irq_domain *domain,
+				       struct irq_data *d, bool reserve)
+{
+	return 0;
+}
+
+static void its_sgi_irq_domain_deactivate(struct irq_domain *domain,
+					  struct irq_data *d)
+{
+	/* Nothing to do */
+}
+
+static struct irq_domain_ops its_sgi_domain_ops = {
+	.alloc		= its_sgi_irq_domain_alloc,
+	.free		= its_sgi_irq_domain_free,
+	.activate	= its_sgi_irq_domain_activate,
+	.deactivate	= its_sgi_irq_domain_deactivate,
+};
+
 static int its_vpe_id_alloc(void)
 {
 	return ida_simple_get(&its_vpeid_ida, 0, ITS_MAX_VPEID, GFP_KERNEL);
@@ -4622,8 +4683,13 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
 		rdists->has_rvpeid = false;
 
 	if (has_v4 & rdists->has_vlpis) {
+		struct irq_domain_ops *sgi_ops = NULL;
+
+		if (has_v4_1)
+			sgi_ops = &its_sgi_domain_ops;
+
 		if (its_init_vpe_domain() ||
-		    its_init_v4(parent_domain, &its_vpe_domain_ops)) {
+		    its_init_v4(parent_domain, &its_vpe_domain_ops, sgi_ops)) {
 			rdists->has_vlpis = false;
 			pr_err("ITS: Disabling GICv4 support\n");
 		}
diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index 45969927cc81..c01910d53f9e 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -85,6 +85,7 @@
 
 static struct irq_domain *gic_domain;
 static const struct irq_domain_ops *vpe_domain_ops;
+static const struct irq_domain_ops *sgi_domain_ops;
 
 int its_alloc_vcpu_irqs(struct its_vm *vm)
 {
@@ -216,12 +217,15 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
 	return irq_set_vcpu_affinity(irq, &info);
 }
 
-int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops)
+int its_init_v4(struct irq_domain *domain,
+		const struct irq_domain_ops *vpe_ops,
+		const struct irq_domain_ops *sgi_ops)
 {
 	if (domain) {
 		pr_info("ITS: Enabling GICv4 support\n");
 		gic_domain = domain;
-		vpe_domain_ops = ops;
+		vpe_domain_ops = vpe_ops;
+		sgi_domain_ops = sgi_ops;
 		return 0;
 	}
 
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index edbaa37fd3f1..03bbd0aed2e2 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -47,6 +47,11 @@ struct its_vpe {
 		};
 		/* GICv4.1 implementations */
 		struct {
+			struct {
+				u8	priority;
+				bool	enabled;
+				bool	group;
+			}			sgi_config[16];
 			atomic_t vmapp_count;
 		};
 	};
@@ -116,6 +121,8 @@ int its_unmap_vlpi(int irq);
 int its_prop_update_vlpi(int irq, u8 config, bool inv);
 
 struct irq_domain_ops;
-int its_init_v4(struct irq_domain *domain, const struct irq_domain_ops *ops);
+int its_init_v4(struct irq_domain *domain,
+		const struct irq_domain_ops *vpe_ops,
+		const struct irq_domain_ops *sgi_ops);
 
 #endif
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 25/36] irqchip/gic-v4.1: Add initial SGI configuration
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (23 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 24/36] irqchip/gic-v4.1: Plumb skeletal VSGI irqchip Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 26/36] irqchip/gic-v4.1: Plumb mask/unmask SGI callbacks Marc Zyngier
                   ` (10 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

The GICv4.1 ITS has yet another new command (VSGI) which allows
a VPE-targeted SGI to be configured (or have its pending state
cleared). Add support for this command and plumb it into the
activate irqdomain callback so that it is ready to be used.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 88 ++++++++++++++++++++++++++++++
 include/linux/irqchip/arm-gic-v3.h |  3 +-
 2 files changed, 90 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 6a3952d3c379..ef5988724aa3 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -329,6 +329,15 @@ struct its_cmd_desc {
 		struct {
 			struct its_vpe *vpe;
 		} its_invdb_cmd;
+
+		struct {
+			struct its_vpe *vpe;
+			u8 sgi;
+			u8 priority;
+			bool enable;
+			bool group;
+			bool clear;
+		} its_vsgi_cmd;
 	};
 };
 
@@ -474,6 +483,31 @@ static void its_encode_db(struct its_cmd_block *cmd, bool db)
 	its_mask_encode(&cmd->raw_cmd[2], db, 63, 63);
 }
 
+static void its_encode_sgi_intid(struct its_cmd_block *cmd, u8 sgi)
+{
+	its_mask_encode(&cmd->raw_cmd[0], sgi, 35, 32);
+}
+
+static void its_encode_sgi_priority(struct its_cmd_block *cmd, u8 prio)
+{
+	its_mask_encode(&cmd->raw_cmd[0], prio >> 4, 23, 20);
+}
+
+static void its_encode_sgi_group(struct its_cmd_block *cmd, bool grp)
+{
+	its_mask_encode(&cmd->raw_cmd[0], grp, 10, 10);
+}
+
+static void its_encode_sgi_clear(struct its_cmd_block *cmd, bool clr)
+{
+	its_mask_encode(&cmd->raw_cmd[0], clr, 9, 9);
+}
+
+static void its_encode_sgi_enable(struct its_cmd_block *cmd, bool en)
+{
+	its_mask_encode(&cmd->raw_cmd[0], en, 8, 8);
+}
+
 static inline void its_fixup_cmd(struct its_cmd_block *cmd)
 {
 	/* Let's fixup BE commands */
@@ -785,6 +819,26 @@ static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
 	return valid_vpe(its, desc->its_invdb_cmd.vpe);
 }
 
+static struct its_vpe *its_build_vsgi_cmd(struct its_node *its,
+					  struct its_cmd_block *cmd,
+					  struct its_cmd_desc *desc)
+{
+	if (WARN_ON(!is_v4_1(its)))
+		return NULL;
+
+	its_encode_cmd(cmd, GITS_CMD_VSGI);
+	its_encode_vpeid(cmd, desc->its_vsgi_cmd.vpe->vpe_id);
+	its_encode_sgi_intid(cmd, desc->its_vsgi_cmd.sgi);
+	its_encode_sgi_priority(cmd, desc->its_vsgi_cmd.priority);
+	its_encode_sgi_group(cmd, desc->its_vsgi_cmd.group);
+	its_encode_sgi_clear(cmd, desc->its_vsgi_cmd.clear);
+	its_encode_sgi_enable(cmd, desc->its_vsgi_cmd.enable);
+
+	its_fixup_cmd(cmd);
+
+	return valid_vpe(its, desc->its_vsgi_cmd.vpe);
+}
+
 static u64 its_cmd_ptr_to_offset(struct its_node *its,
 				 struct its_cmd_block *ptr)
 {
@@ -3581,6 +3635,38 @@ static struct irq_chip its_vpe_4_1_irq_chip = {
 	.irq_set_vcpu_affinity	= its_vpe_4_1_set_vcpu_affinity,
 };
 
+static struct its_node *find_4_1_its(void)
+{
+	static struct its_node *its = NULL;
+
+	if (!its) {
+		list_for_each_entry(its, &its_nodes, entry) {
+			if (is_v4_1(its))
+				return its;
+		}
+
+		/* Oops? */
+		its = NULL;
+	}
+
+	return its;
+}
+
+static void its_configure_sgi(struct irq_data *d, bool clear)
+{
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+	struct its_cmd_desc desc;
+
+	desc.its_vsgi_cmd.vpe = vpe;
+	desc.its_vsgi_cmd.sgi = d->hwirq;
+	desc.its_vsgi_cmd.priority = vpe->sgi_config[d->hwirq].priority;
+	desc.its_vsgi_cmd.enable = vpe->sgi_config[d->hwirq].enabled;
+	desc.its_vsgi_cmd.group = vpe->sgi_config[d->hwirq].group;
+	desc.its_vsgi_cmd.clear = clear;
+
+	its_send_single_vcommand(find_4_1_its(), its_build_vsgi_cmd, &desc);
+}
+
 static int its_sgi_set_affinity(struct irq_data *d,
 				const struct cpumask *mask_val,
 				bool force)
@@ -3626,6 +3712,8 @@ static void its_sgi_irq_domain_free(struct irq_domain *domain,
 static int its_sgi_irq_domain_activate(struct irq_domain *domain,
 				       struct irq_data *d, bool reserve)
 {
+	/* Write out the initial SGI configuration */
+	its_configure_sgi(d, false);
 	return 0;
 }
 
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 5f3278cbf247..c73176d3ab2b 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -497,8 +497,9 @@
 #define GITS_CMD_VMAPTI			GITS_CMD_GICv4(GITS_CMD_MAPTI)
 #define GITS_CMD_VMOVI			GITS_CMD_GICv4(GITS_CMD_MOVI)
 #define GITS_CMD_VSYNC			GITS_CMD_GICv4(GITS_CMD_SYNC)
-/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
+/* VMOVP, VSGI and INVDB are the odd ones, as they dont have a physical counterpart */
 #define GITS_CMD_VMOVP			GITS_CMD_GICv4(2)
+#define GITS_CMD_VSGI			GITS_CMD_GICv4(3)
 #define GITS_CMD_INVDB			GITS_CMD_GICv4(0xe)
 
 /*
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 26/36] irqchip/gic-v4.1: Plumb mask/unmask SGI callbacks
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (24 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 25/36] irqchip/gic-v4.1: Add initial SGI configuration Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 27/36] irqchip/gic-v4.1: Plumb get/set_irqchip_state " Marc Zyngier
                   ` (9 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Implement mask/unmask for virtual SGIs by calling into the
configuration helper.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 18 ++++++++++++++++++
 1 file changed, 18 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index ef5988724aa3..b9cef419f006 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3667,6 +3667,22 @@ static void its_configure_sgi(struct irq_data *d, bool clear)
 	its_send_single_vcommand(find_4_1_its(), its_build_vsgi_cmd, &desc);
 }
 
+static void its_sgi_mask_irq(struct irq_data *d)
+{
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+
+	vpe->sgi_config[d->hwirq].enabled = false;
+	its_configure_sgi(d, false);
+}
+
+static void its_sgi_unmask_irq(struct irq_data *d)
+{
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+
+	vpe->sgi_config[d->hwirq].enabled = true;
+	its_configure_sgi(d, false);
+}
+
 static int its_sgi_set_affinity(struct irq_data *d,
 				const struct cpumask *mask_val,
 				bool force)
@@ -3676,6 +3692,8 @@ static int its_sgi_set_affinity(struct irq_data *d,
 
 static struct irq_chip its_sgi_irq_chip = {
 	.name			= "GICv4.1-sgi",
+	.irq_mask		= its_sgi_mask_irq,
+	.irq_unmask		= its_sgi_unmask_irq,
 	.irq_set_affinity	= its_sgi_set_affinity,
 };
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 27/36] irqchip/gic-v4.1: Plumb get/set_irqchip_state SGI callbacks
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (25 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 26/36] irqchip/gic-v4.1: Plumb mask/unmask SGI callbacks Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 28/36] irqchip/gic-v4.1: Plumb set_vcpu_affinity " Marc Zyngier
                   ` (8 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

To implement the get/set_irqchip_state callbacks (limited to the
PENDING state), we have to use a particular set of hacks:

- Reading the pending state is done by using a pair of new redistributor
  registers (GICR_VSGIR, GICR_VSGIPENDR), which allow the 16 interrupts
  state to be retrieved.
- Setting the pending state is done by generating it as we'd otherwise do
  for a guest (writing to GITS_SGIR)
- Clearing the pending state is done by emiting a VSGI command with the
  "clear" bit set.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 56 ++++++++++++++++++++++++++++++
 include/linux/irqchip/arm-gic-v3.h | 14 ++++++++
 2 files changed, 70 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index b9cef419f006..58dd497dc274 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3690,11 +3690,67 @@ static int its_sgi_set_affinity(struct irq_data *d,
 	return -EINVAL;
 }
 
+static int its_sgi_set_irqchip_state(struct irq_data *d,
+				     enum irqchip_irq_state which,
+				     bool state)
+{
+	if (which != IRQCHIP_STATE_PENDING)
+		return -EINVAL;
+
+	if (state) {
+		struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+		struct its_node *its = find_4_1_its();
+		u64 val;
+
+		val  = FIELD_PREP(GITS_SGIR_VPEID, vpe->vpe_id);
+		val |= FIELD_PREP(GITS_SGIR_VINTID, d->hwirq);
+		writeq_relaxed(val, its->sgir_base + GITS_SGIR - SZ_128K);
+	} else {
+		its_configure_sgi(d, true);
+	}
+
+	return 0;
+}
+
+static int its_sgi_get_irqchip_state(struct irq_data *d,
+				     enum irqchip_irq_state which, bool *val)
+{
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+	void __iomem *base = gic_data_rdist_cpu(vpe->col_idx)->rd_base + SZ_128K;
+	u32 count = 1000000;	/* 1s! */
+	u32 status;
+
+	if (which != IRQCHIP_STATE_PENDING)
+		return -EINVAL;
+
+	writel_relaxed(vpe->vpe_id, base + GICR_VSGIR);
+	do {
+		status = readl_relaxed(base + GICR_VSGIPENDR);
+		if (!(status & GICR_VSGIPENDR_BUSY))
+			goto out;
+
+		count--;
+		if (!count) {
+			pr_err_ratelimited("Unable to get SGI status\n");
+			goto out;
+		}
+		cpu_relax();
+		udelay(1);
+	} while(count);
+
+out:
+	*val = !!(status & (1 << d->hwirq));
+
+	return 0;
+}
+
 static struct irq_chip its_sgi_irq_chip = {
 	.name			= "GICv4.1-sgi",
 	.irq_mask		= its_sgi_mask_irq,
 	.irq_unmask		= its_sgi_unmask_irq,
 	.irq_set_affinity	= its_sgi_set_affinity,
+	.irq_set_irqchip_state	= its_sgi_set_irqchip_state,
+	.irq_get_irqchip_state	= its_sgi_get_irqchip_state,
 };
 
 static int its_sgi_irq_domain_alloc(struct irq_domain *domain,
diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c73176d3ab2b..cb8563554ed2 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -340,6 +340,15 @@
 #define GICR_VPENDBASER_4_1_VGRP1EN	(1ULL << 58)
 #define GICR_VPENDBASER_4_1_VPEID	GENMASK_ULL(15, 0)
 
+#define GICR_VSGIR			0x0080
+
+#define GICR_VSGIR_VPEID		GENMASK(15, 0)
+
+#define GICR_VSGIPENDR			0x0088
+
+#define GICR_VSGIPENDR_BUSY		(1U << 31)
+#define GICR_VSGIPENDR_PENDING		GENMASK(15, 0)
+
 /*
  * ITS registers, offsets from ITS_base
  */
@@ -363,6 +372,11 @@
 
 #define GITS_TRANSLATER			0x10040
 
+#define GITS_SGIR			0x20020
+
+#define GITS_SGIR_VPEID			GENMASK_ULL(47, 32)
+#define GITS_SGIR_VINTID		GENMASK_ULL(7, 0)
+
 #define GITS_CTLR_ENABLE		(1U << 0)
 #define GITS_CTLR_ImDe			(1U << 1)
 #define	GITS_CTLR_ITS_NUMBER_SHIFT	4
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 28/36] irqchip/gic-v4.1: Plumb set_vcpu_affinity SGI callbacks
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (26 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 27/36] irqchip/gic-v4.1: Plumb get/set_irqchip_state " Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 29/36] irqchip/gic-v4.1: Move doorbell management to the GICv4 abstraction layer Marc Zyngier
                   ` (7 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

As for VLPIs, there is a number of configuration bits that cannot
be directly communicated through the normal irqchip API, and we
have to use our good old friend set_vcpu_affinity.

This is used to configure group and priority for a given vSGI.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c   | 18 ++++++++++++++++++
 include/linux/irqchip/arm-gic-v4.h |  5 +++++
 2 files changed, 23 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 58dd497dc274..03ba4964a7f5 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -3744,6 +3744,23 @@ static int its_sgi_get_irqchip_state(struct irq_data *d,
 	return 0;
 }
 
+static int its_sgi_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
+{
+	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
+	struct its_cmd_info *info = vcpu_info;
+
+	switch (info->cmd_type) {
+	case PROP_UPDATE_SGI:
+		vpe->sgi_config[d->hwirq].priority = info->priority;
+		vpe->sgi_config[d->hwirq].group = info->group;
+		its_configure_sgi(d, false);
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+}
+
 static struct irq_chip its_sgi_irq_chip = {
 	.name			= "GICv4.1-sgi",
 	.irq_mask		= its_sgi_mask_irq,
@@ -3751,6 +3768,7 @@ static struct irq_chip its_sgi_irq_chip = {
 	.irq_set_affinity	= its_sgi_set_affinity,
 	.irq_set_irqchip_state	= its_sgi_set_irqchip_state,
 	.irq_get_irqchip_state	= its_sgi_get_irqchip_state,
+	.irq_set_vcpu_affinity	= its_sgi_set_vcpu_affinity,
 };
 
 static int its_sgi_irq_domain_alloc(struct irq_domain *domain,
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index 03bbd0aed2e2..6185926e4582 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -96,6 +96,7 @@ enum its_vcpu_info_cmd_type {
 	SCHEDULE_VPE,
 	DESCHEDULE_VPE,
 	INVALL_VPE,
+	PROP_UPDATE_SGI,
 };
 
 struct its_cmd_info {
@@ -108,6 +109,10 @@ struct its_cmd_info {
 			bool		g0en;
 			bool		g1en;
 		};
+		struct {
+			u8		priority;
+			bool		group;
+		};
 	};
 };
 
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 29/36] irqchip/gic-v4.1: Move doorbell management to the GICv4 abstraction layer
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (27 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 28/36] irqchip/gic-v4.1: Plumb set_vcpu_affinity " Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 30/36] irqchip/gic-v4.1: Add VSGI allocation/teardown Marc Zyngier
                   ` (6 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

In order to hide some of the differences between v4.0 and v4.1, move
the doorbell management out of the KVM code, and into the GICv4-specific
layer. This allows the calling code to ask for the doorbell when blocking,
and otherwise to leave the doorbell permanently disabled.

This matches the v4.1 code perfectly, and only results in a minor
refactoring of the v4.0 code.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v4.c       | 49 +++++++++++++++++++++++++++---
 include/kvm/arm_vgic.h             |  1 +
 include/linux/irqchip/arm-gic-v4.h |  3 +-
 virt/kvm/arm/vgic/vgic-v3.c        |  1 +
 virt/kvm/arm/vgic/vgic-v4.c        | 34 +++++++++------------
 5 files changed, 63 insertions(+), 25 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index c01910d53f9e..60b51d6683aa 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -87,6 +87,11 @@ static struct irq_domain *gic_domain;
 static const struct irq_domain_ops *vpe_domain_ops;
 static const struct irq_domain_ops *sgi_domain_ops;
 
+static bool has_v4_1(void)
+{
+	return !!sgi_domain_ops;
+}
+
 int its_alloc_vcpu_irqs(struct its_vm *vm)
 {
 	int vpe_base_irq, i;
@@ -139,18 +144,54 @@ static int its_send_vpe_cmd(struct its_vpe *vpe, struct its_cmd_info *info)
 	return irq_set_vcpu_affinity(vpe->irq, info);
 }
 
-int its_schedule_vpe(struct its_vpe *vpe, bool on)
+int its_make_vpe_non_resident(struct its_vpe *vpe, bool db)
 {
-	struct its_cmd_info info;
+	struct irq_desc *desc = irq_to_desc(vpe->irq);
+	struct its_cmd_info info = { };
 	int ret;
 
 	WARN_ON(preemptible());
 
-	info.cmd_type = on ? SCHEDULE_VPE : DESCHEDULE_VPE;
+	info.cmd_type = DESCHEDULE_VPE;
+	if (has_v4_1()) {
+		/* GICv4.1 can directly deal with doorbells */
+		info.req_db = db;
+	} else {
+		/* Undo the nested disable_irq() calls... */
+		while (db && irqd_irq_disabled(&desc->irq_data))
+			enable_irq(vpe->irq);
+	}
+
+	ret = its_send_vpe_cmd(vpe, &info);
+	if (!ret)
+		vpe->resident = false;
+
+	return ret;
+}
+
+int its_make_vpe_resident(struct its_vpe *vpe)
+{
+	struct its_cmd_info info = { };
+	int ret;
+
+	WARN_ON(preemptible());
+
+	info.cmd_type = SCHEDULE_VPE;
+	if (has_v4_1()) {
+		/*
+		 * FIXME: This needs to come from the distributor, and
+		 * not be blindly set out of thin air...
+		 */
+		info.g0en = true;
+		info.g1en = true;
+	} else {
+		/* Disabled the doorbell, as we're about to enter the guest */
+		disable_irq_nosync(vpe->irq);
+	}
 
 	ret = its_send_vpe_cmd(vpe, &info);
 	if (!ret)
-		vpe->resident = on;
+		vpe->resident = true;
 
 	return ret;
 }
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 4dc58d7a0010..86cb95171eec 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -70,6 +70,7 @@ struct vgic_global {
 
 	/* Hardware has GICv4? */
 	bool			has_gicv4;
+	bool			has_gicv4_1;
 
 	/* GIC system register CPU interface */
 	struct static_key_false gicv3_cpuif;
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index 6185926e4582..084890a5c2bf 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -118,7 +118,8 @@ struct its_cmd_info {
 
 int its_alloc_vcpu_irqs(struct its_vm *vm);
 void its_free_vcpu_irqs(struct its_vm *vm);
-int its_schedule_vpe(struct its_vpe *vpe, bool on);
+int its_make_vpe_resident(struct its_vpe *vpe);
+int its_make_vpe_non_resident(struct its_vpe *vpe, bool db);
 int its_invall_vpe(struct its_vpe *vpe);
 int its_map_vlpi(int irq, struct its_vlpi_map *map);
 int its_get_vlpi(int irq, struct its_vlpi_map *map);
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 48307a9eb1d8..07a33b3e71c5 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -595,6 +595,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	/* GICv4 support? */
 	if (info->has_v4) {
 		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
+		kvm_vgic_global_state.has_gicv4_1 = info->has_v4_1;
 		kvm_info("GICv4 support %sabled\n",
 			 gicv4_enable ? "en" : "dis");
 	}
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 7e1f3202968a..50f84f4ce903 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -67,10 +67,10 @@
  * it. And if we've migrated our vcpu from one CPU to another, we must
  * tell the ITS (so that the messages reach the right redistributor).
  * This is done in two steps: first issue a irq_set_affinity() on the
- * irq corresponding to the vcpu, then call its_schedule_vpe(). You
- * must be in a non-preemptible context. On exit, another call to
- * its_schedule_vpe() tells the redistributor that we're done with the
- * vcpu.
+ * irq corresponding to the vcpu, then call its_make_vpe_resident().
+ * You must be in a non-preemptible context. On exit, a call to
+ * its_make_vpe_non_resident() tells the redistributor that we're done
+ * with the vcpu.
  *
  * Finally, the doorbell handling: Each vcpu is allocated an interrupt
  * which will fire each time a VLPI is made pending whilst the vcpu is
@@ -86,7 +86,8 @@ static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 	struct kvm_vcpu *vcpu = info;
 
 	/* We got the message, no need to fire again */
-	if (!irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
+	if (!kvm_vgic_global_state.has_gicv4_1 &&
+	    !irqd_irq_disabled(&irq_to_desc(irq)->irq_data))
 		disable_irq_nosync(irq);
 
 	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
@@ -199,19 +200,11 @@ void vgic_v4_teardown(struct kvm *kvm)
 int vgic_v4_put(struct kvm_vcpu *vcpu, bool need_db)
 {
 	struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
-	struct irq_desc *desc = irq_to_desc(vpe->irq);
 
 	if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
 		return 0;
 
-	/*
-	 * If blocking, a doorbell is required. Undo the nested
-	 * disable_irq() calls...
-	 */
-	while (need_db && irqd_irq_disabled(&desc->irq_data))
-		enable_irq(vpe->irq);
-
-	return its_schedule_vpe(vpe, false);
+	return its_make_vpe_non_resident(vpe, need_db);
 }
 
 int vgic_v4_load(struct kvm_vcpu *vcpu)
@@ -232,18 +225,19 @@ int vgic_v4_load(struct kvm_vcpu *vcpu)
 	if (err)
 		return err;
 
-	/* Disabled the doorbell, as we're about to enter the guest */
-	disable_irq_nosync(vpe->irq);
-
-	err = its_schedule_vpe(vpe, true);
+	err = its_make_vpe_resident(vpe);
 	if (err)
 		return err;
 
 	/*
 	 * Now that the VPE is resident, let's get rid of a potential
-	 * doorbell interrupt that would still be pending.
+	 * doorbell interrupt that would still be pending. This is a
+	 * GICv4.0 only "feature"...
 	 */
-	return irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
+	if (!kvm_vgic_global_state.has_gicv4_1)
+		err = irq_set_irqchip_state(vpe->irq, IRQCHIP_STATE_PENDING, false);
+
+	return err;
 }
 
 static struct vgic_its *vgic_get_its(struct kvm *kvm,
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 30/36] irqchip/gic-v4.1: Add VSGI allocation/teardown
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (28 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 29/36] irqchip/gic-v4.1: Move doorbell management to the GICv4 abstraction layer Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 31/36] irqchip/gic-v4.1: Add VSGI property setup Marc Zyngier
                   ` (5 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Allocate per-VPE SGIs when initializing the GIC-specific part of the
VPE data structure.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v4.c       | 68 +++++++++++++++++++++++++++++-
 include/linux/irqchip/arm-gic-v4.h |  2 +
 2 files changed, 69 insertions(+), 1 deletion(-)

diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index 60b51d6683aa..a29a063861bc 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -92,6 +92,47 @@ static bool has_v4_1(void)
 	return !!sgi_domain_ops;
 }
 
+static int its_alloc_vcpu_sgis(struct its_vpe *vpe, int idx)
+{
+	char *name;
+	int sgi_base;
+
+	if (!has_v4_1())
+		return 0;
+
+	name = kasprintf(GFP_KERNEL, "GICv4-sgi-%d", task_pid_nr(current));
+	if (!name)
+		goto err;
+
+	vpe->fwnode = irq_domain_alloc_named_id_fwnode(name, idx);
+	if (!vpe->fwnode)
+		goto err;
+
+	kfree(name);
+	name = NULL;
+
+	vpe->sgi_domain = irq_domain_create_linear(vpe->fwnode, 16,
+						   sgi_domain_ops, vpe);
+	if (!vpe->sgi_domain)
+		goto err;
+
+	sgi_base = __irq_domain_alloc_irqs(vpe->sgi_domain, -1, 16,
+					       NUMA_NO_NODE, vpe,
+					       false, NULL);
+	if (sgi_base <= 0)
+		goto err;
+
+	return 0;
+
+err:
+	if (vpe->sgi_domain)
+		irq_domain_remove(vpe->sgi_domain);
+	if (vpe->fwnode)
+		irq_domain_free_fwnode(vpe->fwnode);
+	kfree(name);
+	return -ENOMEM;
+}
+
 int its_alloc_vcpu_irqs(struct its_vm *vm)
 {
 	int vpe_base_irq, i;
@@ -118,8 +159,13 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
 	if (vpe_base_irq <= 0)
 		goto err;
 
-	for (i = 0; i < vm->nr_vpes; i++)
+	for (i = 0; i < vm->nr_vpes; i++) {
+		int ret;
 		vm->vpes[i]->irq = vpe_base_irq + i;
+		ret = its_alloc_vcpu_sgis(vm->vpes[i], i);
+		if (ret)
+			goto err;
+	}
 
 	return 0;
 
@@ -132,8 +178,28 @@ int its_alloc_vcpu_irqs(struct its_vm *vm)
 	return -ENOMEM;
 }
 
+static void its_free_sgi_irqs(struct its_vm *vm)
+{
+	int i;
+
+	if (!has_v4_1())
+		return;
+
+	for (i = 0; i < vm->nr_vpes; i++) {
+		unsigned int irq = irq_find_mapping(vm->vpes[i]->sgi_domain, 0);
+
+		if (WARN_ON(!irq))
+			continue;
+
+		irq_domain_free_irqs(irq, 16);
+		irq_domain_remove(vm->vpes[i]->sgi_domain);
+		irq_domain_free_fwnode(vm->vpes[i]->fwnode);
+	}
+}
+
 void its_free_vcpu_irqs(struct its_vm *vm)
 {
+	its_free_sgi_irqs(vm);
 	irq_domain_free_irqs(vm->vpes[0]->irq, vm->nr_vpes);
 	irq_domain_remove(vm->domain);
 	irq_domain_free_fwnode(vm->fwnode);
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index 084890a5c2bf..5578cbe7430b 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -47,6 +47,8 @@ struct its_vpe {
 		};
 		/* GICv4.1 implementations */
 		struct {
+			struct fwnode_handle	*fwnode;
+			struct irq_domain	*sgi_domain;
 			struct {
 				u8	priority;
 				bool	enabled;
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 31/36] irqchip/gic-v4.1: Add VSGI property setup
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (29 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 30/36] irqchip/gic-v4.1: Add VSGI allocation/teardown Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 32/36] irqchip/gic-v4.1: Eagerly vmap vPEs Marc Zyngier
                   ` (4 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Add the SGI configuration entry point for KVM to use.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v4.c       | 13 +++++++++++++
 include/linux/irqchip/arm-gic-v4.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/drivers/irqchip/irq-gic-v4.c b/drivers/irqchip/irq-gic-v4.c
index a29a063861bc..b937e51a9178 100644
--- a/drivers/irqchip/irq-gic-v4.c
+++ b/drivers/irqchip/irq-gic-v4.c
@@ -324,6 +324,19 @@ int its_prop_update_vlpi(int irq, u8 config, bool inv)
 	return irq_set_vcpu_affinity(irq, &info);
 }
 
+int its_prop_update_vsgi(int irq, u8 priority, bool group)
+{
+	struct its_cmd_info info = {
+		.cmd_type = PROP_UPDATE_SGI,
+		{
+			.priority	= priority,
+			.group		= group,
+		},
+	};
+
+	return irq_set_vcpu_affinity(irq, &info);
+}
+
 int its_init_v4(struct irq_domain *domain,
 		const struct irq_domain_ops *vpe_ops,
 		const struct irq_domain_ops *sgi_ops)
diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
index 5578cbe7430b..b894796df9ab 100644
--- a/include/linux/irqchip/arm-gic-v4.h
+++ b/include/linux/irqchip/arm-gic-v4.h
@@ -127,6 +127,7 @@ int its_map_vlpi(int irq, struct its_vlpi_map *map);
 int its_get_vlpi(int irq, struct its_vlpi_map *map);
 int its_unmap_vlpi(int irq);
 int its_prop_update_vlpi(int irq, u8 config, bool inv);
+int its_prop_update_vsgi(int irq, u8 priority, bool group);
 
 struct irq_domain_ops;
 int its_init_v4(struct irq_domain *domain,
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 32/36] irqchip/gic-v4.1: Eagerly vmap vPEs
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (30 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 31/36] irqchip/gic-v4.1: Add VSGI property setup Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 33/36] KVM: arm64: GICv4.1: Let doorbells be auto-enabled Marc Zyngier
                   ` (3 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Now that we have HW-accelerated SGIs being delivered to VPEs, it
becomes required to map the VPEs on all ITSs instead of relying
on the lazy approach that we would use when using the ITS-list
mechanism.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 drivers/irqchip/irq-gic-v3-its.c | 39 +++++++++++++++++++++++++-------
 1 file changed, 31 insertions(+), 8 deletions(-)

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 03ba4964a7f5..796c5937ec15 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1419,12 +1419,31 @@ static int its_irq_set_irqchip_state(struct irq_data *d,
 	return 0;
 }
 
+/*
+ * Two favourable cases:
+ *
+ * (a) Either we have a GICv4.1, and all vPEs have to be mapped at all times
+ *     for vSGI delivery
+ *
+ * (b) Or the ITSs do not use a list map, meaning that VMOVP is cheap enough
+ *     and we're better off mapping all VPEs always
+ *
+ * If neither (a) nor (b) is true, then we map vPEs on demand.
+ *
+ */
+static bool gic_requires_eager_mapping(void)
+{
+	if (!its_list_map || gic_rdists->has_rvpeid)
+		return true;
+
+	return false;
+}
+
 static void its_map_vm(struct its_node *its, struct its_vm *vm)
 {
 	unsigned long flags;
 
-	/* Not using the ITS list? Everything is always mapped. */
-	if (!its_list_map)
+	if (gic_requires_eager_mapping())
 		return;
 
 	raw_spin_lock_irqsave(&vmovp_lock, flags);
@@ -1458,7 +1477,7 @@ static void its_unmap_vm(struct its_node *its, struct its_vm *vm)
 	unsigned long flags;
 
 	/* Not using the ITS list? Everything is always mapped. */
-	if (!its_list_map)
+	if (gic_requires_eager_mapping())
 		return;
 
 	raw_spin_lock_irqsave(&vmovp_lock, flags);
@@ -3964,8 +3983,12 @@ static int its_vpe_irq_domain_activate(struct irq_domain *domain,
 	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
 	struct its_node *its;
 
-	/* If we use the list map, we issue VMAPP on demand... */
-	if (its_list_map)
+	/*
+	 * If we use the list map, we issue VMAPP on demand... Unless
+	 * we're on a GICv4.1 and we eagerly map the VPE on all ITSs
+	 * so that VSGIs can work.
+	 */
+	if (!gic_requires_eager_mapping())
 		return 0;
 
 	/* Map the VPE to the first possible CPU */
@@ -3991,10 +4014,10 @@ static void its_vpe_irq_domain_deactivate(struct irq_domain *domain,
 	struct its_node *its;
 
 	/*
-	 * If we use the list map, we unmap the VPE once no VLPIs are
-	 * associated with the VM.
+	 * If we use the list map on GICv4.0, we unmap the VPE once no
+	 * VLPIs are associated with the VM.
 	 */
-	if (its_list_map)
+	if (!gic_requires_eager_mapping())
 		return;
 
 	list_for_each_entry(its, &its_nodes, entry) {
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 33/36] KVM: arm64: GICv4.1: Let doorbells be auto-enabled
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (31 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 32/36] irqchip/gic-v4.1: Eagerly vmap vPEs Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 34/36] KVM: arm64: GICv4.1: Add direct injection capability to SGI registers Marc Zyngier
                   ` (2 subsequent siblings)
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

As GICv4.1 understands the life cycle of doorbells (instead of
just randomly firing them at the most inconvenient time), just
enable them at irq_request time, and be done with it.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 virt/kvm/arm/vgic/vgic-v4.c | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 50f84f4ce903..e61c7a149515 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -141,6 +141,7 @@ int vgic_v4_init(struct kvm *kvm)
 
 	kvm_for_each_vcpu(i, vcpu, kvm) {
 		int irq = dist->its_vm.vpes[i]->irq;
+		unsigned long irq_flags = DB_IRQ_FLAGS;
 
 		/*
 		 * Don't automatically enable the doorbell, as we're
@@ -148,8 +149,14 @@ int vgic_v4_init(struct kvm *kvm)
 		 * blocked. Also disable the lazy disabling, as the
 		 * doorbell could kick us out of the guest too
 		 * early...
+		 *
+		 * On GICv4.1, the doorbell is managed in HW and must
+		 * be left enabled.
 		 */
-		irq_set_status_flags(irq, DB_IRQ_FLAGS);
+		if (kvm_vgic_global_state.has_gicv4_1)
+			irq_flags &= ~IRQ_NOAUTOEN;
+		irq_set_status_flags(irq, irq_flags);
+
 		ret = request_irq(irq, vgic_v4_doorbell_handler,
 				  0, "vcpu", vcpu);
 		if (ret) {
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 34/36] KVM: arm64: GICv4.1: Add direct injection capability to SGI registers
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (32 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 33/36] KVM: arm64: GICv4.1: Let doorbells be auto-enabled Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 35/36] KVM: arm64: GICv4.1: Configure SGIs as HW interrupts Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 36/36] KVM: arm64: GICv4.1: Expose HW-based SGIs in debugfs Marc Zyngier
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Most of the GICv3 emulation code that deals with SGIs now has to be
aware of the v4.1 capabilities in order to benefit from it.

Add such support, keyed on the interrupt having the hw flag set and
being a SGI.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 15 +++++-
 virt/kvm/arm/vgic/vgic-mmio.c    | 88 ++++++++++++++++++++++++++++++--
 2 files changed, 96 insertions(+), 7 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 7dfd15dbb308..d73f4ffd7d36 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -6,6 +6,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
+#include <linux/interrupt.h>
 #include <kvm/iodev.h>
 #include <kvm/arm_vgic.h>
 
@@ -939,8 +940,18 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
 		 * generate interrupts of either group.
 		 */
 		if (!irq->group || allow_group1) {
-			irq->pending_latch = true;
-			vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+			if (!irq->hw) {
+				irq->pending_latch = true;
+				vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+			} else {
+				/* HW SGI? Ask the GIC to inject it */
+				int err;
+				err = irq_set_irqchip_state(irq->host_irq,
+							    IRQCHIP_STATE_PENDING,
+							    true);
+				WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+				raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+			}
 		} else {
 			raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 		}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 0d090482720d..6ebf747a7806 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -5,6 +5,8 @@
 
 #include <linux/bitops.h>
 #include <linux/bsearch.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <kvm/iodev.h>
@@ -59,6 +61,11 @@ unsigned long vgic_mmio_read_group(struct kvm_vcpu *vcpu,
 	return value;
 }
 
+static void vgic_update_vsgi(struct vgic_irq *irq)
+{
+	WARN_ON(its_prop_update_vsgi(irq->host_irq, irq->priority, irq->group));
+}
+
 void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
 			   unsigned int len, unsigned long val)
 {
@@ -71,7 +78,12 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
 
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
 		irq->group = !!(val & BIT(i));
-		vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+		if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+			vgic_update_vsgi(irq);
+			raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+		} else {
+			vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
+		}
 
 		vgic_put_irq(vcpu->kvm, irq);
 	}
@@ -113,7 +125,21 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
-		if (vgic_irq_is_mapped_level(irq)) {
+		if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+			if (!irq->enabled) {
+				struct irq_data *data;
+
+				irq->enabled = true;
+				data = &irq_to_desc(irq->host_irq)->irq_data;
+				while (irqd_irq_disabled(data))
+					enable_irq(irq->host_irq);
+			}
+
+			raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+			vgic_put_irq(vcpu->kvm, irq);
+
+			continue;
+		} else if (vgic_irq_is_mapped_level(irq)) {
 			bool was_high = irq->line_level;
 
 			/*
@@ -148,6 +174,8 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
+		if (irq->hw && vgic_irq_is_sgi(irq->intid) && irq->enabled)
+			disable_irq_nosync(irq->host_irq);
 
 		irq->enabled = false;
 
@@ -167,10 +195,22 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
 	for (i = 0; i < len * 8; i++) {
 		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 		unsigned long flags;
+		bool val;
 
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
-		if (irq_is_pending(irq))
-			value |= (1U << i);
+		if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+			int err;
+
+			val = false;
+			err = irq_get_irqchip_state(irq->host_irq,
+						    IRQCHIP_STATE_PENDING,
+						    &val);
+			WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+		} else {
+			val = irq_is_pending(irq);
+		}
+
+		value |= ((u32)val << i);
 		raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
 		vgic_put_irq(vcpu->kvm, irq);
@@ -236,6 +276,21 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
 		}
 
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
+
+		if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+			/* HW SGI? Ask the GIC to inject it */
+			int err;
+			err = irq_set_irqchip_state(irq->host_irq,
+						    IRQCHIP_STATE_PENDING,
+						    true);
+			WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+
+			raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+			vgic_put_irq(vcpu->kvm, irq);
+
+			continue;
+		}
+
 		if (irq->hw)
 			vgic_hw_irq_spending(vcpu, irq, is_uaccess);
 		else
@@ -290,6 +345,20 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
 
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
+		if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+			/* HW SGI? Ask the GIC to inject it */
+			int err;
+			err = irq_set_irqchip_state(irq->host_irq,
+						    IRQCHIP_STATE_PENDING,
+						    false);
+			WARN_RATELIMIT(err, "IRQ %d", irq->host_irq);
+
+			raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
+			vgic_put_irq(vcpu->kvm, irq);
+
+			continue;
+		}
+
 		if (irq->hw)
 			vgic_hw_irq_cpending(vcpu, irq, is_uaccess);
 		else
@@ -339,8 +408,15 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
 
 	raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
-	if (irq->hw) {
+	if (irq->hw && !vgic_irq_is_sgi(irq->intid)) {
 		vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
+	} else if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+		/*
+		 * GICv4.1 VSGI feature doesn't track an active state,
+		 * so let's not kid ourselves, there is nothing we can
+		 * do here.
+		 */
+		irq->active = false;
 	} else {
 		u32 model = vcpu->kvm->arch.vgic.vgic_model;
 		u8 active_source;
@@ -514,6 +590,8 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
 		raw_spin_lock_irqsave(&irq->irq_lock, flags);
 		/* Narrow the priority range to what we actually support */
 		irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
+		if (irq->hw && vgic_irq_is_sgi(irq->intid))
+			vgic_update_vsgi(irq);
 		raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
 		vgic_put_irq(vcpu->kvm, irq);
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 35/36] KVM: arm64: GICv4.1: Configure SGIs as HW interrupts
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (33 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 34/36] KVM: arm64: GICv4.1: Add direct injection capability to SGI registers Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  2019-10-27 14:42 ` [PATCH v2 36/36] KVM: arm64: GICv4.1: Expose HW-based SGIs in debugfs Marc Zyngier
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

To enable HW delivery of SGIs, set their hw flag to true, link them
to the corresponding Linux interrupt, which is then activated.

This configures the SGIs at the ITS level, and put the show
on the road!

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 virt/kvm/arm/vgic/vgic-v4.c | 42 +++++++++++++++++++++++++++++++++++++
 1 file changed, 42 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index e61c7a149515..0ff6dac16cba 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -97,6 +97,46 @@ static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 	return IRQ_HANDLED;
 }
 
+static void vgic_v4_sync_sgi_config(struct its_vpe *vpe, struct vgic_irq *irq)
+{
+	vpe->sgi_config[irq->intid].enabled	= irq->enabled;
+	vpe->sgi_config[irq->intid].group 	= irq->group;
+	vpe->sgi_config[irq->intid].priority	= irq->priority;
+}
+
+static void vgic_v4_init_vsgis(struct kvm_vcpu *vcpu)
+{
+	struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+	int i;
+
+	if (!kvm_vgic_global_state.has_gicv4_1)
+		return;
+
+	/*
+	 * With GICv4.1, every virtual SGI can be directly injected. So
+	 * let's pretend that they are HW interrupts, tied to a host
+	 * IRQ. The SGI code will do its magic.
+	 */
+	for (i = 0; i < VGIC_NR_SGIS; i++) {
+		struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, i);
+		struct irq_desc *desc;
+		int ret;
+
+		irq->hw = true;
+		irq->host_irq = irq_find_mapping(vpe->sgi_domain, i);
+		vgic_v4_sync_sgi_config(vpe, irq);
+		/*
+		 * SGIs are initialised as disabled. Enable them if
+		 * required by the rest of the VGIC init code.
+		 */
+		desc = irq_to_desc(irq->host_irq);
+		ret = irq_domain_activate_irq(irq_desc_get_irq_data(desc),
+					      false);
+		WARN_ON(ret);
+		vgic_put_irq(vcpu->kvm, irq);
+	}
+}
+
 /**
  * vgic_v4_init - Initialize the GICv4 data structures
  * @kvm:	Pointer to the VM being initialized
@@ -168,6 +208,8 @@ int vgic_v4_init(struct kvm *kvm)
 			dist->its_vm.nr_vpes = i;
 			break;
 		}
+
+		vgic_v4_init_vsgis(vcpu);
 	}
 
 	if (ret)
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* [PATCH v2 36/36] KVM: arm64: GICv4.1: Expose HW-based SGIs in debugfs
  2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
                   ` (34 preceding siblings ...)
  2019-10-27 14:42 ` [PATCH v2 35/36] KVM: arm64: GICv4.1: Configure SGIs as HW interrupts Marc Zyngier
@ 2019-10-27 14:42 ` Marc Zyngier
  35 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-27 14:42 UTC (permalink / raw)
  To: kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

The vgic-state debugfs file could do with showing the pending state
of the HW-backed SGIs. Plug it into the low-level code.

Signed-off-by: Marc Zyngier <maz@kernel.org>
---
 virt/kvm/arm/vgic/vgic-debug.c | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-debug.c b/virt/kvm/arm/vgic/vgic-debug.c
index cc12fe9b2df3..98f3242a34a6 100644
--- a/virt/kvm/arm/vgic/vgic-debug.c
+++ b/virt/kvm/arm/vgic/vgic-debug.c
@@ -178,6 +178,8 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
 			    struct kvm_vcpu *vcpu)
 {
 	char *type;
+	bool pending;
+
 	if (irq->intid < VGIC_NR_SGIS)
 		type = "SGI";
 	else if (irq->intid < VGIC_NR_PRIVATE_IRQS)
@@ -190,6 +192,16 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
 	if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS)
 		print_header(s, irq, vcpu);
 
+	pending = irq->pending_latch;
+	if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
+		int err;
+
+		err = irq_get_irqchip_state(irq->host_irq,
+					    IRQCHIP_STATE_PENDING,
+					    &pending);
+		WARN_ON_ONCE(err);
+	}
+		
 	seq_printf(s, "       %s %4d "
 		      "    %2d "
 		      "%d%d%d%d%d%d%d "
@@ -201,7 +213,7 @@ static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
 		      "\n",
 			type, irq->intid,
 			(irq->target_vcpu) ? irq->target_vcpu->vcpu_id : -1,
-			irq->pending_latch,
+		   	pending,
 			irq->line_level,
 			irq->active,
 			irq->enabled,
-- 
2.20.1

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 02/36] irqchip/gic-v3-its: Factor out wait_for_syncr primitive
  2019-10-27 14:42 ` [PATCH v2 02/36] irqchip/gic-v3-its: Factor out wait_for_syncr primitive Marc Zyngier
@ 2019-10-28  9:20   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-10-28  9:20 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

On 2019/10/27 22:42, Marc Zyngier wrote:
> Waiting for a redistributor to have performed an operation is a
> common thing to do, and the idiom is already spread around.
> As we're going to make even more use of this, let's have a primitive
> that does just that.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy
  2019-10-27 14:42 ` [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy Marc Zyngier
@ 2019-10-28  9:34   ` Zenghui Yu
  2019-10-28 10:52     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-10-28  9:34 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Instead of caching the GICv4 compatibility in a discrete way, cache the
> TYPER register instead, which can then be used to implement the same
> functionnality. This will get used more extensively in subsequent patches.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

nit: You may need to rebase some patches on top of mainline when
you finally decide to take them in, i.e., as we currently have
get_its_list(), which will use the legacy its->is_v4.

Besides,

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 05/36] irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead
  2019-10-27 14:42 ` [PATCH v2 05/36] irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead Marc Zyngier
@ 2019-10-28  9:40   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-10-28  9:40 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

On 2019/10/27 22:42, Marc Zyngier wrote:
> Now that we have a copy of TYPER in the ITS structure, rely on this
> to provide the same service as its->ite_size, which gets axed.
> Errata workarounds are now updating the cached fields instead of
> requiring a separate field in the ITS structure.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy
  2019-10-28  9:34   ` Zenghui Yu
@ 2019-10-28 10:52     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-10-28 10:52 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On Mon, 28 Oct 2019 09:34:42 +0000,
Zenghui Yu <yuzenghui@huawei.com> wrote:
> 
> Hi Marc,
> 
> On 2019/10/27 22:42, Marc Zyngier wrote:
> > Instead of caching the GICv4 compatibility in a discrete way, cache the
> > TYPER register instead, which can then be used to implement the same
> > functionnality. This will get used more extensively in subsequent patches.
> > 
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> 
> nit: You may need to rebase some patches on top of mainline when
> you finally decide to take them in, i.e., as we currently have
> get_its_list(), which will use the legacy its->is_v4.

Yeah, I was planning on rebasing the whole irqchip-next branch on top
of -rc5 to avoid this kind of problems.

> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

Thanks for that.

	M.

-- 
Jazz is not dead, it just smells funny.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 07/36] irqchip/gic-v3-its: Add get_vlpi_map() helper
  2019-10-27 14:42 ` [PATCH v2 07/36] irqchip/gic-v3-its: Add get_vlpi_map() helper Marc Zyngier
@ 2019-10-31  3:54   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-10-31  3:54 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

On 2019/10/27 22:42, Marc Zyngier wrote:
> Obtaining the mapping information for a VLPI is something quite common,
> and the GICv4.1 code is going to make even more use of it. Expose it as
> a separate helper.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids and use TYPER copy instead
  2019-10-27 14:42 ` [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids " Marc Zyngier
@ 2019-10-31  6:33   ` Zenghui Yu
  2019-10-31  8:30     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-10-31  6:33 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Now that we have a copy of TYPER in the ITS structure, rely on this
> to provide the same service as its->device_ids, which gets axed.
> Errata workarounds are now updating the cached fields instead of
> requiring a separate field in the ITS structure.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

> ---
>   drivers/irqchip/irq-gic-v3-its.c   | 24 +++++++++++++-----------
>   include/linux/irqchip/arm-gic-v3.h |  2 +-
>   2 files changed, 14 insertions(+), 12 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 3b046181ddfc..6c91c7feadf3 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -109,7 +109,6 @@ struct its_node {
>   	struct list_head	its_device_list;
>   	u64			flags;
>   	unsigned long		list_nr;
> -	u32			device_ids;
>   	int			numa_node;
>   	unsigned int		msi_domain_flags;
>   	u32			pre_its_base; /* for Socionext Synquacer */
> @@ -117,6 +116,7 @@ struct its_node {
>   };
>   
>   #define is_v4(its)		(!!((its)->typer & GITS_TYPER_VLPIS))
> +#define device_ids(its)		(FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1)
>   
>   #define ITS_ITT_ALIGN		SZ_256
>   
> @@ -1938,9 +1938,9 @@ static bool its_parse_indirect_baser(struct its_node *its,
>   	if (new_order >= MAX_ORDER) {
>   		new_order = MAX_ORDER - 1;
>   		ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
> -		pr_warn("ITS@%pa: %s Table too large, reduce ids %u->%u\n",
> +		pr_warn("ITS@%pa: %s Table too large, reduce ids %llu->%u\n",
>   			&its->phys_base, its_base_type_string[type],
> -			its->device_ids, ids);
> +			device_ids(its), ids);

But this pr_warn() looks a bit odd. The table type is chosen from
its_base_type_string[], but ids is always Devbits (+1)?


Thanks,
Zenghui

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids and use TYPER copy instead
  2019-10-31  6:33   ` Zenghui Yu
@ 2019-10-31  8:30     ` Marc Zyngier
  2019-10-31  9:08       ` Zenghui Yu
  0 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-10-31  8:30 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

Hi Zenghui,

On Thu, 31 Oct 2019 06:33:23 +0000,
Zenghui Yu <yuzenghui@huawei.com> wrote:
> 
> Hi Marc,
> 
> On 2019/10/27 22:42, Marc Zyngier wrote:
> > Now that we have a copy of TYPER in the ITS structure, rely on this
> > to provide the same service as its->device_ids, which gets axed.
> > Errata workarounds are now updating the cached fields instead of
> > requiring a separate field in the ITS structure.
> > 
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> 
> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

Thanks for that.

> 
> > ---
> >   drivers/irqchip/irq-gic-v3-its.c   | 24 +++++++++++++-----------
> >   include/linux/irqchip/arm-gic-v3.h |  2 +-
> >   2 files changed, 14 insertions(+), 12 deletions(-)
> > 
> > diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> > index 3b046181ddfc..6c91c7feadf3 100644
> > --- a/drivers/irqchip/irq-gic-v3-its.c
> > +++ b/drivers/irqchip/irq-gic-v3-its.c
> > @@ -109,7 +109,6 @@ struct its_node {
> >   	struct list_head	its_device_list;
> >   	u64			flags;
> >   	unsigned long		list_nr;
> > -	u32			device_ids;
> >   	int			numa_node;
> >   	unsigned int		msi_domain_flags;
> >   	u32			pre_its_base; /* for Socionext Synquacer */
> > @@ -117,6 +116,7 @@ struct its_node {
> >   };
> >     #define is_v4(its)		(!!((its)->typer &
> > GITS_TYPER_VLPIS))
> > +#define device_ids(its)		(FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1)
> >     #define ITS_ITT_ALIGN		SZ_256
> >   @@ -1938,9 +1938,9 @@ static bool its_parse_indirect_baser(struct
> > its_node *its,
> >   	if (new_order >= MAX_ORDER) {
> >   		new_order = MAX_ORDER - 1;
> >   		ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
> > -		pr_warn("ITS@%pa: %s Table too large, reduce ids %u->%u\n",
> > +		pr_warn("ITS@%pa: %s Table too large, reduce ids %llu->%u\n",
> >   			&its->phys_base, its_base_type_string[type],
> > -			its->device_ids, ids);
> > +			device_ids(its), ids);
> 
> But this pr_warn() looks a bit odd. The table type is chosen from
> its_base_type_string[], but ids is always Devbits (+1)?

This is a bit of a shortcut, I agree. But the device table practically
is the only one where we can run out of space if the ITS doesn't
support two level tables. All the other tables are very small, being
limited by the number of CPUs (collections) or a small ID space
(vPEs).

So while this is a bit ugly, I don't thing it is not too concerning.

Thanks,

	M.

-- 
Jazz is not dead, it just smells funny.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface
  2019-10-27 14:42 ` [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface Marc Zyngier
@ 2019-10-31  8:49   ` Zenghui Yu
  2019-11-01 13:26     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-10-31  8:49 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> We currently don't make much use of the DirectLPI feature, and it would
> be beneficial to do this more, if only because it becomes a mandatory
> feature for GICv4.1.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

I have no objection to this patch, which says:

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>


But this patch really drives me to look through all callsites of
dev_event_to_col(), the abstraction which can be used _only_ with
physical LPI mappings.

I find that when building the INV command, we use dev_event_to_col()
to find the "sync_obj" and then pass it to the following SYNC command.
But the "INV+SYNC" will be performed both on physical LPI and *VLPI*
(lpi_update_config/its_send_inv).
So I have two questions about the way we sending INV on VLPI:

1) Which "sync" command should be followed?  SYNC or VSYNC?
(we currently use SYNC, while the spec says, SYNC "ensures all
outstanding ITS operations associated with *physical* interrupts
for the Redistributor are globally observed ...")

2) The "sync_obj" we are currently using seems to be wrong.


Thanks,
Zenghui

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids and use TYPER copy instead
  2019-10-31  8:30     ` Marc Zyngier
@ 2019-10-31  9:08       ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-10-31  9:08 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On 2019/10/31 16:30, Marc Zyngier wrote:
> Hi Zenghui,
> 
> On Thu, 31 Oct 2019 06:33:23 +0000,
> Zenghui Yu <yuzenghui@huawei.com> wrote:
>>
>> Hi Marc,
>>
>> On 2019/10/27 22:42, Marc Zyngier wrote:
>>> Now that we have a copy of TYPER in the ITS structure, rely on this
>>> to provide the same service as its->device_ids, which gets axed.
>>> Errata workarounds are now updating the cached fields instead of
>>> requiring a separate field in the ITS structure.
>>>
>>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>>
>> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
> 
> Thanks for that.
> 
>>
>>> ---
>>>    drivers/irqchip/irq-gic-v3-its.c   | 24 +++++++++++++-----------
>>>    include/linux/irqchip/arm-gic-v3.h |  2 +-
>>>    2 files changed, 14 insertions(+), 12 deletions(-)
>>>
>>> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
>>> index 3b046181ddfc..6c91c7feadf3 100644
>>> --- a/drivers/irqchip/irq-gic-v3-its.c
>>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>>> @@ -109,7 +109,6 @@ struct its_node {
>>>    	struct list_head	its_device_list;
>>>    	u64			flags;
>>>    	unsigned long		list_nr;
>>> -	u32			device_ids;
>>>    	int			numa_node;
>>>    	unsigned int		msi_domain_flags;
>>>    	u32			pre_its_base; /* for Socionext Synquacer */
>>> @@ -117,6 +116,7 @@ struct its_node {
>>>    };
>>>      #define is_v4(its)		(!!((its)->typer &
>>> GITS_TYPER_VLPIS))
>>> +#define device_ids(its)		(FIELD_GET(GITS_TYPER_DEVBITS, (its)->typer) + 1)
>>>      #define ITS_ITT_ALIGN		SZ_256
>>>    @@ -1938,9 +1938,9 @@ static bool its_parse_indirect_baser(struct
>>> its_node *its,
>>>    	if (new_order >= MAX_ORDER) {
>>>    		new_order = MAX_ORDER - 1;
>>>    		ids = ilog2(PAGE_ORDER_TO_SIZE(new_order) / (int)esz);
>>> -		pr_warn("ITS@%pa: %s Table too large, reduce ids %u->%u\n",
>>> +		pr_warn("ITS@%pa: %s Table too large, reduce ids %llu->%u\n",
>>>    			&its->phys_base, its_base_type_string[type],
>>> -			its->device_ids, ids);
>>> +			device_ids(its), ids);
>>
>> But this pr_warn() looks a bit odd. The table type is chosen from
>> its_base_type_string[], but ids is always Devbits (+1)?
> 
> This is a bit of a shortcut, I agree. But the device table practically
> is the only one where we can run out of space if the ITS doesn't
> support two level tables. All the other tables are very small, being
> limited by the number of CPUs (collections) or a small ID space
> (vPEs).

Make sense. Thanks for the clarification.


Zenghui

> 
> So while this is a bit ugly, I don't thing it is not too concerning.
> 
> Thanks,
> 
> 	M.
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 08/36] irqchip/gic-v3: Detect GICv4.1 supporting RVPEID
  2019-10-27 14:42 ` [PATCH v2 08/36] irqchip/gic-v3: Detect GICv4.1 supporting RVPEID Marc Zyngier
@ 2019-10-31 11:34   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-10-31 11:34 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> GICv4.1 supports the RVPEID ("Residency per vPE ID"), which allows for
> a much efficient way of making virtual CPUs resident (to allow direct
> injection of interrupts).
> 
> The functionnality needs to be discovered on each and every redistributor
> in the system, and disabled if the settings are inconsistent.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery
  2019-10-27 14:42 ` [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery Marc Zyngier
@ 2019-10-31 12:02   ` Zenghui Yu
  2019-11-01 15:13     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-10-31 12:02 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> While GICv4.0 mandates 16 bit worth of VPEIDs, GICv4.1 allows smaller
> implementations to be built. Add the required glue to dynamically
> compute the limit.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>   drivers/irqchip/irq-gic-v3-its.c   | 11 ++++++++++-
>   drivers/irqchip/irq-gic-v3.c       |  3 +++
>   include/linux/irqchip/arm-gic-v3.h |  5 +++++
>   3 files changed, 18 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 94c9c2e9f917..40912b3fb0e1 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -121,7 +121,16 @@ struct its_node {
>   #define ITS_ITT_ALIGN		SZ_256
>   
>   /* The maximum number of VPEID bits supported by VLPI commands */
> -#define ITS_MAX_VPEID_BITS	(16)
> +#define ITS_MAX_VPEID_BITS						\
> +	({								\
> +		int nvpeid = 16;					\
> +		if (gic_rdists->has_rvpeid &&				\
> +		    gic_rdists->gicd_typer2 & GICD_TYPER2_VIL)		\
> +			nvpeid = 1 + (gic_rdists->gicd_typer2 &		\
> +				      GICD_TYPER2_VID);			\

Does it make sense to let nvpeid not more than 16 here? As the spec says
"Values above 0x0F are RESERVED". But I don't know why should we have
this restriction ;-)

Either way,

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>


Thanks

> +									\
> +		nvpeid;							\
> +	})
>   #define ITS_MAX_VPEID		(1 << (ITS_MAX_VPEID_BITS))
>   
>   /* Convert page order to size in bytes */
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index 4f20caf9bc88..50538709bd49 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -1556,6 +1556,9 @@ static int __init gic_init_bases(void __iomem *dist_base,
>   
>   	pr_info("%d SPIs implemented\n", GIC_LINE_NR - 32);
>   	pr_info("%d Extended SPIs implemented\n", GIC_ESPI_NR);
> +
> +	gic_data.rdists.gicd_typer2 = readl_relaxed(gic_data.dist_base + GICD_TYPER2);
> +
>   	gic_data.domain = irq_domain_create_tree(handle, &gic_irq_domain_ops,
>   						 &gic_data);
>   	irq_domain_update_bus_token(gic_data.domain, DOMAIN_BUS_WIRED);
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index c98f34296599..8c6be56da7e9 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -13,6 +13,7 @@
>   #define GICD_CTLR			0x0000
>   #define GICD_TYPER			0x0004
>   #define GICD_IIDR			0x0008
> +#define GICD_TYPER2			0x000C
>   #define GICD_STATUSR			0x0010
>   #define GICD_SETSPI_NSR			0x0040
>   #define GICD_CLRSPI_NSR			0x0048
> @@ -89,6 +90,9 @@
>   #define GICD_TYPER_ESPIS(typer)						\
>   	(((typer) & GICD_TYPER_ESPI) ? GICD_TYPER_SPIS((typer) >> 27) : 0)
>   
> +#define GICD_TYPER2_VIL			(1U << 7)
> +#define GICD_TYPER2_VID			GENMASK(4, 0)
> +
>   #define GICD_IROUTER_SPI_MODE_ONE	(0U << 31)
>   #define GICD_IROUTER_SPI_MODE_ANY	(1U << 31)
>   
> @@ -613,6 +617,7 @@ struct rdists {
>   	void			*prop_table_va;
>   	u64			flags;
>   	u32			gicd_typer;
> +	u32			gicd_typer2;
>   	bool			has_vlpis;
>   	bool			has_rvpeid;
>   	bool			has_direct_lpi;
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP
  2019-10-27 14:42 ` [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP Marc Zyngier
@ 2019-11-01 10:58   ` Zenghui Yu
  2019-11-13  8:02   ` Zenghui Yu
  1 sibling, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 10:58 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> The ITS VMAPP command gains some new fields with GICv4.1:
> - a default doorbell, which allows a single doorbell to be used for
>    all the VLPIs routed to a given VPE
> - a pointer to the configuration table (instead of having it in a register
>    that gets context switched)
> - a flag indicating whether this is the first map or the last unmap for
>    this particulat VPE

particular

> - a flag indicating whether the pending table is known to be zeroed, or not
> 
> Plumb in the new fields in the VMAPP builder, and add the map/unmap
> refcounting so that the ITS can do the right thing.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

> ---
>   drivers/irqchip/irq-gic-v3-its.c   | 60 +++++++++++++++++++++++++++---
>   include/linux/irqchip/arm-gic-v4.h | 18 +++++++--
>   2 files changed, 69 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 478d3678850c..220d490d516e 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -422,6 +422,27 @@ static void its_encode_vpt_size(struct its_cmd_block *cmd, u8 vpt_size)
>   	its_mask_encode(&cmd->raw_cmd[3], vpt_size, 4, 0);
>   }
>   
> +static void its_encode_vconf_addr(struct its_cmd_block *cmd, u64 vconf_pa)
> +{
> +	its_mask_encode(&cmd->raw_cmd[0], vconf_pa >> 16, 51, 16);
> +}
> +
> +static void its_encode_alloc(struct its_cmd_block *cmd, bool alloc)
> +{
> +	its_mask_encode(&cmd->raw_cmd[0], alloc, 8, 8);
> +}
> +
> +static void its_encode_ptz(struct its_cmd_block *cmd, bool ptz)
> +{
> +	its_mask_encode(&cmd->raw_cmd[0], ptz, 9, 9);
> +}
> +
> +static void its_encode_vmapp_default_db(struct its_cmd_block *cmd,
> +					u32 vpe_db_lpi)
> +{
> +	its_mask_encode(&cmd->raw_cmd[1], vpe_db_lpi, 31, 0);
> +}
> +
>   static inline void its_fixup_cmd(struct its_cmd_block *cmd)
>   {
>   	/* Let's fixup BE commands */
> @@ -605,19 +626,45 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
>   					   struct its_cmd_block *cmd,
>   					   struct its_cmd_desc *desc)
>   {
> -	unsigned long vpt_addr;
> +	unsigned long vpt_addr, vconf_addr;
>   	u64 target;
> -
> -	vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
> -	target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
> +	bool alloc;
>   
>   	its_encode_cmd(cmd, GITS_CMD_VMAPP);
>   	its_encode_vpeid(cmd, desc->its_vmapp_cmd.vpe->vpe_id);
>   	its_encode_valid(cmd, desc->its_vmapp_cmd.valid);
> +
> +	if (!desc->its_vmapp_cmd.valid) {
> +		if (is_v4_1(its)) {
> +			alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
> +			its_encode_alloc(cmd, alloc);
> +		}
> +
> +		goto out;

(note to myself, the reason for "goto out" here is that in GICv4.1,
the remaining field are RES0 when V==0.)


Thanks,
Zenghui

> +	}
> +
> +	vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
> +	target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
> +
>   	its_encode_target(cmd, target);
>   	its_encode_vpt_addr(cmd, vpt_addr);
>   	its_encode_vpt_size(cmd, LPI_NRBITS - 1);
>   
> +	if (!is_v4_1(its))
> +		goto out;
> +
> +	vconf_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page));
> +
> +	alloc = atomic_inc_and_test(&desc->its_vmapp_cmd.vpe->vmapp_count);
> +
> +	its_encode_alloc(cmd, alloc);
> +
> +	/* We can only signal PTZ when alloc==1. Why do we have two bits? */
> +	its_encode_ptz(cmd, alloc);
> +	its_encode_vconf_addr(cmd, vconf_addr);
> +	its_encode_vmapp_default_db(cmd, desc->its_vmapp_cmd.vpe->vpe_db_lpi);
> +
> +out:
>   	its_fixup_cmd(cmd);
>   
>   	return valid_vpe(its, desc->its_vmapp_cmd.vpe);
> @@ -3349,7 +3396,10 @@ static int its_vpe_init(struct its_vpe *vpe)
>   
>   	vpe->vpe_id = vpe_id;
>   	vpe->vpt_page = vpt_page;
> -	vpe->vpe_proxy_event = -1;
> +	if (gic_rdists->has_rvpeid)
> +		atomic_set(&vpe->vmapp_count, 0);
> +	else
> +		vpe->vpe_proxy_event = -1;
>   
>   	return 0;
>   }
> diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
> index ab1396afe08a..6213ced6f199 100644
> --- a/include/linux/irqchip/arm-gic-v4.h
> +++ b/include/linux/irqchip/arm-gic-v4.h
> @@ -37,8 +37,20 @@ struct its_vpe {
>   	irq_hw_number_t		vpe_db_lpi;
>   	/* VPE resident */
>   	bool			resident;
> -	/* VPE proxy mapping */
> -	int			vpe_proxy_event;
> +	union {
> +		/* GICv4.0 implementations */
> +		struct {
> +			/* VPE proxy mapping */
> +			int	vpe_proxy_event;
> +			/* Implementation Defined Area Invalid */
> +			bool	idai;
> +		};
> +		/* GICv4.1 implementations */
> +		struct {
> +			atomic_t vmapp_count;
> +		};
> +	};
> +
>   	/*
>   	 * This collection ID is used to indirect the target
>   	 * redistributor for this VPE. The ID itself isn't involved in
> @@ -47,8 +59,6 @@ struct its_vpe {
>   	u16			col_idx;
>   	/* Unique (system-wide) VPE identifier */
>   	u16			vpe_id;
> -	/* Implementation Defined Area Invalid */
> -	bool			idai;
>   	/* Pending VLPIs on schedule out? */
>   	bool			pending_last;
>   };
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set
  2019-10-27 14:42 ` [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set Marc Zyngier
@ 2019-11-01 11:05   ` Zenghui Yu
  2019-12-18 14:39     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:05 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> The infamous VPE proxy device isn't used with GICv4.1 because:
> - we can invalidate any LPI from the DirectLPI MMIO interface
> - the ITS and redistributors understand the life cycle of
>    the doorbell, so we don't need to enable/disable it all
>    the time
> 
> So let's escape early from the proxy related functions.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

> ---
>   drivers/irqchip/irq-gic-v3-its.c | 23 ++++++++++++++++++++++-
>   1 file changed, 22 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 220d490d516e..999e61a9b2c3 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -3069,7 +3069,7 @@ static const struct irq_domain_ops its_domain_ops = {
>   /*
>    * This is insane.
>    *
> - * If a GICv4 doesn't implement Direct LPIs (which is extremely
> + * If a GICv4.0 doesn't implement Direct LPIs (which is extremely
>    * likely), the only way to perform an invalidate is to use a fake
>    * device to issue an INV command, implying that the LPI has first
>    * been mapped to some event on that device. Since this is not exactly
> @@ -3077,9 +3077,18 @@ static const struct irq_domain_ops its_domain_ops = {
>    * only issue an UNMAP if we're short on available slots.
>    *
>    * Broken by design(tm).
> + *
> + * GICv4.1 actually mandates that we're able to invalidate by writing to a
> + * MMIO register. It doesn't implement the whole of DirectLPI, but that's
> + * good enough. And most of the time, we don't even have to invalidate
> + * anything, so that's actually pretty good!

I can't understand the meaning of this last sentence. May I ask for an
explanation? :)


Thanks,
Zenghui

>    */
>   static void its_vpe_db_proxy_unmap_locked(struct its_vpe *vpe)
>   {
> +	/* GICv4.1 doesn't use a proxy, so nothing to do here */
> +	if (gic_rdists->has_rvpeid)
> +		return;
> +
>   	/* Already unmapped? */
>   	if (vpe->vpe_proxy_event == -1)
>   		return;
> @@ -3102,6 +3111,10 @@ static void its_vpe_db_proxy_unmap_locked(struct its_vpe *vpe)
>   
>   static void its_vpe_db_proxy_unmap(struct its_vpe *vpe)
>   {
> +	/* GICv4.1 doesn't use a proxy, so nothing to do here */
> +	if (gic_rdists->has_rvpeid)
> +		return;
> +
>   	if (!gic_rdists->has_direct_lpi) {
>   		unsigned long flags;
>   
> @@ -3113,6 +3126,10 @@ static void its_vpe_db_proxy_unmap(struct its_vpe *vpe)
>   
>   static void its_vpe_db_proxy_map_locked(struct its_vpe *vpe)
>   {
> +	/* GICv4.1 doesn't use a proxy, so nothing to do here */
> +	if (gic_rdists->has_rvpeid)
> +		return;
> +
>   	/* Already mapped? */
>   	if (vpe->vpe_proxy_event != -1)
>   		return;
> @@ -3135,6 +3152,10 @@ static void its_vpe_db_proxy_move(struct its_vpe *vpe, int from, int to)
>   	unsigned long flags;
>   	struct its_collection *target_col;
>   
> +	/* GICv4.1 doesn't use a proxy, so nothing to do here */
> +	if (gic_rdists->has_rvpeid)
> +		return;
> +
>   	if (gic_rdists->has_direct_lpi) {
>   		void __iomem *rdbase;
>   
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 14/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP
  2019-10-27 14:42 ` [PATCH v2 14/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP Marc Zyngier
@ 2019-11-01 11:10   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:10 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> With GICv4.1, VMOVP is extended to allow a default doorbell to be
> specified, as well as a validity bit for this doorbell. As an added
> bonus, VMOPVP isn't required anymore of moving a VPE between
         ^^^^^^
VMOVP

> redistributors that share the same affinity.
> 
> Let's add this support to the VMOVP builder, and make sure we don't
> issuer the command if we don't really need to.

issue

> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 15/36] irqchip/gic-v4.1: Plumb skeletal VPE irqchip
  2019-10-27 14:42 ` [PATCH v2 15/36] irqchip/gic-v4.1: Plumb skeletal VPE irqchip Marc Zyngier
@ 2019-11-01 11:13   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:13 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Just like for GICv4.0, each VPE has its own doorbell interrupt, and
> thus an irqchip that manages them. Since the doorbell management is
> quite different on GICv4.1, let's introduce an almost empty irqchip
> the will get populated over the next new patches.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks
  2019-10-27 14:42 ` [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks Marc Zyngier
@ 2019-11-01 11:23   ` Zenghui Yu
  2019-12-18 15:06     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:23 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> masking/unmasking doorbells on GICv4.1 relies on a new INVDB command,
> which broadcasts the invalidation to all RDs.
> 
> Implement the new command as well as the masking callbacks, and plug
> the whole thing into the v4.1 VPE irqchip.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

> ---
>   drivers/irqchip/irq-gic-v3-its.c   | 60 ++++++++++++++++++++++++++++++
>   include/linux/irqchip/arm-gic-v3.h |  3 +-
>   2 files changed, 62 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index dcc7227af5f1..3c34bef70bdd 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -309,6 +309,10 @@ struct its_cmd_desc {
>   			u16 seq_num;
>   			u16 its_list;
>   		} its_vmovp_cmd;
> +
> +		struct {
> +			struct its_vpe *vpe;
> +		} its_invdb_cmd;
>   	};
>   };
>   
> @@ -750,6 +754,21 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
>   	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
>   }
>   
> +static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
> +					   struct its_cmd_block *cmd,
> +					   struct its_cmd_desc *desc)
> +{
> +	if (WARN_ON(!is_v4_1(its)))
> +		return NULL;
> +
> +	its_encode_cmd(cmd, GITS_CMD_INVDB);
> +	its_encode_vpeid(cmd, desc->its_invdb_cmd.vpe->vpe_id);
> +
> +	its_fixup_cmd(cmd);
> +
> +	return valid_vpe(its, desc->its_invdb_cmd.vpe);
> +}
> +
>   static u64 its_cmd_ptr_to_offset(struct its_node *its,
>   				 struct its_cmd_block *ptr)
>   {
> @@ -1117,6 +1136,14 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
>   	its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
>   }
>   
> +static void its_send_invdb(struct its_node *its, struct its_vpe *vpe)
> +{
> +	struct its_cmd_desc desc;
> +
> +	desc.its_invdb_cmd.vpe = vpe;
> +	its_send_single_vcommand(its, its_build_invdb_cmd, &desc);
> +}
> +
>   /*
>    * irqchip functions - assumes MSI, mostly.
>    */
> @@ -3408,6 +3435,37 @@ static struct irq_chip its_vpe_irq_chip = {
>   	.irq_set_vcpu_affinity	= its_vpe_set_vcpu_affinity,
>   };
>   
> +static void its_vpe_4_1_send_inv(struct irq_data *d)
> +{
> +	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
> +	struct its_node *its;
> +
> +	/*
> +	 * GICv4.1 wants doorbells to be invalidated using the
> +	 * INVDB command in order to be broadcast to all RDs. Send
> +	 * it to the first valid ITS, and let the HW do its magic.
> +	 */
> +	list_for_each_entry(its, &its_nodes, entry) {
> +		if (!is_v4_1(its))
> +			continue;
> +
> +		its_send_invdb(its, vpe);
> +		break;
> +	}

Maybe use find_4_1_its() helper instead?


Thanks,
Zenghui

> +}
> +
> +static void its_vpe_4_1_mask_irq(struct irq_data *d)
> +{
> +	lpi_write_config(d->parent_data, LPI_PROP_ENABLED, 0);
> +	its_vpe_4_1_send_inv(d);
> +}
> +
> +static void its_vpe_4_1_unmask_irq(struct irq_data *d)
> +{
> +	lpi_write_config(d->parent_data, 0, LPI_PROP_ENABLED);
> +	its_vpe_4_1_send_inv(d);
> +}
> +
>   static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
>   {
>   	struct its_cmd_info *info = vcpu_info;
> @@ -3429,6 +3487,8 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
>   
>   static struct irq_chip its_vpe_4_1_irq_chip = {
>   	.name			= "GICv4.1-vpe",
> +	.irq_mask		= its_vpe_4_1_mask_irq,
> +	.irq_unmask		= its_vpe_4_1_unmask_irq,
>   	.irq_eoi		= irq_chip_eoi_parent,
>   	.irq_set_affinity	= its_vpe_set_affinity,
>   	.irq_set_vcpu_affinity	= its_vpe_4_1_set_vcpu_affinity,
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index f1d6de53e09b..8157737053e4 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -484,8 +484,9 @@
>   #define GITS_CMD_VMAPTI			GITS_CMD_GICv4(GITS_CMD_MAPTI)
>   #define GITS_CMD_VMOVI			GITS_CMD_GICv4(GITS_CMD_MOVI)
>   #define GITS_CMD_VSYNC			GITS_CMD_GICv4(GITS_CMD_SYNC)
> -/* VMOVP is the odd one, as it doesn't have a physical counterpart */
> +/* VMOVP and INVDB are the odd ones, as they dont have a physical counterpart */
>   #define GITS_CMD_VMOVP			GITS_CMD_GICv4(2)
> +#define GITS_CMD_INVDB			GITS_CMD_GICv4(0xe)
>   
>   /*
>    * ITS error numbers
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 17/36] irqchip/gic-v4.1: Add VPE residency callback
  2019-10-27 14:42 ` [PATCH v2 17/36] irqchip/gic-v4.1: Add VPE residency callback Marc Zyngier
@ 2019-11-01 11:34   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:34 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Making a VPE resident on GICv4.1 is pretty simple, as it is just a
> single write to the local redistributor. We just need extra information
> about which groups to enable, which the KVM code will have to provide.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 18/36] irqchip/gic-v4.1: Add VPE eviction callback
  2019-10-27 14:42 ` [PATCH v2 18/36] irqchip/gic-v4.1: Add VPE eviction callback Marc Zyngier
@ 2019-11-01 11:39   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:39 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> When descheduling a VPE, special care must be taken to tell the GIC
> about whether we want to receive a doorbell or not. This is a
> major improvement on GICv4.0, where the doorbell had to be separately
> enabled/disabled.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback
  2019-10-27 14:42 ` [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback Marc Zyngier
@ 2019-11-01 11:51   ` Zenghui Yu
  2019-12-18 14:18     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 11:51 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> GICv4.1 redistributors have a VPE-aware INVALL register. Progress!
> We can now emulate a guest-requested INVALL without emiting a
> VINVALL command.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

> ---
>   drivers/irqchip/irq-gic-v3-its.c   | 14 ++++++++++++++
>   include/linux/irqchip/arm-gic-v3.h |  3 +++
>   2 files changed, 17 insertions(+)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index f7effd453729..10bd156aa042 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -3511,6 +3511,19 @@ static void its_vpe_4_1_deschedule(struct its_vpe *vpe,
>   	}
>   }
>   
> +static void its_vpe_4_1_invall(struct its_vpe *vpe)
> +{
> +	void __iomem *rdbase;
> +	u64 val;
> +
> +	val  = GICR_INVLPIR_V;
> +	val |= FIELD_PREP(GICR_INVLPIR_VPEID, vpe->vpe_id);

Can we use GICR_INVALL_V/VPEID instead, and ...

> +
> +	/* Target the redistributor this vPE is currently known on */
> +	rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
> +	gic_write_lpir(val, rdbase + GICR_INVALLR);
> +}
> +
>   static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
>   {
>   	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
> @@ -3526,6 +3539,7 @@ static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
>   		return 0;
>   
>   	case INVALL_VPE:
> +		its_vpe_4_1_invall(vpe);
>   		return 0;
>   
>   	default:
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 6fd89d77b2b2..b69f60792554 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -247,6 +247,9 @@
>   #define GICR_TYPER_COMMON_LPI_AFF	GENMASK_ULL(25, 24)
>   #define GICR_TYPER_AFFINITY		GENMASK_ULL(63, 32)
>   
> +#define GICR_INVLPIR_VPEID		GENMASK_ULL(47, 32)
> +#define GICR_INVLPIR_V			GENMASK_ULL(63, 63)
> +

... define them here:

#define GICR_INVALL_VPEID		GICR_INVLPIR_VPEID
#define GICR_INVALL_V			GICR_INVLPIR_V


Thanks,
Zenghui

>   #define GIC_V3_REDIST_SIZE		0x20000
>   
>   #define LPI_PROP_GROUP1			(1 << 1)
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 20/36] irqchip/gic-v4.1: Suppress per-VLPI doorbell
  2019-10-27 14:42 ` [PATCH v2 20/36] irqchip/gic-v4.1: Suppress per-VLPI doorbell Marc Zyngier
@ 2019-11-01 12:17   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 12:17 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Since GICv4.1 gives us a per-VPE doorbell, avoid programming anything
> else on VMOVI/VMAPI/VMAPTI and on any other action that would have
> otherwise resulted in a per-VLPI doorbell to be programmed.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 21/36] irqchip/gic-v4.1: Allow direct invalidation of VLPIs
  2019-10-27 14:42 ` [PATCH v2 21/36] irqchip/gic-v4.1: Allow direct invalidation of VLPIs Marc Zyngier
@ 2019-11-01 12:30   ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 12:30 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Just like for INVALL, GICv4.1 has grown a VPE-aware INVLPI register.
> Let's plumb it in and make use of the DirectLPI code in that case.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM
  2019-10-27 14:42 ` [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM Marc Zyngier
@ 2019-11-01 12:55   ` Zenghui Yu
  2019-12-18 14:48     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-11-01 12:55 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, Robert Richter, Jayachandran C,
	Thomas Gleixner

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> Tell KVM that we support v4.1. Nothing uses this information so far.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---
>   drivers/irqchip/irq-gic-v3-its.c       | 9 ++++++++-
>   drivers/irqchip/irq-gic-v3.c           | 1 +
>   include/linux/irqchip/arm-gic-common.h | 2 ++
>   3 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index df259e202482..6483f8051b3e 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -4580,6 +4580,7 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
>   	struct device_node *of_node;
>   	struct its_node *its;
>   	bool has_v4 = false;
> +	bool has_v4_1 = false;
>   	int err;
>   
>   	gic_rdists = rdists;
> @@ -4600,8 +4601,14 @@ int __init its_init(struct fwnode_handle *handle, struct rdists *rdists,
>   	if (err)
>   		return err;
>   
> -	list_for_each_entry(its, &its_nodes, entry)
> +	list_for_each_entry(its, &its_nodes, entry) {
>   		has_v4 |= is_v4(its);
> +		has_v4_1 |= is_v4_1(its);
> +	}
> +
> +	/* Don't bother with inconsistent systems */
> +	if (WARN_ON(!has_v4_1 && rdists->has_rvpeid))
> +		rdists->has_rvpeid = false;
>   
>   	if (has_v4 & rdists->has_vlpis) {
>   		if (its_init_vpe_domain() ||
> diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
> index f0d33ac64a99..94dddfb21076 100644
> --- a/drivers/irqchip/irq-gic-v3.c
> +++ b/drivers/irqchip/irq-gic-v3.c
> @@ -1758,6 +1758,7 @@ static void __init gic_of_setup_kvm_info(struct device_node *node)
>   		gic_v3_kvm_info.vcpu = r;
>   
>   	gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
> +	gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;

Also set gic_v3_kvm_info.has_v4_1 in gic_acpi_setup_kvm_info().


Thanks,
Zenghui

>   	gic_set_kvm_info(&gic_v3_kvm_info);
>   }
>   
> diff --git a/include/linux/irqchip/arm-gic-common.h b/include/linux/irqchip/arm-gic-common.h
> index b9850f5f1906..fa8c0455c352 100644
> --- a/include/linux/irqchip/arm-gic-common.h
> +++ b/include/linux/irqchip/arm-gic-common.h
> @@ -32,6 +32,8 @@ struct gic_kvm_info {
>   	struct resource vctrl;
>   	/* vlpi support */
>   	bool		has_v4;
> +	/* rvpeid support */
> +	bool		has_v4_1;
>   };
>   
>   const struct gic_kvm_info *gic_get_kvm_info(void);
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface
  2019-10-31  8:49   ` Zenghui Yu
@ 2019-11-01 13:26     ` Marc Zyngier
  2019-11-05 10:30       ` Zenghui Yu
  0 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-11-01 13:26 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On Thu, 31 Oct 2019 08:49:32 +0000,
Zenghui Yu <yuzenghui@huawei.com> wrote:
> 
> Hi Marc,
> 
> On 2019/10/27 22:42, Marc Zyngier wrote:
> > We currently don't make much use of the DirectLPI feature, and it would
> > be beneficial to do this more, if only because it becomes a mandatory
> > feature for GICv4.1.
> > 
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> 
> I have no objection to this patch, which says:
> 
> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
> 
> 
> But this patch really drives me to look through all callsites of
> dev_event_to_col(), the abstraction which can be used _only_ with
> physical LPI mappings.
> 
> I find that when building the INV command, we use dev_event_to_col()
> to find the "sync_obj" and then pass it to the following SYNC command.
> But the "INV+SYNC" will be performed both on physical LPI and *VLPI*
> (lpi_update_config/its_send_inv).
> So I have two questions about the way we sending INV on VLPI:
> 
> 1) Which "sync" command should be followed?  SYNC or VSYNC?
> (we currently use SYNC, while the spec says, SYNC "ensures all
> outstanding ITS operations associated with *physical* interrupts
> for the Redistributor are globally observed ...")
> 
> 2) The "sync_obj" we are currently using seems to be wrong.

I think you're right on both counts (where were you when I wrote the
initial GICv4 support? ;-). I think the confusion stems from the fact
that there is no 'VINV' command, and we simply overlooked the sync
object issue. It is quite likely that existing implementations don't
care much about the difference (otherwise we'd have seen the problem
before), but it doesn't hurt to do the right thing.

I have the following patch as part of a set of fixes that I'm about to
post (once I get a chance to test them), let me know what you think.

	M.

diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index a47ed2ba2907..75ab3716a870 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -702,6 +702,24 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
 	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
 }
 
+static struct its_vpe *its_build_vinv_cmd(struct its_node *its,
+					  struct its_cmd_block *cmd,
+					  struct its_cmd_desc *desc)
+{
+	struct its_vlpi_map *map;
+
+	map = dev_event_to_vlpi_map(desc->its_inv_cmd.dev,
+				    desc->its_inv_cmd.event_id);
+
+	its_encode_cmd(cmd, GITS_CMD_INV);
+	its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
+	its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
+
+	its_fixup_cmd(cmd);
+
+	return valid_vpe(its, map->vpe);
+}
+
 static u64 its_cmd_ptr_to_offset(struct its_node *its,
 				 struct its_cmd_block *ptr)
 {
@@ -1068,6 +1086,20 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
 	its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
 }
 
+static void its_send_vinv(struct its_device *dev, u32 event_id)
+{
+	struct its_cmd_desc desc;
+
+	/*
+	 * There is no real VINV command. This is just a normal INV,
+	 * with a VSYNC instead of a SYNC.
+	 */
+	desc.its_inv_cmd.dev = dev;
+	desc.its_inv_cmd.event_id = event_id;
+
+	its_send_single_vcommand(dev->its, its_build_vinv_cmd, &desc);
+}
+
 /*
  * irqchip functions - assumes MSI, mostly.
  */
@@ -1142,8 +1174,10 @@ static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
 	lpi_write_config(d, clr, set);
 	if (gic_rdists->has_direct_lpi && !irqd_is_forwarded_to_vcpu(d))
 		direct_lpi_inv(d);
-	else
+	else if (!irqd_is_forwarded_to_vcpu(d))
 		its_send_inv(its_dev, its_get_event_id(d));
+	else
+		its_send_vinv(its_dev, its_get_event_id(d));
 }
 
 static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)

-- 
Jazz is not dead, it just smells funny.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery
  2019-10-31 12:02   ` Zenghui Yu
@ 2019-11-01 15:13     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-11-01 15:13 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On Thu, 31 Oct 2019 12:02:24 +0000,
Zenghui Yu <yuzenghui@huawei.com> wrote:
> 
> Hi Marc,
> 
> On 2019/10/27 22:42, Marc Zyngier wrote:
> > While GICv4.0 mandates 16 bit worth of VPEIDs, GICv4.1 allows smaller
> > implementations to be built. Add the required glue to dynamically
> > compute the limit.
> > 
> > Signed-off-by: Marc Zyngier <maz@kernel.org>
> > ---
> >   drivers/irqchip/irq-gic-v3-its.c   | 11 ++++++++++-
> >   drivers/irqchip/irq-gic-v3.c       |  3 +++
> >   include/linux/irqchip/arm-gic-v3.h |  5 +++++
> >   3 files changed, 18 insertions(+), 1 deletion(-)
> > 
> > diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> > index 94c9c2e9f917..40912b3fb0e1 100644
> > --- a/drivers/irqchip/irq-gic-v3-its.c
> > +++ b/drivers/irqchip/irq-gic-v3-its.c
> > @@ -121,7 +121,16 @@ struct its_node {
> >   #define ITS_ITT_ALIGN		SZ_256
> >     /* The maximum number of VPEID bits supported by VLPI commands
> > */
> > -#define ITS_MAX_VPEID_BITS	(16)
> > +#define ITS_MAX_VPEID_BITS						\
> > +	({								\
> > +		int nvpeid = 16;					\
> > +		if (gic_rdists->has_rvpeid &&				\
> > +		    gic_rdists->gicd_typer2 & GICD_TYPER2_VIL)		\
> > +			nvpeid = 1 + (gic_rdists->gicd_typer2 &		\
> > +				      GICD_TYPER2_VID);			\
> 
> Does it make sense to let nvpeid not more than 16 here? As the spec says
> "Values above 0x0F are RESERVED". But I don't know why should we have
> this restriction ;-)

This is something that Andrew raised in the previous version. My take
on this is that properly implemented HW should give us something that
matches the spec (in the 0-15 range), and I don't think that guarding
against that is useful at this stage.

My understanding is that once the architecture allows using the 16-31
range, we'll either use it directly because it is just a natural
extension to the existing range, or they mean something different
altogether and we'll get a new discovery bit somewhere.

> Either way,
> 
> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>

Thanks,

	M.

-- 
Jazz is not dead, it just smells funny.
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface
  2019-11-01 13:26     ` Marc Zyngier
@ 2019-11-05 10:30       ` Zenghui Yu
  2019-11-05 12:12         ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-11-05 10:30 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

Hi Marc,

On 2019/11/1 21:26, Marc Zyngier wrote:
> On Thu, 31 Oct 2019 08:49:32 +0000,
> Zenghui Yu <yuzenghui@huawei.com> wrote:
>>
>> But this patch really drives me to look through all callsites of
>> dev_event_to_col(), the abstraction which can be used _only_ with
>> physical LPI mappings.
>>
>> I find that when building the INV command, we use dev_event_to_col()
>> to find the "sync_obj" and then pass it to the following SYNC command.
>> But the "INV+SYNC" will be performed both on physical LPI and *VLPI*
>> (lpi_update_config/its_send_inv).
>> So I have two questions about the way we sending INV on VLPI:
>>
>> 1) Which "sync" command should be followed?  SYNC or VSYNC?
>> (we currently use SYNC, while the spec says, SYNC "ensures all
>> outstanding ITS operations associated with *physical* interrupts
>> for the Redistributor are globally observed ...")
>>
>> 2) The "sync_obj" we are currently using seems to be wrong.
> 
> I think you're right on both counts (where were you when I wrote the
> initial GICv4 support? ;-). I think the confusion stems from the fact

(I'm a bit late here :-).

> that there is no 'VINV' command, and we simply overlooked the sync
> object issue. It is quite likely that existing implementations don't
> care much about the difference (otherwise we'd have seen the problem
> before), but it doesn't hurt to do the right thing.
> 
> I have the following patch as part of a set of fixes that I'm about to
> post (once I get a chance to test them), let me know what you think.
> 
> 	M.
> 
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index a47ed2ba2907..75ab3716a870 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
> @@ -702,6 +702,24 @@ static struct its_vpe *its_build_vmovp_cmd(struct its_node *its,
>   	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
>   }
>   
> +static struct its_vpe *its_build_vinv_cmd(struct its_node *its,
> +					  struct its_cmd_block *cmd,
> +					  struct its_cmd_desc *desc)
> +{
> +	struct its_vlpi_map *map;
> +
> +	map = dev_event_to_vlpi_map(desc->its_inv_cmd.dev,
> +				    desc->its_inv_cmd.event_id);

Indeed!  I think we need this kind of abstraction for VLPI.

> +
> +	its_encode_cmd(cmd, GITS_CMD_INV);
> +	its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
> +	its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
> +
> +	its_fixup_cmd(cmd);
> +
> +	return valid_vpe(its, map->vpe);
> +}
> +
>   static u64 its_cmd_ptr_to_offset(struct its_node *its,
>   				 struct its_cmd_block *ptr)
>   {
> @@ -1068,6 +1086,20 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
>   	its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
>   }
>   
> +static void its_send_vinv(struct its_device *dev, u32 event_id)
> +{
> +	struct its_cmd_desc desc;
> +
> +	/*
> +	 * There is no real VINV command. This is just a normal INV,
> +	 * with a VSYNC instead of a SYNC.
> +	 */
> +	desc.its_inv_cmd.dev = dev;
> +	desc.its_inv_cmd.event_id = event_id;
> +
> +	its_send_single_vcommand(dev->its, its_build_vinv_cmd, &desc);
> +}
> +
>   /*
>    * irqchip functions - assumes MSI, mostly.
>    */
> @@ -1142,8 +1174,10 @@ static void lpi_update_config(struct irq_data *d, u8 clr, u8 set)
>   	lpi_write_config(d, clr, set);
>   	if (gic_rdists->has_direct_lpi && !irqd_is_forwarded_to_vcpu(d))
>   		direct_lpi_inv(d);
> -	else
> +	else if (!irqd_is_forwarded_to_vcpu(d))
>   		its_send_inv(its_dev, its_get_event_id(d));
> +	else
> +		its_send_vinv(its_dev, its_get_event_id(d));

Yeah, this is exactly what I was having in the mind when reporting this
problem - "maybe we should have a SW emulated VINV+VSYNC for VLPI".
So I think this patch has done the right thing.

And what about the INT and CLEAR?  In response to guest's INT/CLEAR
commands, hypervisor (I mean KVM) will bother the ITS driver to send
INT/CLEAR for VLPIs.  They're both followed by SYNC and might need the
same fixes?


Thanks,
Zenghui

>   }
>   
>   static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface
  2019-11-05 10:30       ` Zenghui Yu
@ 2019-11-05 12:12         ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-11-05 12:12 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On 2019-11-05 11:39, Zenghui Yu wrote:
> Hi Marc,
>
> On 2019/11/1 21:26, Marc Zyngier wrote:
>> On Thu, 31 Oct 2019 08:49:32 +0000,
>> Zenghui Yu <yuzenghui@huawei.com> wrote:
>>>
>>> But this patch really drives me to look through all callsites of
>>> dev_event_to_col(), the abstraction which can be used _only_ with
>>> physical LPI mappings.
>>>
>>> I find that when building the INV command, we use 
>>> dev_event_to_col()
>>> to find the "sync_obj" and then pass it to the following SYNC 
>>> command.
>>> But the "INV+SYNC" will be performed both on physical LPI and 
>>> *VLPI*
>>> (lpi_update_config/its_send_inv).
>>> So I have two questions about the way we sending INV on VLPI:
>>>
>>> 1) Which "sync" command should be followed?  SYNC or VSYNC?
>>> (we currently use SYNC, while the spec says, SYNC "ensures all
>>> outstanding ITS operations associated with *physical* interrupts
>>> for the Redistributor are globally observed ...")
>>>
>>> 2) The "sync_obj" we are currently using seems to be wrong.
>> I think you're right on both counts (where were you when I wrote the
>> initial GICv4 support? ;-). I think the confusion stems from the 
>> fact
>
> (I'm a bit late here :-).
>
>> that there is no 'VINV' command, and we simply overlooked the sync
>> object issue. It is quite likely that existing implementations don't
>> care much about the difference (otherwise we'd have seen the problem
>> before), but it doesn't hurt to do the right thing.
>> I have the following patch as part of a set of fixes that I'm about 
>> to
>> post (once I get a chance to test them), let me know what you think.
>>
>> 	M.
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>> b/drivers/irqchip/irq-gic-v3-its.c
>> index a47ed2ba2907..75ab3716a870 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -702,6 +702,24 @@ static struct its_vpe 
>> *its_build_vmovp_cmd(struct its_node *its,
>>   	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
>>   }
>>   +static struct its_vpe *its_build_vinv_cmd(struct its_node *its,
>> +					  struct its_cmd_block *cmd,
>> +					  struct its_cmd_desc *desc)
>> +{
>> +	struct its_vlpi_map *map;
>> +
>> +	map = dev_event_to_vlpi_map(desc->its_inv_cmd.dev,
>> +				    desc->its_inv_cmd.event_id);
>
> Indeed!  I think we need this kind of abstraction for VLPI.

Yeah, I finally realised we'd needed something like that, and made
it part of the get_vlpi_map() patch.

>
>> +
>> +	its_encode_cmd(cmd, GITS_CMD_INV);
>> +	its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
>> +	its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
>> +
>> +	its_fixup_cmd(cmd);
>> +
>> +	return valid_vpe(its, map->vpe);
>> +}
>> +
>>   static u64 its_cmd_ptr_to_offset(struct its_node *its,
>>   				 struct its_cmd_block *ptr)
>>   {
>> @@ -1068,6 +1086,20 @@ static void its_send_vinvall(struct its_node 
>> *its, struct its_vpe *vpe)
>>   	its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
>>   }
>>   +static void its_send_vinv(struct its_device *dev, u32 event_id)
>> +{
>> +	struct its_cmd_desc desc;
>> +
>> +	/*
>> +	 * There is no real VINV command. This is just a normal INV,
>> +	 * with a VSYNC instead of a SYNC.
>> +	 */
>> +	desc.its_inv_cmd.dev = dev;
>> +	desc.its_inv_cmd.event_id = event_id;
>> +
>> +	its_send_single_vcommand(dev->its, its_build_vinv_cmd, &desc);
>> +}
>> +
>>   /*
>>    * irqchip functions - assumes MSI, mostly.
>>    */
>> @@ -1142,8 +1174,10 @@ static void lpi_update_config(struct irq_data 
>> *d, u8 clr, u8 set)
>>   	lpi_write_config(d, clr, set);
>>   	if (gic_rdists->has_direct_lpi && !irqd_is_forwarded_to_vcpu(d))
>>   		direct_lpi_inv(d);
>> -	else
>> +	else if (!irqd_is_forwarded_to_vcpu(d))
>>   		its_send_inv(its_dev, its_get_event_id(d));
>> +	else
>> +		its_send_vinv(its_dev, its_get_event_id(d));
>
> Yeah, this is exactly what I was having in the mind when reporting 
> this
> problem - "maybe we should have a SW emulated VINV+VSYNC for VLPI".
> So I think this patch has done the right thing.
>
> And what about the INT and CLEAR?  In response to guest's INT/CLEAR
> commands, hypervisor (I mean KVM) will bother the ITS driver to send
> INT/CLEAR for VLPIs.  They're both followed by SYNC and might need 
> the
> same fixes?

Yup. Please see this series[1], which has grown quite a few fixups,
including some pretty old ones (I've just pushed an update, and should
post it shortly).

Thanks,

         M.

[1] 
https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/log/?h=irq/gic-5.5-wip
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP
  2019-10-27 14:42 ` [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP Marc Zyngier
  2019-11-01 10:58   ` Zenghui Yu
@ 2019-11-13  8:02   ` Zenghui Yu
  2019-11-13  9:47     ` Marc Zyngier
  1 sibling, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-11-13  8:02 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, jiayanlei, Robert Richter,
	Jayachandran C, Thomas Gleixner, liangboyan

Hi Marc,

On 2019/10/27 22:42, Marc Zyngier wrote:
> The ITS VMAPP command gains some new fields with GICv4.1:
> - a default doorbell, which allows a single doorbell to be used for
>    all the VLPIs routed to a given VPE
> - a pointer to the configuration table (instead of having it in a register
>    that gets context switched)
> - a flag indicating whether this is the first map or the last unmap for
>    this particulat VPE
> - a flag indicating whether the pending table is known to be zeroed, or not
> 
> Plumb in the new fields in the VMAPP builder, and add the map/unmap
> refcounting so that the ITS can do the right thing.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>

[...]

> @@ -605,19 +626,45 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
>   					   struct its_cmd_block *cmd,
>   					   struct its_cmd_desc *desc)
>   {
> -	unsigned long vpt_addr;
> +	unsigned long vpt_addr, vconf_addr;
>   	u64 target;
> -
> -	vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
> -	target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
> +	bool alloc;
>   
>   	its_encode_cmd(cmd, GITS_CMD_VMAPP);
>   	its_encode_vpeid(cmd, desc->its_vmapp_cmd.vpe->vpe_id);
>   	its_encode_valid(cmd, desc->its_vmapp_cmd.valid);
> +
> +	if (!desc->its_vmapp_cmd.valid) {
> +		if (is_v4_1(its)) {
> +			alloc = !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
> +			its_encode_alloc(cmd, alloc);
> +		}
> +
> +		goto out;
> +	}
> +
> +	vpt_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
> +	target = desc->its_vmapp_cmd.col->target_address + its->vlpi_redist_offset;
> +
>   	its_encode_target(cmd, target);
>   	its_encode_vpt_addr(cmd, vpt_addr);
>   	its_encode_vpt_size(cmd, LPI_NRBITS - 1);
>   
> +	if (!is_v4_1(its))
> +		goto out;
> +
> +	vconf_addr = virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page));
> +
> +	alloc = atomic_inc_and_test(&desc->its_vmapp_cmd.vpe->vmapp_count);

As the comment block on top of atomic_inc_and_test(atomic *v) says,

	 * Atomically increments @v by 1
	 * and returns true if the result is zero, or false for all
	 * other cases.
	 */

We will always get the 'alloc' as false here, even if this is the
first mapping of this vPE.  This is not as expected, I think.

And on the other hand, I wonder what is the reason for 'vmapp_count'
to be atomic_t?


Thanks,
Zenghui

> +
> +	its_encode_alloc(cmd, alloc);
> +
> +	/* We can only signal PTZ when alloc==1. Why do we have two bits? */
> +	its_encode_ptz(cmd, alloc);
> +	its_encode_vconf_addr(cmd, vconf_addr);
> +	its_encode_vmapp_default_db(cmd, desc->its_vmapp_cmd.vpe->vpe_db_lpi);
> +
> +out:
>   	its_fixup_cmd(cmd);
>   
>   	return valid_vpe(its, desc->its_vmapp_cmd.vpe);
> @@ -3349,7 +3396,10 @@ static int its_vpe_init(struct its_vpe *vpe)
>   
>   	vpe->vpe_id = vpe_id;
>   	vpe->vpt_page = vpt_page;
> -	vpe->vpe_proxy_event = -1;
> +	if (gic_rdists->has_rvpeid)
> +		atomic_set(&vpe->vmapp_count, 0);
> +	else
> +		vpe->vpe_proxy_event = -1;
>   
>   	return 0;
>   }
> diff --git a/include/linux/irqchip/arm-gic-v4.h b/include/linux/irqchip/arm-gic-v4.h
> index ab1396afe08a..6213ced6f199 100644
> --- a/include/linux/irqchip/arm-gic-v4.h
> +++ b/include/linux/irqchip/arm-gic-v4.h
> @@ -37,8 +37,20 @@ struct its_vpe {
>   	irq_hw_number_t		vpe_db_lpi;
>   	/* VPE resident */
>   	bool			resident;
> -	/* VPE proxy mapping */
> -	int			vpe_proxy_event;
> +	union {
> +		/* GICv4.0 implementations */
> +		struct {
> +			/* VPE proxy mapping */
> +			int	vpe_proxy_event;
> +			/* Implementation Defined Area Invalid */
> +			bool	idai;
> +		};
> +		/* GICv4.1 implementations */
> +		struct {
> +			atomic_t vmapp_count;
> +		};
> +	};
> +
>   	/*
>   	 * This collection ID is used to indirect the target
>   	 * redistributor for this VPE. The ID itself isn't involved in
> @@ -47,8 +59,6 @@ struct its_vpe {
>   	u16			col_idx;
>   	/* Unique (system-wide) VPE identifier */
>   	u16			vpe_id;
> -	/* Implementation Defined Area Invalid */
> -	bool			idai;
>   	/* Pending VLPIs on schedule out? */
>   	bool			pending_last;
>   };
> 

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP
  2019-11-13  8:02   ` Zenghui Yu
@ 2019-11-13  9:47     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-11-13  9:47 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, jiayanlei, linux-kernel,
	Robert Richter, Jayachandran C, Thomas Gleixner, liangboyan,
	kvmarm

Hi Zenghui,

On 2019-11-13 09:11, Zenghui Yu wrote:
> Hi Marc,
>
> On 2019/10/27 22:42, Marc Zyngier wrote:
>> The ITS VMAPP command gains some new fields with GICv4.1:
>> - a default doorbell, which allows a single doorbell to be used for
>>    all the VLPIs routed to a given VPE
>> - a pointer to the configuration table (instead of having it in a 
>> register
>>    that gets context switched)
>> - a flag indicating whether this is the first map or the last unmap 
>> for
>>    this particulat VPE
>> - a flag indicating whether the pending table is known to be zeroed, 
>> or not
>> Plumb in the new fields in the VMAPP builder, and add the map/unmap
>> refcounting so that the ITS can do the right thing.
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>
> [...]
>
>> @@ -605,19 +626,45 @@ static struct its_vpe 
>> *its_build_vmapp_cmd(struct its_node *its,
>>   					   struct its_cmd_block *cmd,
>>   					   struct its_cmd_desc *desc)
>>   {
>> -	unsigned long vpt_addr;
>> +	unsigned long vpt_addr, vconf_addr;
>>   	u64 target;
>> -
>> -	vpt_addr = 
>> virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
>> -	target = desc->its_vmapp_cmd.col->target_address + 
>> its->vlpi_redist_offset;
>> +	bool alloc;
>>
>>   	its_encode_cmd(cmd, GITS_CMD_VMAPP);
>>   	its_encode_vpeid(cmd, desc->its_vmapp_cmd.vpe->vpe_id);
>>   	its_encode_valid(cmd, desc->its_vmapp_cmd.valid);
>> +
>> +	if (!desc->its_vmapp_cmd.valid) {
>> +		if (is_v4_1(its)) {
>> +			alloc = 
>> !atomic_dec_return(&desc->its_vmapp_cmd.vpe->vmapp_count);
>> +			its_encode_alloc(cmd, alloc);
>> +		}
>> +
>> +		goto out;
>> +	}
>> +
>> +	vpt_addr = 
>> virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->vpt_page));
>> +	target = desc->its_vmapp_cmd.col->target_address + 
>> its->vlpi_redist_offset;
>> +
>>   	its_encode_target(cmd, target);
>>   	its_encode_vpt_addr(cmd, vpt_addr);
>>   	its_encode_vpt_size(cmd, LPI_NRBITS - 1);
>>   +	if (!is_v4_1(its))
>> +		goto out;
>> +
>> +	vconf_addr = 
>> virt_to_phys(page_address(desc->its_vmapp_cmd.vpe->its_vm->vprop_page));
>> +
>> +	alloc = 
>> atomic_inc_and_test(&desc->its_vmapp_cmd.vpe->vmapp_count);
>
> As the comment block on top of atomic_inc_and_test(atomic *v) says,
>
>  * Atomically increments @v by 1
>  * and returns true if the result is zero, or false for all
>  * other cases.
>  */
>
> We will always get the 'alloc' as false here, even if this is the
> first mapping of this vPE.  This is not as expected, I think.

As usual, a very good observation!

Indeed, I cocked up the logic here, as we need to test the value before
the increment (and not after). What we want is probably something like:

   alloc = !atomic_fetch_inc(&desc->its_vmapp_cmd.vpe->vmapp_count);

> And on the other hand, I wonder what is the reason for 'vmapp_count'
> to be atomic_t?

The rational is that we could end-up with multiple VMAPP commands 
emitted
in parallel, for example. That's probably not strictly necessary right 
now,
but I'm trying to be cautious.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback
  2019-11-01 11:51   ` Zenghui Yu
@ 2019-12-18 14:18     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-12-18 14:18 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

[Old email, doing some v3 cleanup]

On 2019-11-01 11:51, Zenghui Yu wrote:
> Hi Marc,
>
> On 2019/10/27 22:42, Marc Zyngier wrote:
>> GICv4.1 redistributors have a VPE-aware INVALL register. Progress!
>> We can now emulate a guest-requested INVALL without emiting a
>> VINVALL command.
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>
> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c   | 14 ++++++++++++++
>>   include/linux/irqchip/arm-gic-v3.h |  3 +++
>>   2 files changed, 17 insertions(+)
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>> b/drivers/irqchip/irq-gic-v3-its.c
>> index f7effd453729..10bd156aa042 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -3511,6 +3511,19 @@ static void its_vpe_4_1_deschedule(struct 
>> its_vpe *vpe,
>>   	}
>>   }
>>   +static void its_vpe_4_1_invall(struct its_vpe *vpe)
>> +{
>> +	void __iomem *rdbase;
>> +	u64 val;
>> +
>> +	val  = GICR_INVLPIR_V;
>> +	val |= FIELD_PREP(GICR_INVLPIR_VPEID, vpe->vpe_id);
>
> Can we use GICR_INVALL_V/VPEID instead, and ...
>
>> +
>> +	/* Target the redistributor this vPE is currently known on */
>> +	rdbase = per_cpu_ptr(gic_rdists->rdist, vpe->col_idx)->rd_base;
>> +	gic_write_lpir(val, rdbase + GICR_INVALLR);
>> +}
>> +
>>   static int its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void 
>> *vcpu_info)
>>   {
>>   	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
>> @@ -3526,6 +3539,7 @@ static int 
>> its_vpe_4_1_set_vcpu_affinity(struct irq_data *d, void *vcpu_info)
>>   		return 0;
>>
>>   	case INVALL_VPE:
>> +		its_vpe_4_1_invall(vpe);
>>   		return 0;
>>
>>   	default:
>> diff --git a/include/linux/irqchip/arm-gic-v3.h 
>> b/include/linux/irqchip/arm-gic-v3.h
>> index 6fd89d77b2b2..b69f60792554 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -247,6 +247,9 @@
>>   #define GICR_TYPER_COMMON_LPI_AFF	GENMASK_ULL(25, 24)
>>   #define GICR_TYPER_AFFINITY		GENMASK_ULL(63, 32)
>>   +#define GICR_INVLPIR_VPEID		GENMASK_ULL(47, 32)
>> +#define GICR_INVLPIR_V			GENMASK_ULL(63, 63)
>> +
>
> ... define them here:
>
> #define GICR_INVALL_VPEID		GICR_INVLPIR_VPEID
> #define GICR_INVALL_V			GICR_INVLPIR_V

Yes, that's a sensible things to do. I'll squash that in my rebased 
series.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set
  2019-11-01 11:05   ` Zenghui Yu
@ 2019-12-18 14:39     ` Marc Zyngier
  2019-12-19  3:05       ` Zenghui Yu
  0 siblings, 1 reply; 72+ messages in thread
From: Marc Zyngier @ 2019-12-18 14:39 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On 2019-11-01 11:05, Zenghui Yu wrote:
> Hi Marc,
>
> On 2019/10/27 22:42, Marc Zyngier wrote:
>> The infamous VPE proxy device isn't used with GICv4.1 because:
>> - we can invalidate any LPI from the DirectLPI MMIO interface
>> - the ITS and redistributors understand the life cycle of
>>    the doorbell, so we don't need to enable/disable it all
>>    the time
>> So let's escape early from the proxy related functions.
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>
> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c | 23 ++++++++++++++++++++++-
>>   1 file changed, 22 insertions(+), 1 deletion(-)
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>> b/drivers/irqchip/irq-gic-v3-its.c
>> index 220d490d516e..999e61a9b2c3 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -3069,7 +3069,7 @@ static const struct irq_domain_ops 
>> its_domain_ops = {
>>   /*
>>    * This is insane.
>>    *
>> - * If a GICv4 doesn't implement Direct LPIs (which is extremely
>> + * If a GICv4.0 doesn't implement Direct LPIs (which is extremely
>>    * likely), the only way to perform an invalidate is to use a fake
>>    * device to issue an INV command, implying that the LPI has first
>>    * been mapped to some event on that device. Since this is not 
>> exactly
>> @@ -3077,9 +3077,18 @@ static const struct irq_domain_ops 
>> its_domain_ops = {
>>    * only issue an UNMAP if we're short on available slots.
>>    *
>>    * Broken by design(tm).
>> + *
>> + * GICv4.1 actually mandates that we're able to invalidate by 
>> writing to a
>> + * MMIO register. It doesn't implement the whole of DirectLPI, but 
>> that's
>> + * good enough. And most of the time, we don't even have to 
>> invalidate
>> + * anything, so that's actually pretty good!
>
> I can't understand the meaning of this last sentence. May I ask for 
> an
> explanation? :)

Yeah, reading this now, it feels pretty clumsy, and only remotely
connected to the patch.

What I'm trying to say here is that, although GICv4.1 doesn't have
the full spectrum of v4.0 DirectLPI (it only allows a subset of it),
this subset is more then enough for us. Here's the rational:

When a vPE exits from the hypervisor, we know whether we need to
request a doorbell or not (depending on whether we're blocking on
WFI or not). On GICv4.0, this translates into enabling the doorbell
interrupt, which generates an invalidation (costly). And whenever
we've taken a doorbell, or are scheduled again, we need to turn
the doorbell off (invalidation again).

With v4.1, we can just say *at exit time* whether we want doorbells
to be subsequently generated (see its_vpe_4_1_deschedule() and the
req_db parameter in the info structure). This is part of making
the vPE non-resident, so we have 0 overhead at this stage.

I'll try and update the comment here.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM
  2019-11-01 12:55   ` Zenghui Yu
@ 2019-12-18 14:48     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-12-18 14:48 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On 2019-11-01 12:55, Zenghui Yu wrote:
> Hi Marc,
>
> On 2019/10/27 22:42, Marc Zyngier wrote:
>> Tell KVM that we support v4.1. Nothing uses this information so far.
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c       | 9 ++++++++-
>>   drivers/irqchip/irq-gic-v3.c           | 1 +
>>   include/linux/irqchip/arm-gic-common.h | 2 ++
>>   3 files changed, 11 insertions(+), 1 deletion(-)
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>> b/drivers/irqchip/irq-gic-v3-its.c
>> index df259e202482..6483f8051b3e 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -4580,6 +4580,7 @@ int __init its_init(struct fwnode_handle 
>> *handle, struct rdists *rdists,
>>   	struct device_node *of_node;
>>   	struct its_node *its;
>>   	bool has_v4 = false;
>> +	bool has_v4_1 = false;
>>   	int err;
>>
>>   	gic_rdists = rdists;
>> @@ -4600,8 +4601,14 @@ int __init its_init(struct fwnode_handle 
>> *handle, struct rdists *rdists,
>>   	if (err)
>>   		return err;
>>   -	list_for_each_entry(its, &its_nodes, entry)
>> +	list_for_each_entry(its, &its_nodes, entry) {
>>   		has_v4 |= is_v4(its);
>> +		has_v4_1 |= is_v4_1(its);
>> +	}
>> +
>> +	/* Don't bother with inconsistent systems */
>> +	if (WARN_ON(!has_v4_1 && rdists->has_rvpeid))
>> +		rdists->has_rvpeid = false;
>>
>>   	if (has_v4 & rdists->has_vlpis) {
>>   		if (its_init_vpe_domain() ||
>> diff --git a/drivers/irqchip/irq-gic-v3.c 
>> b/drivers/irqchip/irq-gic-v3.c
>> index f0d33ac64a99..94dddfb21076 100644
>> --- a/drivers/irqchip/irq-gic-v3.c
>> +++ b/drivers/irqchip/irq-gic-v3.c
>> @@ -1758,6 +1758,7 @@ static void __init 
>> gic_of_setup_kvm_info(struct device_node *node)
>>   		gic_v3_kvm_info.vcpu = r;
>>
>>   	gic_v3_kvm_info.has_v4 = gic_data.rdists.has_vlpis;
>> +	gic_v3_kvm_info.has_v4_1 = gic_data.rdists.has_rvpeid;
>
> Also set gic_v3_kvm_info.has_v4_1 in gic_acpi_setup_kvm_info().

Indeed. Now fixed.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks
  2019-11-01 11:23   ` Zenghui Yu
@ 2019-12-18 15:06     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-12-18 15:06 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

On 2019-11-01 11:23, Zenghui Yu wrote:
> Hi Marc,
>
> On 2019/10/27 22:42, Marc Zyngier wrote:
>> masking/unmasking doorbells on GICv4.1 relies on a new INVDB 
>> command,
>> which broadcasts the invalidation to all RDs.
>> Implement the new command as well as the masking callbacks, and plug
>> the whole thing into the v4.1 VPE irqchip.
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>
> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
>
>> ---
>>   drivers/irqchip/irq-gic-v3-its.c   | 60 
>> ++++++++++++++++++++++++++++++
>>   include/linux/irqchip/arm-gic-v3.h |  3 +-
>>   2 files changed, 62 insertions(+), 1 deletion(-)
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>> b/drivers/irqchip/irq-gic-v3-its.c
>> index dcc7227af5f1..3c34bef70bdd 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>> @@ -309,6 +309,10 @@ struct its_cmd_desc {
>>   			u16 seq_num;
>>   			u16 its_list;
>>   		} its_vmovp_cmd;
>> +
>> +		struct {
>> +			struct its_vpe *vpe;
>> +		} its_invdb_cmd;
>>   	};
>>   };
>>   @@ -750,6 +754,21 @@ static struct its_vpe 
>> *its_build_vmovp_cmd(struct its_node *its,
>>   	return valid_vpe(its, desc->its_vmovp_cmd.vpe);
>>   }
>>   +static struct its_vpe *its_build_invdb_cmd(struct its_node *its,
>> +					   struct its_cmd_block *cmd,
>> +					   struct its_cmd_desc *desc)
>> +{
>> +	if (WARN_ON(!is_v4_1(its)))
>> +		return NULL;
>> +
>> +	its_encode_cmd(cmd, GITS_CMD_INVDB);
>> +	its_encode_vpeid(cmd, desc->its_invdb_cmd.vpe->vpe_id);
>> +
>> +	its_fixup_cmd(cmd);
>> +
>> +	return valid_vpe(its, desc->its_invdb_cmd.vpe);
>> +}
>> +
>>   static u64 its_cmd_ptr_to_offset(struct its_node *its,
>>   				 struct its_cmd_block *ptr)
>>   {
>> @@ -1117,6 +1136,14 @@ static void its_send_vinvall(struct its_node 
>> *its, struct its_vpe *vpe)
>>   	its_send_single_vcommand(its, its_build_vinvall_cmd, &desc);
>>   }
>>   +static void its_send_invdb(struct its_node *its, struct its_vpe 
>> *vpe)
>> +{
>> +	struct its_cmd_desc desc;
>> +
>> +	desc.its_invdb_cmd.vpe = vpe;
>> +	its_send_single_vcommand(its, its_build_invdb_cmd, &desc);
>> +}
>> +
>>   /*
>>    * irqchip functions - assumes MSI, mostly.
>>    */
>> @@ -3408,6 +3435,37 @@ static struct irq_chip its_vpe_irq_chip = {
>>   	.irq_set_vcpu_affinity	= its_vpe_set_vcpu_affinity,
>>   };
>>   +static void its_vpe_4_1_send_inv(struct irq_data *d)
>> +{
>> +	struct its_vpe *vpe = irq_data_get_irq_chip_data(d);
>> +	struct its_node *its;
>> +
>> +	/*
>> +	 * GICv4.1 wants doorbells to be invalidated using the
>> +	 * INVDB command in order to be broadcast to all RDs. Send
>> +	 * it to the first valid ITS, and let the HW do its magic.
>> +	 */
>> +	list_for_each_entry(its, &its_nodes, entry) {
>> +		if (!is_v4_1(its))
>> +			continue;
>> +
>> +		its_send_invdb(its, vpe);
>> +		break;
>> +	}
>
> Maybe use find_4_1_its() helper instead?

Yes, good point. I've moved it up in the series, and it is now added
to this patch.

Thanks,

         M.
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set
  2019-12-18 14:39     ` Marc Zyngier
@ 2019-12-19  3:05       ` Zenghui Yu
  0 siblings, 0 replies; 72+ messages in thread
From: Zenghui Yu @ 2019-12-19  3:05 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Lorenzo Pieralisi, Jason Cooper, linux-kernel, Robert Richter,
	Jayachandran C, Thomas Gleixner, kvmarm

Hi Marc,

On 2019/12/18 22:39, Marc Zyngier wrote:
> On 2019-11-01 11:05, Zenghui Yu wrote:
>> Hi Marc,
>>
>> On 2019/10/27 22:42, Marc Zyngier wrote:
>>> The infamous VPE proxy device isn't used with GICv4.1 because:
>>> - we can invalidate any LPI from the DirectLPI MMIO interface
>>> - the ITS and redistributors understand the life cycle of
>>>    the doorbell, so we don't need to enable/disable it all
>>>    the time
>>> So let's escape early from the proxy related functions.
>>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>>
>> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com>
>>
>>> ---
>>>   drivers/irqchip/irq-gic-v3-its.c | 23 ++++++++++++++++++++++-
>>>   1 file changed, 22 insertions(+), 1 deletion(-)
>>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>>> b/drivers/irqchip/irq-gic-v3-its.c
>>> index 220d490d516e..999e61a9b2c3 100644
>>> --- a/drivers/irqchip/irq-gic-v3-its.c
>>> +++ b/drivers/irqchip/irq-gic-v3-its.c
>>> @@ -3069,7 +3069,7 @@ static const struct irq_domain_ops 
>>> its_domain_ops = {
>>>   /*
>>>    * This is insane.
>>>    *
>>> - * If a GICv4 doesn't implement Direct LPIs (which is extremely
>>> + * If a GICv4.0 doesn't implement Direct LPIs (which is extremely
>>>    * likely), the only way to perform an invalidate is to use a fake
>>>    * device to issue an INV command, implying that the LPI has first
>>>    * been mapped to some event on that device. Since this is not exactly
>>> @@ -3077,9 +3077,18 @@ static const struct irq_domain_ops 
>>> its_domain_ops = {
>>>    * only issue an UNMAP if we're short on available slots.
>>>    *
>>>    * Broken by design(tm).
>>> + *
>>> + * GICv4.1 actually mandates that we're able to invalidate by 
>>> writing to a
>>> + * MMIO register. It doesn't implement the whole of DirectLPI, but 
>>> that's
>>> + * good enough. And most of the time, we don't even have to invalidate
>>> + * anything, so that's actually pretty good!
>>
>> I can't understand the meaning of this last sentence. May I ask for an
>> explanation? :)
> 
> Yeah, reading this now, it feels pretty clumsy, and only remotely
> connected to the patch.
> 
> What I'm trying to say here is that, although GICv4.1 doesn't have
> the full spectrum of v4.0 DirectLPI (it only allows a subset of it),
> this subset is more then enough for us. Here's the rational:
> 
> When a vPE exits from the hypervisor, we know whether we need to
> request a doorbell or not (depending on whether we're blocking on
> WFI or not). On GICv4.0, this translates into enabling the doorbell
> interrupt, which generates an invalidation (costly). And whenever
> we've taken a doorbell, or are scheduled again, we need to turn
> the doorbell off (invalidation again).
> 
> With v4.1, we can just say *at exit time* whether we want doorbells
> to be subsequently generated (see its_vpe_4_1_deschedule() and the
> req_db parameter in the info structure). This is part of making
> the vPE non-resident, so we have 0 overhead at this stage.

Great, and get it. Thanks for this clear explanation!


Zenghui

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation
  2019-10-27 14:42 ` [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation Marc Zyngier
@ 2019-12-24  7:10   ` Zenghui Yu
  2019-12-24  9:19     ` Marc Zyngier
  0 siblings, 1 reply; 72+ messages in thread
From: Zenghui Yu @ 2019-12-24  7:10 UTC (permalink / raw)
  To: Marc Zyngier, kvmarm, linux-kernel
  Cc: Lorenzo Pieralisi, Jason Cooper, wangwudi, Robert Richter,
	Jayachandran C, Thomas Gleixner

Hi Marc,

[ +Wudi and Nianyao. As they spotted the following issue but
  I forgot to send it out. ]

On 2019/10/27 22:42, Marc Zyngier wrote:
> GICv4.1 defines a new VPE table that is potentially shared between
> both the ITSs and the redistributors, following complicated affinity
> rules.
> 
> To make things more confusing, the programming of this table at
> the redistributor level is reusing the GICv4.0 GICR_VPROPBASER register
> for something completely different.
> 
> The code flow is somewhat complexified by the need to respect the
> affinities required by the HW, meaning that tables can either be
> inherited from a previously discovered ITS or redistributor.
> 
> Signed-off-by: Marc Zyngier <maz@kernel.org>
> ---[...]
> diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
> index 40912b3fb0e1..478d3678850c 100644
> --- a/drivers/irqchip/irq-gic-v3-its.c
> +++ b/drivers/irqchip/irq-gic-v3-its.c
[...]
> @@ -2025,6 +2098,214 @@ static int its_alloc_tables(struct its_node *its)
>   	return 0;
>   }
>   
> +static u64 inherit_vpe_l1_table_from_its(void)
> +{
> +	struct its_node *its;
> +	u64 val;
> +	u32 aff;
> +
> +	val = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
> +	aff = compute_common_aff(val);
> +
> +	list_for_each_entry(its, &its_nodes, entry) {
> +		u64 baser;
> +
> +		if (!is_v4_1(its))
> +			continue;
> +
> +		if (!FIELD_GET(GITS_TYPER_SVPET, its->typer))
> +			continue;
> +
> +		if (aff != compute_its_aff(its))
> +			continue;
> +
> +		/* GICv4.1 guarantees that the vPE table is GITS_BASER2 */
> +		baser = its->tables[2].val;
> +		if (!(baser & GITS_BASER_VALID))
> +			continue;
> +
> +		/* We have a winner! */
> +		val  = GICR_VPROPBASER_4_1_VALID;
> +		if (baser & GITS_BASER_INDIRECT)
> +			val |= GICR_VPROPBASER_4_1_INDIRECT;
> +		val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE,
> +				  FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser));
> +		val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR,
> +				  GITS_BASER_ADDR_48_to_52(baser) >> 12);

We've used GITS_BASER_ADDR_48_to_52() only in the KVM code where the
pagesize of ITS table is fixed to 64K.
It may not work when the pagesize is 4K or 16K?


Thanks,
Zenghui

> +		val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK,
> +				  FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser));
> +		val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK,
> +				  FIELD_GET(GITS_BASER_INNER_CACHEABILITY_MASK, baser));
> +		val |= FIELD_PREP(GICR_VPROPBASER_4_1_SIZE, GITS_BASER_NR_PAGES(baser) - 1);
> +
> +		return val;
> +	}
> +
> +	return 0;
> +}

_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply	[flat|nested] 72+ messages in thread

* Re: [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation
  2019-12-24  7:10   ` Zenghui Yu
@ 2019-12-24  9:19     ` Marc Zyngier
  0 siblings, 0 replies; 72+ messages in thread
From: Marc Zyngier @ 2019-12-24  9:19 UTC (permalink / raw)
  To: Zenghui Yu
  Cc: Lorenzo Pieralisi, Jason Cooper, wangwudi, linux-kernel,
	Robert Richter, Jayachandran C, Thomas Gleixner, kvmarm

Hi Zenghui,

On 2019-12-24 07:10, Zenghui Yu wrote:
> Hi Marc,
>
> [ +Wudi and Nianyao. As they spotted the following issue but
>  I forgot to send it out. ]
>
> On 2019/10/27 22:42, Marc Zyngier wrote:
>> GICv4.1 defines a new VPE table that is potentially shared between
>> both the ITSs and the redistributors, following complicated affinity
>> rules.
>> To make things more confusing, the programming of this table at
>> the redistributor level is reusing the GICv4.0 GICR_VPROPBASER 
>> register
>> for something completely different.
>> The code flow is somewhat complexified by the need to respect the
>> affinities required by the HW, meaning that tables can either be
>> inherited from a previously discovered ITS or redistributor.
>> Signed-off-by: Marc Zyngier <maz@kernel.org>
>> ---[...]
>> diff --git a/drivers/irqchip/irq-gic-v3-its.c 
>> b/drivers/irqchip/irq-gic-v3-its.c
>> index 40912b3fb0e1..478d3678850c 100644
>> --- a/drivers/irqchip/irq-gic-v3-its.c
>> +++ b/drivers/irqchip/irq-gic-v3-its.c
> [...]
>> @@ -2025,6 +2098,214 @@ static int its_alloc_tables(struct its_node 
>> *its)
>>   	return 0;
>>   }
>>   +static u64 inherit_vpe_l1_table_from_its(void)
>> +{
>> +	struct its_node *its;
>> +	u64 val;
>> +	u32 aff;
>> +
>> +	val = gic_read_typer(gic_data_rdist_rd_base() + GICR_TYPER);
>> +	aff = compute_common_aff(val);
>> +
>> +	list_for_each_entry(its, &its_nodes, entry) {
>> +		u64 baser;
>> +
>> +		if (!is_v4_1(its))
>> +			continue;
>> +
>> +		if (!FIELD_GET(GITS_TYPER_SVPET, its->typer))
>> +			continue;
>> +
>> +		if (aff != compute_its_aff(its))
>> +			continue;
>> +
>> +		/* GICv4.1 guarantees that the vPE table is GITS_BASER2 */
>> +		baser = its->tables[2].val;
>> +		if (!(baser & GITS_BASER_VALID))
>> +			continue;
>> +
>> +		/* We have a winner! */
>> +		val  = GICR_VPROPBASER_4_1_VALID;
>> +		if (baser & GITS_BASER_INDIRECT)
>> +			val |= GICR_VPROPBASER_4_1_INDIRECT;
>> +		val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE,
>> +				  FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser));
>> +		val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR,
>> +				  GITS_BASER_ADDR_48_to_52(baser) >> 12);
>
> We've used GITS_BASER_ADDR_48_to_52() only in the KVM code where the
> pagesize of ITS table is fixed to 64K.
> It may not work when the pagesize is 4K or 16K?

You're absolutely right, we shouldn't mess with the 52bit macros when
PZ isn't set to 64k. I'm adding the following fix to this patch:

diff --git a/drivers/irqchip/irq-gic-v3-its.c 
b/drivers/irqchip/irq-gic-v3-its.c
index e1f8d5f9a0e3..3234bb9fbdbe 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -2433,7 +2433,7 @@ static u64 inherit_vpe_l1_table_from_its(void)
  	aff = compute_common_aff(val);

  	list_for_each_entry(its, &its_nodes, entry) {
-		u64 baser;
+		u64 baser, addr;

  		if (!is_v4_1(its))
  			continue;
@@ -2455,8 +2455,15 @@ static u64 inherit_vpe_l1_table_from_its(void)
  			val |= GICR_VPROPBASER_4_1_INDIRECT;
  		val |= FIELD_PREP(GICR_VPROPBASER_4_1_PAGE_SIZE,
  				  FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser));
-		val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR,
-				  GITS_BASER_ADDR_48_to_52(baser) >> 12);
+		switch (FIELD_GET(GITS_BASER_PAGE_SIZE_MASK, baser)) {
+		case GIC_PAGE_SIZE_64K:
+			addr = GITS_BASER_ADDR_48_to_52(baser);
+			break;
+		default:
+			addr = baser & GENMASK_ULL(47, 12);
+			break;
+		}
+		val |= FIELD_PREP(GICR_VPROPBASER_4_1_ADDR, addr >> 12);
  		val |= FIELD_PREP(GICR_VPROPBASER_SHAREABILITY_MASK,
  				  FIELD_GET(GITS_BASER_SHAREABILITY_MASK, baser));
  		val |= FIELD_PREP(GICR_VPROPBASER_INNER_CACHEABILITY_MASK,


Thanks again,

         M.
-- 
Jazz is not dead. It just smells funny...
_______________________________________________
kvmarm mailing list
kvmarm@lists.cs.columbia.edu
https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

^ permalink raw reply related	[flat|nested] 72+ messages in thread

end of thread, other threads:[~2019-12-24  9:19 UTC | newest]

Thread overview: 72+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-27 14:41 [PATCH v2 00/36] irqchip/gic-v4: GICv4.1 architecture support Marc Zyngier
2019-10-27 14:41 ` [PATCH v2 01/36] KVM: arm64: vgic-v4: Move the GICv4 residency flow to be driven by vcpu_load/put Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 02/36] irqchip/gic-v3-its: Factor out wait_for_syncr primitive Marc Zyngier
2019-10-28  9:20   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 03/36] irqchip/gic-v3-its: Allow LPI invalidation via the DirectLPI interface Marc Zyngier
2019-10-31  8:49   ` Zenghui Yu
2019-11-01 13:26     ` Marc Zyngier
2019-11-05 10:30       ` Zenghui Yu
2019-11-05 12:12         ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 04/36] irqchip/gic-v3-its: Make is_v4 use a TYPER copy Marc Zyngier
2019-10-28  9:34   ` Zenghui Yu
2019-10-28 10:52     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 05/36] irqchip/gic-v3-its: Kill its->ite_size and use TYPER copy instead Marc Zyngier
2019-10-28  9:40   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 06/36] irqchip/gic-v3-its: Kill its->device_ids " Marc Zyngier
2019-10-31  6:33   ` Zenghui Yu
2019-10-31  8:30     ` Marc Zyngier
2019-10-31  9:08       ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 07/36] irqchip/gic-v3-its: Add get_vlpi_map() helper Marc Zyngier
2019-10-31  3:54   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 08/36] irqchip/gic-v3: Detect GICv4.1 supporting RVPEID Marc Zyngier
2019-10-31 11:34   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 09/36] irqchip/gic-v3: Add GICv4.1 VPEID size discovery Marc Zyngier
2019-10-31 12:02   ` Zenghui Yu
2019-11-01 15:13     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 10/36] irqchip/gic-v3: Workaround Cavium TX1 erratum when reading GICD_TYPER2 Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 11/36] irqchip/gic-v4.1: VPE table (aka GICR_VPROPBASER) allocation Marc Zyngier
2019-12-24  7:10   ` Zenghui Yu
2019-12-24  9:19     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 12/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMAPP Marc Zyngier
2019-11-01 10:58   ` Zenghui Yu
2019-11-13  8:02   ` Zenghui Yu
2019-11-13  9:47     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 13/36] irqchip/gic-v4.1: Don't use the VPE proxy if RVPEID is set Marc Zyngier
2019-11-01 11:05   ` Zenghui Yu
2019-12-18 14:39     ` Marc Zyngier
2019-12-19  3:05       ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 14/36] irqchip/gic-v4.1: Implement the v4.1 flavour of VMOVP Marc Zyngier
2019-11-01 11:10   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 15/36] irqchip/gic-v4.1: Plumb skeletal VPE irqchip Marc Zyngier
2019-11-01 11:13   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 16/36] irqchip/gic-v4.1: Add mask/unmask doorbell callbacks Marc Zyngier
2019-11-01 11:23   ` Zenghui Yu
2019-12-18 15:06     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 17/36] irqchip/gic-v4.1: Add VPE residency callback Marc Zyngier
2019-11-01 11:34   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 18/36] irqchip/gic-v4.1: Add VPE eviction callback Marc Zyngier
2019-11-01 11:39   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 19/36] irqchip/gic-v4.1: Add VPE INVALL callback Marc Zyngier
2019-11-01 11:51   ` Zenghui Yu
2019-12-18 14:18     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 20/36] irqchip/gic-v4.1: Suppress per-VLPI doorbell Marc Zyngier
2019-11-01 12:17   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 21/36] irqchip/gic-v4.1: Allow direct invalidation of VLPIs Marc Zyngier
2019-11-01 12:30   ` Zenghui Yu
2019-10-27 14:42 ` [PATCH v2 22/36] irqchip/gic-v4.1: Advertise support v4.1 to KVM Marc Zyngier
2019-11-01 12:55   ` Zenghui Yu
2019-12-18 14:48     ` Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 23/36] irqchip/gic-v4.1: Map the ITS SGIR register page Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 24/36] irqchip/gic-v4.1: Plumb skeletal VSGI irqchip Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 25/36] irqchip/gic-v4.1: Add initial SGI configuration Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 26/36] irqchip/gic-v4.1: Plumb mask/unmask SGI callbacks Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 27/36] irqchip/gic-v4.1: Plumb get/set_irqchip_state " Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 28/36] irqchip/gic-v4.1: Plumb set_vcpu_affinity " Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 29/36] irqchip/gic-v4.1: Move doorbell management to the GICv4 abstraction layer Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 30/36] irqchip/gic-v4.1: Add VSGI allocation/teardown Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 31/36] irqchip/gic-v4.1: Add VSGI property setup Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 32/36] irqchip/gic-v4.1: Eagerly vmap vPEs Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 33/36] KVM: arm64: GICv4.1: Let doorbells be auto-enabled Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 34/36] KVM: arm64: GICv4.1: Add direct injection capability to SGI registers Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 35/36] KVM: arm64: GICv4.1: Configure SGIs as HW interrupts Marc Zyngier
2019-10-27 14:42 ` [PATCH v2 36/36] KVM: arm64: GICv4.1: Expose HW-based SGIs in debugfs Marc Zyngier

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).