All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v4 00/26] KVM/ARM: Add support for GICv4
@ 2017-10-06 15:33 ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

This series implements full support for GICv4 in KVM, bringing direct
injection of MSIs to arm and arm64, assuming you have the right
hardware (which is quite unlikely).

To get an idea of the design, I'd recommend you start with commit
7954907bedaf as well as patch #26, which try to shed some light on the
approach that I've taken. And before that, please digest some of the
GICv3/GICv4 architecture documentation[1] (less than 800 pages!). Once
you feel reasonably insane, you'll be in the right mood to read the
code (no, I didn't bother changing the above, I already hit LWN/QotW
once).

Now that the low-level irqchip code has been merged, what we have here
is only the KVM-specific part. I've lifted two of Eric's patches
(having slightly changed one of them) as they form the base of this
series.

The stack has been *very lightly* tested on an arm64 model, with a PCI
virtio block device passed from the host to a guest (using kvmtool and
Jean-Philippe Brucker's excellent VFIO support patches[3]), as well as
on a Huawei D05 box using an Intel I350 Ethernet card and passing a VF
into the guest. So far, things are solid enough (although some HW need
workarounds that I'll address separately).

I've pushed out a branch based on 4.14-rc3 containing the dependencies:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/gicv4-kvm

* From v3:
   - Lots of cleanups following Christoffer's review
   - Got rid of all of the irqchip code (well, merged it)
   - Picked the minimal set of patches from Eric to get this working
   - Prevent VM save if using GICv4
   - Rebased on top of 4.14-rc3

* From v2:
  - Lots of fixes all over the map (the doorbell code was amazingly
    wrong, both at the GICv4 level and in KVM)
  - KVM GICv4 enablement is now gated by a command-line option and
    defaults to off
  - Now properly deals with ordering of vITS creation
  - Some debugging features
  - More documentation so that I can forget what this is all about
  - Huawei D05 quirks

* From v1:
  - The bulk of the 30-something initial patches have seen countless
    bugs being fixed, and some key data structures have been subtly
    tweaked (or killed altogether). They are still quite similar to
    what I had in v1 though.
  - The whole KVM code is brand new and as I said above, only lightly
    tested.
  - Collected a bunch a R-bs from Thomas and Eric (many thanks, guys).

[1] https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_architecture_specification.pfd
[2] http://www.spinics.net/lists/kvm/msg151463.html
[3] http://www.spinics.net/lists/kvm/msg151823.html

Eric Auger (2):
  KVM: arm/arm64: register irq bypass consumer on ARM/ARM64
  KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq

Marc Zyngier (24):
  KVM: arm: Select ARM_GIC_V3 and ARM_GIC_V3_ITS
  KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around
  KVM: arm/arm64: vITS: Add MSI translation helpers
  KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI
  KVM: arm/arm64: GICv4: Add property field and per-VM predicate
  KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
  KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq
    bypass
  KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI
  KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI
  KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS
  KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI
  KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
  KVM: arm/arm64: GICv4: Propagate property updates to VLPIs
  KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE
  KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint
  KVM: arm/arm64: GICv4: Add doorbell interrupt handling
  KVM: arm/arm64: GICv4: Use the doorbell interrupt as an unblocking
    source
  KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
  KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered
  KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
  KVM: arm/arm64: GICv4: Enable VLPI support
  KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  KVM: arm/arm64: GICv4: Theory of operations

 Documentation/admin-guide/kernel-parameters.txt |   4 +
 arch/arm/kvm/Kconfig                            |   5 +
 arch/arm/kvm/Makefile                           |   1 +
 arch/arm64/kvm/Kconfig                          |   3 +
 arch/arm64/kvm/Makefile                         |   1 +
 include/kvm/arm_vgic.h                          |  41 ++-
 include/linux/irqchip/arm-gic-v3.h              |   2 +
 virt/kvm/arm/arch_timer.c                       |  24 +-
 virt/kvm/arm/arm.c                              |  48 +++-
 virt/kvm/arm/hyp/vgic-v3-sr.c                   |   9 +-
 virt/kvm/arm/vgic/vgic-init.c                   |   9 +
 virt/kvm/arm/vgic/vgic-its.c                    | 195 ++++++++-----
 virt/kvm/arm/vgic/vgic-mmio-v3.c                |   5 +
 virt/kvm/arm/vgic/vgic-v3.c                     |  39 ++-
 virt/kvm/arm/vgic/vgic-v4.c                     | 361 ++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c                        |  67 ++++-
 virt/kvm/arm/vgic/vgic.h                        |  12 +
 17 files changed, 713 insertions(+), 113 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v4.c

-- 
2.14.1

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

* [PATCH v4 00/26] KVM/ARM: Add support for GICv4
@ 2017-10-06 15:33 ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

This series implements full support for GICv4 in KVM, bringing direct
injection of MSIs to arm and arm64, assuming you have the right
hardware (which is quite unlikely).

To get an idea of the design, I'd recommend you start with commit
7954907bedaf as well as patch #26, which try to shed some light on the
approach that I've taken. And before that, please digest some of the
GICv3/GICv4 architecture documentation[1] (less than 800 pages!). Once
you feel reasonably insane, you'll be in the right mood to read the
code (no, I didn't bother changing the above, I already hit LWN/QotW
once).

Now that the low-level irqchip code has been merged, what we have here
is only the KVM-specific part. I've lifted two of Eric's patches
(having slightly changed one of them) as they form the base of this
series.

The stack has been *very lightly* tested on an arm64 model, with a PCI
virtio block device passed from the host to a guest (using kvmtool and
Jean-Philippe Brucker's excellent VFIO support patches[3]), as well as
on a Huawei D05 box using an Intel I350 Ethernet card and passing a VF
into the guest. So far, things are solid enough (although some HW need
workarounds that I'll address separately).

I've pushed out a branch based on 4.14-rc3 containing the dependencies:

git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git kvm-arm64/gicv4-kvm

* From v3:
   - Lots of cleanups following Christoffer's review
   - Got rid of all of the irqchip code (well, merged it)
   - Picked the minimal set of patches from Eric to get this working
   - Prevent VM save if using GICv4
   - Rebased on top of 4.14-rc3

* From v2:
  - Lots of fixes all over the map (the doorbell code was amazingly
    wrong, both at the GICv4 level and in KVM)
  - KVM GICv4 enablement is now gated by a command-line option and
    defaults to off
  - Now properly deals with ordering of vITS creation
  - Some debugging features
  - More documentation so that I can forget what this is all about
  - Huawei D05 quirks

* From v1:
  - The bulk of the 30-something initial patches have seen countless
    bugs being fixed, and some key data structures have been subtly
    tweaked (or killed altogether). They are still quite similar to
    what I had in v1 though.
  - The whole KVM code is brand new and as I said above, only lightly
    tested.
  - Collected a bunch a R-bs from Thomas and Eric (many thanks, guys).

[1] https://static.docs.arm.com/ihi0069/c/IHI0069C_gic_architecture_specification.pfd
[2] http://www.spinics.net/lists/kvm/msg151463.html
[3] http://www.spinics.net/lists/kvm/msg151823.html

Eric Auger (2):
  KVM: arm/arm64: register irq bypass consumer on ARM/ARM64
  KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq

Marc Zyngier (24):
  KVM: arm: Select ARM_GIC_V3 and ARM_GIC_V3_ITS
  KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around
  KVM: arm/arm64: vITS: Add MSI translation helpers
  KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI
  KVM: arm/arm64: GICv4: Add property field and per-VM predicate
  KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
  KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq
    bypass
  KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI
  KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI
  KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS
  KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI
  KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
  KVM: arm/arm64: GICv4: Propagate property updates to VLPIs
  KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE
  KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint
  KVM: arm/arm64: GICv4: Add doorbell interrupt handling
  KVM: arm/arm64: GICv4: Use the doorbell interrupt as an unblocking
    source
  KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
  KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered
  KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
  KVM: arm/arm64: GICv4: Enable VLPI support
  KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  KVM: arm/arm64: GICv4: Theory of operations

 Documentation/admin-guide/kernel-parameters.txt |   4 +
 arch/arm/kvm/Kconfig                            |   5 +
 arch/arm/kvm/Makefile                           |   1 +
 arch/arm64/kvm/Kconfig                          |   3 +
 arch/arm64/kvm/Makefile                         |   1 +
 include/kvm/arm_vgic.h                          |  41 ++-
 include/linux/irqchip/arm-gic-v3.h              |   2 +
 virt/kvm/arm/arch_timer.c                       |  24 +-
 virt/kvm/arm/arm.c                              |  48 +++-
 virt/kvm/arm/hyp/vgic-v3-sr.c                   |   9 +-
 virt/kvm/arm/vgic/vgic-init.c                   |   9 +
 virt/kvm/arm/vgic/vgic-its.c                    | 195 ++++++++-----
 virt/kvm/arm/vgic/vgic-mmio-v3.c                |   5 +
 virt/kvm/arm/vgic/vgic-v3.c                     |  39 ++-
 virt/kvm/arm/vgic/vgic-v4.c                     | 361 ++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c                        |  67 ++++-
 virt/kvm/arm/vgic/vgic.h                        |  12 +
 17 files changed, 713 insertions(+), 113 deletions(-)
 create mode 100644 virt/kvm/arm/vgic/vgic-v4.c

-- 
2.14.1

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

* [PATCH v4 01/26] KVM: arm/arm64: register irq bypass consumer on ARM/ARM64
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

From: Eric Auger <eric.auger@redhat.com>

This patch selects IRQ_BYPASS_MANAGER and HAVE_KVM_IRQ_BYPASS
configs for ARM/ARM64.

kvm_arch_has_irq_bypass() now is implemented and returns true.
As a consequence the irq bypass consumer will be registered for
ARM/ARM64 with the forwarding callbacks:

- stop/start: halt/resume guest execution
- add/del_producer: set/unset forwarding at vgic/irqchip level

We don't have any actual support yet, so nothing gets actually
forwarded.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
[maz: dropped the DEOI stuff for the time being in order to
      reduce the dependency chain, amended commit message]
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/Kconfig   |  3 +++
 arch/arm64/kvm/Kconfig |  3 +++
 virt/kvm/arm/arm.c     | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 90d0176fb30d..4e2b192a030a 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -3,6 +3,7 @@
 #
 
 source "virt/kvm/Kconfig"
+source "virt/lib/Kconfig"
 
 menuconfig VIRTUALIZATION
 	bool "Virtualization"
@@ -35,6 +36,8 @@ config KVM
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQ_ROUTING
 	select HAVE_KVM_MSI
+	select IRQ_BYPASS_MANAGER
+	select HAVE_KVM_IRQ_BYPASS
 	depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
 	---help---
 	  Support hosting virtualized guest machines.
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 52cb7ad9b2fd..7e0d6e63cc71 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -3,6 +3,7 @@
 #
 
 source "virt/kvm/Kconfig"
+source "virt/lib/Kconfig"
 
 menuconfig VIRTUALIZATION
 	bool "Virtualization"
@@ -35,6 +36,8 @@ config KVM
 	select HAVE_KVM_MSI
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQ_ROUTING
+	select IRQ_BYPASS_MANAGER
+	select HAVE_KVM_IRQ_BYPASS
 	---help---
 	  Support hosting virtualized guest machines.
 	  We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index b9f68e4add71..7ac4ecba9ebd 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -27,6 +27,8 @@
 #include <linux/mman.h>
 #include <linux/sched.h>
 #include <linux/kvm.h>
+#include <linux/kvm_irqfd.h>
+#include <linux/irqbypass.h>
 #include <trace/events/kvm.h>
 #include <kvm/arm_pmu.h>
 
@@ -1449,6 +1451,44 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
 	return NULL;
 }
 
+bool kvm_arch_has_irq_bypass(void)
+{
+	return true;
+}
+
+int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
+				      struct irq_bypass_producer *prod)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	return 0;
+}
+void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
+				      struct irq_bypass_producer *prod)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	return;
+}
+
+void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	kvm_arm_halt_guest(irqfd->kvm);
+}
+
+void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *cons)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	kvm_arm_resume_guest(irqfd->kvm);
+}
+
 /**
  * Initialize Hyp-mode and memory mappings on all CPUs.
  */
-- 
2.14.1

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

* [PATCH v4 01/26] KVM: arm/arm64: register irq bypass consumer on ARM/ARM64
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Eric Auger <eric.auger@redhat.com>

This patch selects IRQ_BYPASS_MANAGER and HAVE_KVM_IRQ_BYPASS
configs for ARM/ARM64.

kvm_arch_has_irq_bypass() now is implemented and returns true.
As a consequence the irq bypass consumer will be registered for
ARM/ARM64 with the forwarding callbacks:

- stop/start: halt/resume guest execution
- add/del_producer: set/unset forwarding at vgic/irqchip level

We don't have any actual support yet, so nothing gets actually
forwarded.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
[maz: dropped the DEOI stuff for the time being in order to
      reduce the dependency chain, amended commit message]
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/Kconfig   |  3 +++
 arch/arm64/kvm/Kconfig |  3 +++
 virt/kvm/arm/arm.c     | 40 ++++++++++++++++++++++++++++++++++++++++
 3 files changed, 46 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 90d0176fb30d..4e2b192a030a 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -3,6 +3,7 @@
 #
 
 source "virt/kvm/Kconfig"
+source "virt/lib/Kconfig"
 
 menuconfig VIRTUALIZATION
 	bool "Virtualization"
@@ -35,6 +36,8 @@ config KVM
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQ_ROUTING
 	select HAVE_KVM_MSI
+	select IRQ_BYPASS_MANAGER
+	select HAVE_KVM_IRQ_BYPASS
 	depends on ARM_VIRT_EXT && ARM_LPAE && ARM_ARCH_TIMER
 	---help---
 	  Support hosting virtualized guest machines.
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index 52cb7ad9b2fd..7e0d6e63cc71 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -3,6 +3,7 @@
 #
 
 source "virt/kvm/Kconfig"
+source "virt/lib/Kconfig"
 
 menuconfig VIRTUALIZATION
 	bool "Virtualization"
@@ -35,6 +36,8 @@ config KVM
 	select HAVE_KVM_MSI
 	select HAVE_KVM_IRQCHIP
 	select HAVE_KVM_IRQ_ROUTING
+	select IRQ_BYPASS_MANAGER
+	select HAVE_KVM_IRQ_BYPASS
 	---help---
 	  Support hosting virtualized guest machines.
 	  We don't support KVM with 16K page tables yet, due to the multiple
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index b9f68e4add71..7ac4ecba9ebd 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -27,6 +27,8 @@
 #include <linux/mman.h>
 #include <linux/sched.h>
 #include <linux/kvm.h>
+#include <linux/kvm_irqfd.h>
+#include <linux/irqbypass.h>
 #include <trace/events/kvm.h>
 #include <kvm/arm_pmu.h>
 
@@ -1449,6 +1451,44 @@ struct kvm_vcpu *kvm_mpidr_to_vcpu(struct kvm *kvm, unsigned long mpidr)
 	return NULL;
 }
 
+bool kvm_arch_has_irq_bypass(void)
+{
+	return true;
+}
+
+int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
+				      struct irq_bypass_producer *prod)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	return 0;
+}
+void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
+				      struct irq_bypass_producer *prod)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	return;
+}
+
+void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	kvm_arm_halt_guest(irqfd->kvm);
+}
+
+void kvm_arch_irq_bypass_start(struct irq_bypass_consumer *cons)
+{
+	struct kvm_kernel_irqfd *irqfd =
+		container_of(cons, struct kvm_kernel_irqfd, consumer);
+
+	kvm_arm_resume_guest(irqfd->kvm);
+}
+
 /**
  * Initialize Hyp-mode and memory mappings on all CPUs.
  */
-- 
2.14.1

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

* [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

From: Eric Auger <eric.auger@redhat.com>

We want to reuse the core of the map/unmap functions for IRQ
forwarding. Let's move the computation of the hwirq in
kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
the host_irq is added to struct vgic_irq.

We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
handle as a parameter.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 include/kvm/arm_vgic.h    |  8 ++++---
 virt/kvm/arm/arch_timer.c | 24 +------------------
 virt/kvm/arm/vgic/vgic.c  | 60 +++++++++++++++++++++++++++++++++++------------
 3 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 34dba516ef24..53f631bdec75 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -116,6 +116,7 @@ struct vgic_irq {
 	bool hw;			/* Tied to HW IRQ */
 	struct kref refcount;		/* Used for LPIs */
 	u32 hwintid;			/* HW INTID number */
+	unsigned int host_irq;		/* linux irq corresponding to hwintid */
 	union {
 		u8 targets;			/* GICv2 target VCPUs mask */
 		u32 mpidr;			/* GICv3 target VCPU */
@@ -307,9 +308,10 @@ void kvm_vgic_init_cpu_hardware(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level, void *owner);
-int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
+			  u32 vintid);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 8e89d63005c7..b24e2f7b363a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -647,9 +647,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 	int ret;
 
 	if (timer->enabled)
@@ -667,26 +664,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 		return -EINVAL;
 	}
 
-	/*
-	 * Find the physical IRQ number corresponding to the host_vtimer_irq
-	 */
-	desc = irq_to_desc(host_vtimer_irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
-
-	/*
-	 * Tell the VGIC that the virtual interrupt is tied to a
-	 * physical interrupt. We do that once per VCPU.
-	 */
-	ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
+	ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq);
 	if (ret)
 		return ret;
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fed717e07938..9d557efd1f7d 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -17,6 +17,8 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/list_sort.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include "vgic.h"
 
@@ -403,38 +405,66 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return 0;
 }
 
-int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+/* @irq->irq_lock must be held */
+static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+			    unsigned int host_irq)
 {
-	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	struct irq_desc *desc;
+	struct irq_data *data;
 
-	BUG_ON(!irq);
-
-	spin_lock(&irq->irq_lock);
+	/*
+	 * Find the physical IRQ number corresponding to @host_irq
+	 */
+	desc = irq_to_desc(host_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
 
 	irq->hw = true;
-	irq->hwintid = phys_irq;
+	irq->host_irq = host_irq;
+	irq->hwintid = data->hwirq;
+	return 0;
+}
+
+/* @irq->irq_lock must be held */
+static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
+{
+	irq->hw = false;
+	irq->hwintid = 0;
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
+			  u32 vintid)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+	int ret;
 
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+	ret = kvm_vgic_map_irq(vcpu, irq, host_irq);
 	spin_unlock(&irq->irq_lock);
 	vgic_put_irq(vcpu->kvm, irq);
 
-	return 0;
+	return ret;
 }
 
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
 {
 	struct vgic_irq *irq;
 
 	if (!vgic_initialized(vcpu->kvm))
 		return -EAGAIN;
 
-	irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
 	BUG_ON(!irq);
 
 	spin_lock(&irq->irq_lock);
-
-	irq->hw = false;
-	irq->hwintid = 0;
-
+	kvm_vgic_unmap_irq(irq);
 	spin_unlock(&irq->irq_lock);
 	vgic_put_irq(vcpu->kvm, irq);
 
@@ -772,9 +802,9 @@ void vgic_kick_vcpus(struct kvm *kvm)
 	}
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
 {
-	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
 	bool map_is_active;
 
 	spin_lock(&irq->irq_lock);
-- 
2.14.1

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

* [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

From: Eric Auger <eric.auger@redhat.com>

We want to reuse the core of the map/unmap functions for IRQ
forwarding. Let's move the computation of the hwirq in
kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
the host_irq is added to struct vgic_irq.

We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
handle as a parameter.

Signed-off-by: Eric Auger <eric.auger@redhat.com>
---
 include/kvm/arm_vgic.h    |  8 ++++---
 virt/kvm/arm/arch_timer.c | 24 +------------------
 virt/kvm/arm/vgic/vgic.c  | 60 +++++++++++++++++++++++++++++++++++------------
 3 files changed, 51 insertions(+), 41 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 34dba516ef24..53f631bdec75 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -116,6 +116,7 @@ struct vgic_irq {
 	bool hw;			/* Tied to HW IRQ */
 	struct kref refcount;		/* Used for LPIs */
 	u32 hwintid;			/* HW INTID number */
+	unsigned int host_irq;		/* linux irq corresponding to hwintid */
 	union {
 		u8 targets;			/* GICv2 target VCPUs mask */
 		u32 mpidr;			/* GICv3 target VCPU */
@@ -307,9 +308,10 @@ void kvm_vgic_init_cpu_hardware(void);
 
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 			bool level, void *owner);
-int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
+			  u32 vintid);
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
 
 int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
 
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 8e89d63005c7..b24e2f7b363a 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -647,9 +647,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 {
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
-	struct irq_desc *desc;
-	struct irq_data *data;
-	int phys_irq;
 	int ret;
 
 	if (timer->enabled)
@@ -667,26 +664,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
 		return -EINVAL;
 	}
 
-	/*
-	 * Find the physical IRQ number corresponding to the host_vtimer_irq
-	 */
-	desc = irq_to_desc(host_vtimer_irq);
-	if (!desc) {
-		kvm_err("%s: no interrupt descriptor\n", __func__);
-		return -EINVAL;
-	}
-
-	data = irq_desc_get_irq_data(desc);
-	while (data->parent_data)
-		data = data->parent_data;
-
-	phys_irq = data->hwirq;
-
-	/*
-	 * Tell the VGIC that the virtual interrupt is tied to a
-	 * physical interrupt. We do that once per VCPU.
-	 */
-	ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
+	ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq);
 	if (ret)
 		return ret;
 
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index fed717e07938..9d557efd1f7d 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -17,6 +17,8 @@
 #include <linux/kvm.h>
 #include <linux/kvm_host.h>
 #include <linux/list_sort.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
 
 #include "vgic.h"
 
@@ -403,38 +405,66 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
 	return 0;
 }
 
-int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
+/* @irq->irq_lock must be held */
+static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
+			    unsigned int host_irq)
 {
-	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	struct irq_desc *desc;
+	struct irq_data *data;
 
-	BUG_ON(!irq);
-
-	spin_lock(&irq->irq_lock);
+	/*
+	 * Find the physical IRQ number corresponding to @host_irq
+	 */
+	desc = irq_to_desc(host_irq);
+	if (!desc) {
+		kvm_err("%s: no interrupt descriptor\n", __func__);
+		return -EINVAL;
+	}
+	data = irq_desc_get_irq_data(desc);
+	while (data->parent_data)
+		data = data->parent_data;
 
 	irq->hw = true;
-	irq->hwintid = phys_irq;
+	irq->host_irq = host_irq;
+	irq->hwintid = data->hwirq;
+	return 0;
+}
+
+/* @irq->irq_lock must be held */
+static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
+{
+	irq->hw = false;
+	irq->hwintid = 0;
+}
+
+int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
+			  u32 vintid)
+{
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
+	int ret;
 
+	BUG_ON(!irq);
+
+	spin_lock(&irq->irq_lock);
+	ret = kvm_vgic_map_irq(vcpu, irq, host_irq);
 	spin_unlock(&irq->irq_lock);
 	vgic_put_irq(vcpu->kvm, irq);
 
-	return 0;
+	return ret;
 }
 
-int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
 {
 	struct vgic_irq *irq;
 
 	if (!vgic_initialized(vcpu->kvm))
 		return -EAGAIN;
 
-	irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
 	BUG_ON(!irq);
 
 	spin_lock(&irq->irq_lock);
-
-	irq->hw = false;
-	irq->hwintid = 0;
-
+	kvm_vgic_unmap_irq(irq);
 	spin_unlock(&irq->irq_lock);
 	vgic_put_irq(vcpu->kvm, irq);
 
@@ -772,9 +802,9 @@ void vgic_kick_vcpus(struct kvm *kvm)
 	}
 }
 
-bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
+bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
 {
-	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
+	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
 	bool map_is_active;
 
 	spin_lock(&irq->irq_lock);
-- 
2.14.1

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

* [PATCH v4 03/26] KVM: arm: Select ARM_GIC_V3 and ARM_GIC_V3_ITS
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

The GICv4 support introduces a hard dependency between the KVM
core and the ITS infrastructure. arm64 already selects it at
the architecture level, but 32bit doesn't. In order to avoid
littering the kernel with #ifdefs, let's just select the whole
of the GICv3 suport code.

You know you want it.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 4e2b192a030a..52b50af04e3b 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -23,6 +23,8 @@ config KVM
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
 	select ARM_GIC
+	select ARM_GIC_V3
+	select ARM_GIC_V3_ITS
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	select HAVE_KVM_ARCH_TLB_FLUSH_ALL
 	select KVM_MMIO
-- 
2.14.1

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

* [PATCH v4 03/26] KVM: arm: Select ARM_GIC_V3 and ARM_GIC_V3_ITS
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The GICv4 support introduces a hard dependency between the KVM
core and the ITS infrastructure. arm64 already selects it at
the architecture level, but 32bit doesn't. In order to avoid
littering the kernel with #ifdefs, let's just select the whole
of the GICv3 suport code.

You know you want it.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/Kconfig | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/kvm/Kconfig b/arch/arm/kvm/Kconfig
index 4e2b192a030a..52b50af04e3b 100644
--- a/arch/arm/kvm/Kconfig
+++ b/arch/arm/kvm/Kconfig
@@ -23,6 +23,8 @@ config KVM
 	select PREEMPT_NOTIFIERS
 	select ANON_INODES
 	select ARM_GIC
+	select ARM_GIC_V3
+	select ARM_GIC_V3_ITS
 	select HAVE_KVM_CPU_RELAX_INTERCEPT
 	select HAVE_KVM_ARCH_TLB_FLUSH_ALL
 	select KVM_MMIO
-- 
2.14.1

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

* [PATCH v4 04/26] KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

The way we call kvm_vgic_destroy is a bit bizarre. We call it
*after* having freed the vcpus, which sort of defeats the point
of cleaning up things before that point.

Let's move kvm_vgic_destroy towards the beginning of kvm_arch_destroy_vm,
which seems more sensible.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 7ac4ecba9ebd..5d5218ecd547 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -177,6 +177,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 {
 	int i;
 
+	kvm_vgic_destroy(kvm);
+
 	free_percpu(kvm->arch.last_vcpu_ran);
 	kvm->arch.last_vcpu_ran = NULL;
 
@@ -186,8 +188,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 			kvm->vcpus[i] = NULL;
 		}
 	}
-
-	kvm_vgic_destroy(kvm);
 }
 
 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
-- 
2.14.1

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

* [PATCH v4 04/26] KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The way we call kvm_vgic_destroy is a bit bizarre. We call it
*after* having freed the vcpus, which sort of defeats the point
of cleaning up things before that point.

Let's move kvm_vgic_destroy towards the beginning of kvm_arch_destroy_vm,
which seems more sensible.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/arm.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 7ac4ecba9ebd..5d5218ecd547 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -177,6 +177,8 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 {
 	int i;
 
+	kvm_vgic_destroy(kvm);
+
 	free_percpu(kvm->arch.last_vcpu_ran);
 	kvm->arch.last_vcpu_ran = NULL;
 
@@ -186,8 +188,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 			kvm->vcpus[i] = NULL;
 		}
 	}
-
-	kvm_vgic_destroy(kvm);
 }
 
 int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
-- 
2.14.1

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

* [PATCH v4 05/26] KVM: arm/arm64: vITS: Add MSI translation helpers
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

The whole MSI injection process is fairly monolithic. An MSI write
gets turned into an injected LPI in one swift go. But this is actually
a more fine-grained process:

- First, a virtual ITS gets selected using the doorbell address
- Then the DevID/EventID pair gets translated into an LPI
- Finally the LPI is injected

Since the GICv4 code needs the first two steps in order to match
an IRQ routing entry to an LPI, let's expose them as helpers,
and refactor the existing code to use them

Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 93 +++++++++++++++++++++++++-------------------
 virt/kvm/arm/vgic/vgic.h     |  4 ++
 2 files changed, 57 insertions(+), 40 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f51c1e1b3f70..475dffd0a44c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -503,15 +503,8 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
 	return 0;
 }
 
-/*
- * Find the target VCPU and the LPI number for a given devid/eventid pair
- * and make this IRQ pending, possibly injecting it.
- * Must be called with the its_lock mutex held.
- * Returns 0 on success, a positive error value for any ITS mapping
- * related errors and negative error values for generic errors.
- */
-static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
-				u32 devid, u32 eventid)
+int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
+			 u32 devid, u32 eventid, struct vgic_irq **irq)
 {
 	struct kvm_vcpu *vcpu;
 	struct its_ite *ite;
@@ -530,26 +523,60 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 	if (!vcpu->arch.vgic_cpu.lpis_enabled)
 		return -EBUSY;
 
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->pending_latch = true;
-	vgic_queue_irq_unlock(kvm, ite->irq);
-
+	*irq = ite->irq;
 	return 0;
 }
 
-static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
+struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi)
 {
+	u64 address;
+	struct kvm_io_device *kvm_io_dev;
 	struct vgic_io_device *iodev;
 
-	if (dev->ops != &kvm_io_gic_ops)
-		return NULL;
+	if (!vgic_has_its(kvm))
+		return ERR_PTR(-ENODEV);
 
-	iodev = container_of(dev, struct vgic_io_device, dev);
+	if (!(msi->flags & KVM_MSI_VALID_DEVID))
+		return ERR_PTR(-EINVAL);
+
+	address = (u64)msi->address_hi << 32 | msi->address_lo;
+
+	kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
+	if (!kvm_io_dev)
+		return ERR_PTR(-EINVAL);
 
+	if (kvm_io_dev->ops != &kvm_io_gic_ops)
+		return ERR_PTR(-EINVAL);
+
+	iodev = container_of(kvm_io_dev, struct vgic_io_device, dev);
 	if (iodev->iodev_type != IODEV_ITS)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
-	return iodev;
+	return iodev->its;
+}
+
+/*
+ * Find the target VCPU and the LPI number for a given devid/eventid pair
+ * and make this IRQ pending, possibly injecting it.
+ * Must be called with the its_lock mutex held.
+ * Returns 0 on success, a positive error value for any ITS mapping
+ * related errors and negative error values for generic errors.
+ */
+static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
+				u32 devid, u32 eventid)
+{
+	struct vgic_irq *irq = NULL;
+	int err;
+
+	err = vgic_its_resolve_lpi(kvm, its, devid, eventid, &irq);
+	if (err)
+		return err;
+
+	spin_lock(&irq->irq_lock);
+	irq->pending_latch = true;
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
 }
 
 /*
@@ -560,30 +587,16 @@ static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
  */
 int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 {
-	u64 address;
-	struct kvm_io_device *kvm_io_dev;
-	struct vgic_io_device *iodev;
+	struct vgic_its *its;
 	int ret;
 
-	if (!vgic_has_its(kvm))
-		return -ENODEV;
-
-	if (!(msi->flags & KVM_MSI_VALID_DEVID))
-		return -EINVAL;
-
-	address = (u64)msi->address_hi << 32 | msi->address_lo;
-
-	kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
-	if (!kvm_io_dev)
-		return -EINVAL;
+	its = vgic_msi_to_its(kvm, msi);
+	if (IS_ERR(its))
+		return PTR_ERR(its);
 
-	iodev = vgic_get_its_iodev(kvm_io_dev);
-	if (!iodev)
-		return -EINVAL;
-
-	mutex_lock(&iodev->its->its_lock);
-	ret = vgic_its_trigger_msi(kvm, iodev->its, msi->devid, msi->data);
-	mutex_unlock(&iodev->its->its_lock);
+	mutex_lock(&its->its_lock);
+	ret = vgic_its_trigger_msi(kvm, its, msi->devid, msi->data);
+	mutex_unlock(&its->its_lock);
 
 	if (ret < 0)
 		return ret;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index bf9ceab67c77..31b70326b966 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -236,4 +236,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
 	}
 }
 
+int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
+			 u32 devid, u32 eventid, struct vgic_irq **irq);
+struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
+
 #endif
-- 
2.14.1

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

* [PATCH v4 05/26] KVM: arm/arm64: vITS: Add MSI translation helpers
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The whole MSI injection process is fairly monolithic. An MSI write
gets turned into an injected LPI in one swift go. But this is actually
a more fine-grained process:

- First, a virtual ITS gets selected using the doorbell address
- Then the DevID/EventID pair gets translated into an LPI
- Finally the LPI is injected

Since the GICv4 code needs the first two steps in order to match
an IRQ routing entry to an LPI, let's expose them as helpers,
and refactor the existing code to use them

Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 93 +++++++++++++++++++++++++-------------------
 virt/kvm/arm/vgic/vgic.h     |  4 ++
 2 files changed, 57 insertions(+), 40 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f51c1e1b3f70..475dffd0a44c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -503,15 +503,8 @@ static unsigned long vgic_mmio_read_its_idregs(struct kvm *kvm,
 	return 0;
 }
 
-/*
- * Find the target VCPU and the LPI number for a given devid/eventid pair
- * and make this IRQ pending, possibly injecting it.
- * Must be called with the its_lock mutex held.
- * Returns 0 on success, a positive error value for any ITS mapping
- * related errors and negative error values for generic errors.
- */
-static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
-				u32 devid, u32 eventid)
+int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
+			 u32 devid, u32 eventid, struct vgic_irq **irq)
 {
 	struct kvm_vcpu *vcpu;
 	struct its_ite *ite;
@@ -530,26 +523,60 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 	if (!vcpu->arch.vgic_cpu.lpis_enabled)
 		return -EBUSY;
 
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->pending_latch = true;
-	vgic_queue_irq_unlock(kvm, ite->irq);
-
+	*irq = ite->irq;
 	return 0;
 }
 
-static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
+struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi)
 {
+	u64 address;
+	struct kvm_io_device *kvm_io_dev;
 	struct vgic_io_device *iodev;
 
-	if (dev->ops != &kvm_io_gic_ops)
-		return NULL;
+	if (!vgic_has_its(kvm))
+		return ERR_PTR(-ENODEV);
 
-	iodev = container_of(dev, struct vgic_io_device, dev);
+	if (!(msi->flags & KVM_MSI_VALID_DEVID))
+		return ERR_PTR(-EINVAL);
+
+	address = (u64)msi->address_hi << 32 | msi->address_lo;
+
+	kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
+	if (!kvm_io_dev)
+		return ERR_PTR(-EINVAL);
 
+	if (kvm_io_dev->ops != &kvm_io_gic_ops)
+		return ERR_PTR(-EINVAL);
+
+	iodev = container_of(kvm_io_dev, struct vgic_io_device, dev);
 	if (iodev->iodev_type != IODEV_ITS)
-		return NULL;
+		return ERR_PTR(-EINVAL);
 
-	return iodev;
+	return iodev->its;
+}
+
+/*
+ * Find the target VCPU and the LPI number for a given devid/eventid pair
+ * and make this IRQ pending, possibly injecting it.
+ * Must be called with the its_lock mutex held.
+ * Returns 0 on success, a positive error value for any ITS mapping
+ * related errors and negative error values for generic errors.
+ */
+static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
+				u32 devid, u32 eventid)
+{
+	struct vgic_irq *irq = NULL;
+	int err;
+
+	err = vgic_its_resolve_lpi(kvm, its, devid, eventid, &irq);
+	if (err)
+		return err;
+
+	spin_lock(&irq->irq_lock);
+	irq->pending_latch = true;
+	vgic_queue_irq_unlock(kvm, irq);
+
+	return 0;
 }
 
 /*
@@ -560,30 +587,16 @@ static struct vgic_io_device *vgic_get_its_iodev(struct kvm_io_device *dev)
  */
 int vgic_its_inject_msi(struct kvm *kvm, struct kvm_msi *msi)
 {
-	u64 address;
-	struct kvm_io_device *kvm_io_dev;
-	struct vgic_io_device *iodev;
+	struct vgic_its *its;
 	int ret;
 
-	if (!vgic_has_its(kvm))
-		return -ENODEV;
-
-	if (!(msi->flags & KVM_MSI_VALID_DEVID))
-		return -EINVAL;
-
-	address = (u64)msi->address_hi << 32 | msi->address_lo;
-
-	kvm_io_dev = kvm_io_bus_get_dev(kvm, KVM_MMIO_BUS, address);
-	if (!kvm_io_dev)
-		return -EINVAL;
+	its = vgic_msi_to_its(kvm, msi);
+	if (IS_ERR(its))
+		return PTR_ERR(its);
 
-	iodev = vgic_get_its_iodev(kvm_io_dev);
-	if (!iodev)
-		return -EINVAL;
-
-	mutex_lock(&iodev->its->its_lock);
-	ret = vgic_its_trigger_msi(kvm, iodev->its, msi->devid, msi->data);
-	mutex_unlock(&iodev->its->its_lock);
+	mutex_lock(&its->its_lock);
+	ret = vgic_its_trigger_msi(kvm, its, msi->devid, msi->data);
+	mutex_unlock(&its->its_lock);
 
 	if (ret < 0)
 		return ret;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index bf9ceab67c77..31b70326b966 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -236,4 +236,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
 	}
 }
 
+int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
+			 u32 devid, u32 eventid, struct vgic_irq **irq);
+struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
+
 #endif
-- 
2.14.1

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

* [PATCH v4 06/26] KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

In order help integrating the vITS code with GICv4, let's add
a new helper that deals with updating the affinity of an LPI,
which will later be augmented with super duper extra GICv4
goodness.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 475dffd0a44c..8ee03f1e89fc 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -335,6 +335,15 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 	return i;
 }
 
+static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
+{
+	spin_lock(&irq->irq_lock);
+	irq->target_vcpu = vcpu;
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /*
  * Promotes the ITS view of affinity of an ITTE (which redistributor this LPI
  * is targeting) to the VGIC's view, which deals with target VCPUs.
@@ -349,10 +358,7 @@ static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
 		return;
 
 	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
-
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->target_vcpu = vcpu;
-	spin_unlock(&ite->irq->irq_lock);
+	update_affinity(ite->irq, vcpu);
 }
 
 /*
@@ -693,11 +699,7 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
 	ite->collection = collection;
 	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->target_vcpu = vcpu;
-	spin_unlock(&ite->irq->irq_lock);
-
-	return 0;
+	return update_affinity(ite->irq, vcpu);
 }
 
 /*
-- 
2.14.1

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

* [PATCH v4 06/26] KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

In order help integrating the vITS code with GICv4, let's add
a new helper that deals with updating the affinity of an LPI,
which will later be augmented with super duper extra GICv4
goodness.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++---------
 1 file changed, 11 insertions(+), 9 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 475dffd0a44c..8ee03f1e89fc 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -335,6 +335,15 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 	return i;
 }
 
+static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
+{
+	spin_lock(&irq->irq_lock);
+	irq->target_vcpu = vcpu;
+	spin_unlock(&irq->irq_lock);
+
+	return 0;
+}
+
 /*
  * Promotes the ITS view of affinity of an ITTE (which redistributor this LPI
  * is targeting) to the VGIC's view, which deals with target VCPUs.
@@ -349,10 +358,7 @@ static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
 		return;
 
 	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
-
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->target_vcpu = vcpu;
-	spin_unlock(&ite->irq->irq_lock);
+	update_affinity(ite->irq, vcpu);
 }
 
 /*
@@ -693,11 +699,7 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
 	ite->collection = collection;
 	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
 
-	spin_lock(&ite->irq->irq_lock);
-	ite->irq->target_vcpu = vcpu;
-	spin_unlock(&ite->irq->irq_lock);
-
-	return 0;
+	return update_affinity(ite->irq, vcpu);
 }
 
 /*
-- 
2.14.1

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

* [PATCH v4 07/26] KVM: arm/arm64: GICv4: Add property field and per-VM predicate
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

Add a new has_gicv4 field in the global VGIC state that indicates
whether the HW is GICv4 capable, as a per-VM predicate indicating
if there is a possibility for a VM to support direct injection
(the above being true and the VM having an ITS).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_vgic.h           | 3 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 5 +++++
 virt/kvm/arm/vgic/vgic.h         | 2 ++
 3 files changed, 10 insertions(+)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 53f631bdec75..ba9fb450aa1b 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -73,6 +73,9 @@ struct vgic_global {
 	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
 	bool			can_emulate_gicv2;
 
+	/* Hardware has GICv4? */
+	bool			has_gicv4;
+
 	/* GIC system register CPU interface */
 	struct static_key_false gicv3_cpuif;
 
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 408ef06638fc..f87fd17b2eb9 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -54,6 +54,11 @@ bool vgic_has_its(struct kvm *kvm)
 	return dist->has_its;
 }
 
+bool vgic_supports_direct_msis(struct kvm *kvm)
+{
+	return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
 					    gpa_t addr, unsigned int len)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 31b70326b966..e67ccb6a6250 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -240,4 +240,6 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
 			 u32 devid, u32 eventid, struct vgic_irq **irq);
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
 
+bool vgic_supports_direct_msis(struct kvm *kvm);
+
 #endif
-- 
2.14.1

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

* [PATCH v4 07/26] KVM: arm/arm64: GICv4: Add property field and per-VM predicate
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Add a new has_gicv4 field in the global VGIC state that indicates
whether the HW is GICv4 capable, as a per-VM predicate indicating
if there is a possibility for a VM to support direct injection
(the above being true and the VM having an ITS).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_vgic.h           | 3 +++
 virt/kvm/arm/vgic/vgic-mmio-v3.c | 5 +++++
 virt/kvm/arm/vgic/vgic.h         | 2 ++
 3 files changed, 10 insertions(+)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 53f631bdec75..ba9fb450aa1b 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -73,6 +73,9 @@ struct vgic_global {
 	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
 	bool			can_emulate_gicv2;
 
+	/* Hardware has GICv4? */
+	bool			has_gicv4;
+
 	/* GIC system register CPU interface */
 	struct static_key_false gicv3_cpuif;
 
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 408ef06638fc..f87fd17b2eb9 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -54,6 +54,11 @@ bool vgic_has_its(struct kvm *kvm)
 	return dist->has_its;
 }
 
+bool vgic_supports_direct_msis(struct kvm *kvm)
+{
+	return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
+}
+
 static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
 					    gpa_t addr, unsigned int len)
 {
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index 31b70326b966..e67ccb6a6250 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -240,4 +240,6 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
 			 u32 devid, u32 eventid, struct vgic_irq **irq);
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
 
+bool vgic_supports_direct_msis(struct kvm *kvm);
+
 #endif
-- 
2.14.1

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

* [PATCH v4 08/26] KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

In order to control the GICv4 view of virtual CPUs, we rely
on an irqdomain allocated for that purpose. Let's add a couple
of helpers to that effect.

At the same time, the vgic data structures gain new fields to
track all this... erm... wonderful stuff.

The way we hook into the vgic init is slightly convoluted. We
need the vgic to be initialized (in order to guarantee that
the number of vcpus is now fixed), and we must have a vITS
(otherwise this is all very pointless). So we end-up calling
the init from both vgic_init and vgic_its_create.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/Makefile         |  1 +
 arch/arm64/kvm/Makefile       |  1 +
 include/kvm/arm_vgic.h        | 19 ++++++++++
 virt/kvm/arm/vgic/vgic-init.c |  9 +++++
 virt/kvm/arm/vgic/vgic-its.c  |  8 +++++
 virt/kvm/arm/vgic/vgic-v4.c   | 83 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  2 ++
 7 files changed, 123 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v4.c

diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index d9beee652d36..0a1dd2cdb928 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -31,6 +31,7 @@ obj-y += $(KVM)/arm/vgic/vgic-init.o
 obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
 obj-y += $(KVM)/arm/vgic/vgic-v2.o
 obj-y += $(KVM)/arm/vgic/vgic-v3.o
+obj-y += $(KVM)/arm/vgic/vgic-v4.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 5d9810086c25..c30fd388ef80 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -26,6 +26,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v4.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index ba9fb450aa1b..7eeb6c2a2f9c 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -26,6 +26,8 @@
 #include <linux/list.h>
 #include <linux/jump_label.h>
 
+#include <linux/irqchip/arm-gic-v4.h>
+
 #define VGIC_V3_MAX_CPUS	255
 #define VGIC_V2_MAX_CPUS	8
 #define VGIC_NR_IRQS_LEGACY     256
@@ -236,6 +238,15 @@ struct vgic_dist {
 
 	/* used by vgic-debug */
 	struct vgic_state_iter *iter;
+
+	/*
+	 * GICv4 ITS per-VM data, containing the IRQ domain, the VPE
+	 * array, the property table pointer as well as allocation
+	 * data. This essentially ties the Linux IRQ core and ITS
+	 * together, and avoids leaking KVM's data structures anywhere
+	 * else.
+	 */
+	struct its_vm		its_vm;
 };
 
 struct vgic_v2_cpu_if {
@@ -254,6 +265,14 @@ struct vgic_v3_cpu_if {
 	u32		vgic_ap0r[4];
 	u32		vgic_ap1r[4];
 	u64		vgic_lr[VGIC_V3_MAX_LRS];
+
+	/*
+	 * GICv4 ITS per-VPE data, containing the doorbell IRQ, the
+	 * pending table pointer, the its_vm pointer and a few other
+	 * HW specific things. As for the its_vm structure, this is
+	 * linking the Linux IRQ subsystem and the ITS together.
+	 */
+	struct its_vpe	its_vpe;
 };
 
 struct vgic_cpu {
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 5801261f3add..c2749387615b 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -285,6 +285,12 @@ int vgic_init(struct kvm *kvm)
 	if (ret)
 		goto out;
 
+	if (vgic_has_its(kvm) && vgic_supports_direct_msis(kvm)) {
+		ret = vgic_v4_init(kvm);
+		if (ret)
+			goto out;
+	}
+
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		kvm_vgic_vcpu_enable(vcpu);
 
@@ -320,6 +326,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
 
 	kfree(dist->spis);
 	dist->nr_spis = 0;
+
+	if (vgic_supports_direct_msis(kvm))
+		vgic_v4_teardown(kvm);
 }
 
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 8ee03f1e89fc..89768d2b6a91 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1603,6 +1603,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 	if (!its)
 		return -ENOMEM;
 
+	if (vgic_initialized(dev->kvm)) {
+		int ret = vgic_v4_init(dev->kvm);
+		if (ret) {
+			kfree(its);
+			return ret;
+		}
+	}
+	
 	mutex_init(&its->its_lock);
 	mutex_init(&its->cmd_lock);
 
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
new file mode 100644
index 000000000000..c794f0cef09e
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/**
+ * vgic_v4_init - Initialize the GICv4 data structures
+ * @kvm:	Pointer to the VM being initialized
+ *
+ * We may be called each time a vITS is created, or when the
+ * vgic is initialized. This relies on kvm->lock to be
+ * held. In both cases, the number of vcpus should now be
+ * fixed.
+ */
+int vgic_v4_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int i, nr_vcpus, ret;
+
+	if (dist->its_vm.vpes)
+		return 0;
+
+	nr_vcpus = atomic_read(&kvm->online_vcpus);
+
+	dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
+				    GFP_KERNEL);
+	if (!dist->its_vm.vpes)
+		return -ENOMEM;
+
+	dist->its_vm.nr_vpes = nr_vcpus;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		dist->its_vm.vpes[i] = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+
+	ret = its_alloc_vcpu_irqs(&dist->its_vm);
+	if (ret < 0) {
+		kvm_err("VPE IRQ allocation failure\n");
+		kfree(dist->its_vm.vpes);
+		dist->its_vm.nr_vpes = 0;
+		dist->its_vm.vpes = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * vgic_v4_teardown - Free the GICv4 data structures
+ * @kvm:	Pointer to the VM being destroyed
+ *
+ * Relies on kvm->lock to be held.
+ */
+void vgic_v4_teardown(struct kvm *kvm)
+{
+	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
+
+	if (!its_vm->vpes)
+		return;
+
+	its_free_vcpu_irqs(its_vm);
+	kfree(its_vm->vpes);
+	its_vm->nr_vpes = 0;
+	its_vm->vpes = NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e67ccb6a6250..c4105f613f57 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -241,5 +241,7 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
 
 bool vgic_supports_direct_msis(struct kvm *kvm);
+int vgic_v4_init(struct kvm *kvm);
+void vgic_v4_teardown(struct kvm *kvm);
 
 #endif
-- 
2.14.1

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

* [PATCH v4 08/26] KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

In order to control the GICv4 view of virtual CPUs, we rely
on an irqdomain allocated for that purpose. Let's add a couple
of helpers to that effect.

At the same time, the vgic data structures gain new fields to
track all this... erm... wonderful stuff.

The way we hook into the vgic init is slightly convoluted. We
need the vgic to be initialized (in order to guarantee that
the number of vcpus is now fixed), and we must have a vITS
(otherwise this is all very pointless). So we end-up calling
the init from both vgic_init and vgic_its_create.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/Makefile         |  1 +
 arch/arm64/kvm/Makefile       |  1 +
 include/kvm/arm_vgic.h        | 19 ++++++++++
 virt/kvm/arm/vgic/vgic-init.c |  9 +++++
 virt/kvm/arm/vgic/vgic-its.c  |  8 +++++
 virt/kvm/arm/vgic/vgic-v4.c   | 83 +++++++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.h      |  2 ++
 7 files changed, 123 insertions(+)
 create mode 100644 virt/kvm/arm/vgic/vgic-v4.c

diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
index d9beee652d36..0a1dd2cdb928 100644
--- a/arch/arm/kvm/Makefile
+++ b/arch/arm/kvm/Makefile
@@ -31,6 +31,7 @@ obj-y += $(KVM)/arm/vgic/vgic-init.o
 obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
 obj-y += $(KVM)/arm/vgic/vgic-v2.o
 obj-y += $(KVM)/arm/vgic/vgic-v3.o
+obj-y += $(KVM)/arm/vgic/vgic-v4.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
 obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 5d9810086c25..c30fd388ef80 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -26,6 +26,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
+kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v4.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
 kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index ba9fb450aa1b..7eeb6c2a2f9c 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -26,6 +26,8 @@
 #include <linux/list.h>
 #include <linux/jump_label.h>
 
+#include <linux/irqchip/arm-gic-v4.h>
+
 #define VGIC_V3_MAX_CPUS	255
 #define VGIC_V2_MAX_CPUS	8
 #define VGIC_NR_IRQS_LEGACY     256
@@ -236,6 +238,15 @@ struct vgic_dist {
 
 	/* used by vgic-debug */
 	struct vgic_state_iter *iter;
+
+	/*
+	 * GICv4 ITS per-VM data, containing the IRQ domain, the VPE
+	 * array, the property table pointer as well as allocation
+	 * data. This essentially ties the Linux IRQ core and ITS
+	 * together, and avoids leaking KVM's data structures anywhere
+	 * else.
+	 */
+	struct its_vm		its_vm;
 };
 
 struct vgic_v2_cpu_if {
@@ -254,6 +265,14 @@ struct vgic_v3_cpu_if {
 	u32		vgic_ap0r[4];
 	u32		vgic_ap1r[4];
 	u64		vgic_lr[VGIC_V3_MAX_LRS];
+
+	/*
+	 * GICv4 ITS per-VPE data, containing the doorbell IRQ, the
+	 * pending table pointer, the its_vm pointer and a few other
+	 * HW specific things. As for the its_vm structure, this is
+	 * linking the Linux IRQ subsystem and the ITS together.
+	 */
+	struct its_vpe	its_vpe;
 };
 
 struct vgic_cpu {
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index 5801261f3add..c2749387615b 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -285,6 +285,12 @@ int vgic_init(struct kvm *kvm)
 	if (ret)
 		goto out;
 
+	if (vgic_has_its(kvm) && vgic_supports_direct_msis(kvm)) {
+		ret = vgic_v4_init(kvm);
+		if (ret)
+			goto out;
+	}
+
 	kvm_for_each_vcpu(i, vcpu, kvm)
 		kvm_vgic_vcpu_enable(vcpu);
 
@@ -320,6 +326,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
 
 	kfree(dist->spis);
 	dist->nr_spis = 0;
+
+	if (vgic_supports_direct_msis(kvm))
+		vgic_v4_teardown(kvm);
 }
 
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 8ee03f1e89fc..89768d2b6a91 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1603,6 +1603,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
 	if (!its)
 		return -ENOMEM;
 
+	if (vgic_initialized(dev->kvm)) {
+		int ret = vgic_v4_init(dev->kvm);
+		if (ret) {
+			kfree(its);
+			return ret;
+		}
+	}
+	
 	mutex_init(&its->its_lock);
 	mutex_init(&its->cmd_lock);
 
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
new file mode 100644
index 000000000000..c794f0cef09e
--- /dev/null
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2017 ARM Ltd.
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/interrupt.h>
+#include <linux/irqdomain.h>
+#include <linux/kvm_host.h>
+
+#include "vgic.h"
+
+/**
+ * vgic_v4_init - Initialize the GICv4 data structures
+ * @kvm:	Pointer to the VM being initialized
+ *
+ * We may be called each time a vITS is created, or when the
+ * vgic is initialized. This relies on kvm->lock to be
+ * held. In both cases, the number of vcpus should now be
+ * fixed.
+ */
+int vgic_v4_init(struct kvm *kvm)
+{
+	struct vgic_dist *dist = &kvm->arch.vgic;
+	struct kvm_vcpu *vcpu;
+	int i, nr_vcpus, ret;
+
+	if (dist->its_vm.vpes)
+		return 0;
+
+	nr_vcpus = atomic_read(&kvm->online_vcpus);
+
+	dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
+				    GFP_KERNEL);
+	if (!dist->its_vm.vpes)
+		return -ENOMEM;
+
+	dist->its_vm.nr_vpes = nr_vcpus;
+
+	kvm_for_each_vcpu(i, vcpu, kvm)
+		dist->its_vm.vpes[i] = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+
+	ret = its_alloc_vcpu_irqs(&dist->its_vm);
+	if (ret < 0) {
+		kvm_err("VPE IRQ allocation failure\n");
+		kfree(dist->its_vm.vpes);
+		dist->its_vm.nr_vpes = 0;
+		dist->its_vm.vpes = NULL;
+		return ret;
+	}
+
+	return ret;
+}
+
+/**
+ * vgic_v4_teardown - Free the GICv4 data structures
+ * @kvm:	Pointer to the VM being destroyed
+ *
+ * Relies on kvm->lock to be held.
+ */
+void vgic_v4_teardown(struct kvm *kvm)
+{
+	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
+
+	if (!its_vm->vpes)
+		return;
+
+	its_free_vcpu_irqs(its_vm);
+	kfree(its_vm->vpes);
+	its_vm->nr_vpes = 0;
+	its_vm->vpes = NULL;
+}
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index e67ccb6a6250..c4105f613f57 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -241,5 +241,7 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
 
 bool vgic_supports_direct_msis(struct kvm *kvm);
+int vgic_v4_init(struct kvm *kvm);
+void vgic_v4_teardown(struct kvm *kvm);
 
 #endif
-- 
2.14.1

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

* [PATCH v4 09/26] KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

Let's use the irq bypass mechanism introduced for platform device
interrupts to intercept the virtual PCIe endpoint configuration
and establish our LPI->VLPI mapping.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_vgic.h      |   8 ++++
 virt/kvm/arm/arm.c          |   6 ++-
 virt/kvm/arm/vgic/vgic-v4.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 7eeb6c2a2f9c..2f750c770bf2 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -373,4 +373,12 @@ int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
 
 int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner);
 
+struct kvm_kernel_irq_routing_entry;
+
+int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq,
+			       struct kvm_kernel_irq_routing_entry *irq_entry);
+
+int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
+				 struct kvm_kernel_irq_routing_entry *irq_entry);
+
 #endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 5d5218ecd547..8388c1cc23f6 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -1462,7 +1462,8 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 
-	return 0;
+	return kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
+					  &irqfd->irq_entry);
 }
 void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
 				      struct irq_bypass_producer *prod)
@@ -1470,7 +1471,8 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 
-	return;
+	kvm_vgic_v4_unset_forwarding(irqfd->kvm, prod->irq,
+				     &irqfd->irq_entry);
 }
 
 void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons)
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index c794f0cef09e..ba1dd3162eba 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -81,3 +81,107 @@ void vgic_v4_teardown(struct kvm *kvm)
 	its_vm->nr_vpes = 0;
 	its_vm->vpes = NULL;
 }
+
+static struct vgic_its *vgic_get_its(struct kvm *kvm,
+				     struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+	struct kvm_msi msi  = (struct kvm_msi) {
+		.address_lo	= irq_entry->msi.address_lo,
+		.address_hi	= irq_entry->msi.address_hi,
+		.data		= irq_entry->msi.data,
+		.flags		= irq_entry->msi.flags,
+		.devid		= irq_entry->msi.devid,
+	};
+
+	/*
+	 * Get a reference on the LPI. If NULL, this is not a valid
+	 * translation for any of our vITSs.
+	 */
+	return vgic_msi_to_its(kvm, &msi);
+}
+
+int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
+			       struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+	struct vgic_its *its;
+	struct vgic_irq *irq;
+	struct its_vlpi_map map;
+	int ret;
+
+	if (!vgic_supports_direct_msis(kvm))
+		return 0;
+
+	/*
+	 * Get the ITS, and escape early on error (not a valid
+	 * doorbell for any of our vITSs).
+	 */
+	its = vgic_get_its(kvm, irq_entry);
+	if (IS_ERR(its))
+		return 0;
+
+	mutex_lock(&its->its_lock);
+
+	/* Perform then actual DevID/EventID -> LPI translation. */
+	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
+				   irq_entry->msi.data, &irq);
+	if (ret)
+		goto out;
+
+	/*
+	 * Emit the mapping request. If it fails, the ITS probably
+	 * isn't v4 compatible, so let's silently bail out. Holding
+	 * the ITS lock should ensure that nothing can modify the
+	 * target vcpu.
+	 */
+	map = (struct its_vlpi_map) {
+		.vm		= &kvm->arch.vgic.its_vm,
+		.vpe		= &irq->target_vcpu->arch.vgic_cpu.vgic_v3.its_vpe,
+		.vintid		= irq->intid,
+		.db_enabled	= true,
+	};
+
+	ret = its_map_vlpi(virq, &map);
+	if (ret)
+		goto out;
+
+	irq->hw		= true;
+	irq->host_irq	= virq;
+
+out:
+	mutex_unlock(&its->its_lock);
+	return ret;
+}
+
+int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq,
+				 struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+	struct vgic_its *its;
+	struct vgic_irq *irq;
+	int ret;
+
+	if (!vgic_supports_direct_msis(kvm))
+		return 0;
+
+	/*
+	 * Get the ITS, and escape early on error (not a valid
+	 * doorbell for any of our vITSs).
+	 */
+	its = vgic_get_its(kvm, irq_entry);
+	if (IS_ERR(its))
+		return 0;
+
+	mutex_lock(&its->its_lock);
+
+	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
+				   irq_entry->msi.data, &irq);
+	if (ret)
+		goto out;
+
+	WARN_ON(!(irq->hw && irq->host_irq == virq));
+	irq->hw = false;
+	ret = its_unmap_vlpi(virq);
+
+out:
+	mutex_unlock(&its->its_lock);
+	return ret;
+}
-- 
2.14.1

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

* [PATCH v4 09/26] KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Let's use the irq bypass mechanism introduced for platform device
interrupts to intercept the virtual PCIe endpoint configuration
and establish our LPI->VLPI mapping.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_vgic.h      |   8 ++++
 virt/kvm/arm/arm.c          |   6 ++-
 virt/kvm/arm/vgic/vgic-v4.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 7eeb6c2a2f9c..2f750c770bf2 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -373,4 +373,12 @@ int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
 
 int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner);
 
+struct kvm_kernel_irq_routing_entry;
+
+int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq,
+			       struct kvm_kernel_irq_routing_entry *irq_entry);
+
+int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
+				 struct kvm_kernel_irq_routing_entry *irq_entry);
+
 #endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 5d5218ecd547..8388c1cc23f6 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -1462,7 +1462,8 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 
-	return 0;
+	return kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
+					  &irqfd->irq_entry);
 }
 void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
 				      struct irq_bypass_producer *prod)
@@ -1470,7 +1471,8 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
 	struct kvm_kernel_irqfd *irqfd =
 		container_of(cons, struct kvm_kernel_irqfd, consumer);
 
-	return;
+	kvm_vgic_v4_unset_forwarding(irqfd->kvm, prod->irq,
+				     &irqfd->irq_entry);
 }
 
 void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons)
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index c794f0cef09e..ba1dd3162eba 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -81,3 +81,107 @@ void vgic_v4_teardown(struct kvm *kvm)
 	its_vm->nr_vpes = 0;
 	its_vm->vpes = NULL;
 }
+
+static struct vgic_its *vgic_get_its(struct kvm *kvm,
+				     struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+	struct kvm_msi msi  = (struct kvm_msi) {
+		.address_lo	= irq_entry->msi.address_lo,
+		.address_hi	= irq_entry->msi.address_hi,
+		.data		= irq_entry->msi.data,
+		.flags		= irq_entry->msi.flags,
+		.devid		= irq_entry->msi.devid,
+	};
+
+	/*
+	 * Get a reference on the LPI. If NULL, this is not a valid
+	 * translation for any of our vITSs.
+	 */
+	return vgic_msi_to_its(kvm, &msi);
+}
+
+int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
+			       struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+	struct vgic_its *its;
+	struct vgic_irq *irq;
+	struct its_vlpi_map map;
+	int ret;
+
+	if (!vgic_supports_direct_msis(kvm))
+		return 0;
+
+	/*
+	 * Get the ITS, and escape early on error (not a valid
+	 * doorbell for any of our vITSs).
+	 */
+	its = vgic_get_its(kvm, irq_entry);
+	if (IS_ERR(its))
+		return 0;
+
+	mutex_lock(&its->its_lock);
+
+	/* Perform then actual DevID/EventID -> LPI translation. */
+	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
+				   irq_entry->msi.data, &irq);
+	if (ret)
+		goto out;
+
+	/*
+	 * Emit the mapping request. If it fails, the ITS probably
+	 * isn't v4 compatible, so let's silently bail out. Holding
+	 * the ITS lock should ensure that nothing can modify the
+	 * target vcpu.
+	 */
+	map = (struct its_vlpi_map) {
+		.vm		= &kvm->arch.vgic.its_vm,
+		.vpe		= &irq->target_vcpu->arch.vgic_cpu.vgic_v3.its_vpe,
+		.vintid		= irq->intid,
+		.db_enabled	= true,
+	};
+
+	ret = its_map_vlpi(virq, &map);
+	if (ret)
+		goto out;
+
+	irq->hw		= true;
+	irq->host_irq	= virq;
+
+out:
+	mutex_unlock(&its->its_lock);
+	return ret;
+}
+
+int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq,
+				 struct kvm_kernel_irq_routing_entry *irq_entry)
+{
+	struct vgic_its *its;
+	struct vgic_irq *irq;
+	int ret;
+
+	if (!vgic_supports_direct_msis(kvm))
+		return 0;
+
+	/*
+	 * Get the ITS, and escape early on error (not a valid
+	 * doorbell for any of our vITSs).
+	 */
+	its = vgic_get_its(kvm, irq_entry);
+	if (IS_ERR(its))
+		return 0;
+
+	mutex_lock(&its->its_lock);
+
+	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
+				   irq_entry->msi.data, &irq);
+	if (ret)
+		goto out;
+
+	WARN_ON(!(irq->hw && irq->host_irq == virq));
+	irq->hw = false;
+	ret = its_unmap_vlpi(virq);
+
+out:
+	mutex_unlock(&its->its_lock);
+	return ret;
+}
-- 
2.14.1

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

* [PATCH v4 10/26] KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

If the guest issues an INT command targetting a VLPI, let's
call into the irq_set_irqchip_state() helper to make it pending
on the physical side.

This works just as well if userspace decides to inject an interrupt
using the normal userspace API...

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 89768d2b6a91..b2a678d131d0 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -578,6 +578,10 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 	if (err)
 		return err;
 
+	if (irq->hw)
+		return irq_set_irqchip_state(irq->host_irq,
+					     IRQCHIP_STATE_PENDING, true);
+
 	spin_lock(&irq->irq_lock);
 	irq->pending_latch = true;
 	vgic_queue_irq_unlock(kvm, irq);
-- 
2.14.1

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

* [PATCH v4 10/26] KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

If the guest issues an INT command targetting a VLPI, let's
call into the irq_set_irqchip_state() helper to make it pending
on the physical side.

This works just as well if userspace decides to inject an interrupt
using the normal userspace API...

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 89768d2b6a91..b2a678d131d0 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -578,6 +578,10 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
 	if (err)
 		return err;
 
+	if (irq->hw)
+		return irq_set_irqchip_state(irq->host_irq,
+					     IRQCHIP_STATE_PENDING, true);
+
 	spin_lock(&irq->irq_lock);
 	irq->pending_latch = true;
 	vgic_queue_irq_unlock(kvm, irq);
-- 
2.14.1

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

* [PATCH v4 11/26] KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

When freeing an LPI (on a DISCARD command, for example), we need
to unmap the VLPI down to the physical ITS level.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b2a678d131d0..c9b1c0967426 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -628,8 +628,12 @@ static void its_free_ite(struct kvm *kvm, struct its_ite *ite)
 	list_del(&ite->ite_list);
 
 	/* This put matches the get in vgic_add_lpi. */
-	if (ite->irq)
+	if (ite->irq) {
+		if (ite->irq->hw)
+			WARN_ON(its_unmap_vlpi(ite->irq->host_irq));
+
 		vgic_put_irq(kvm, ite->irq);
+	}
 
 	kfree(ite);
 }
-- 
2.14.1

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

* [PATCH v4 11/26] KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

When freeing an LPI (on a DISCARD command, for example), we need
to unmap the VLPI down to the physical ITS level.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index b2a678d131d0..c9b1c0967426 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -628,8 +628,12 @@ static void its_free_ite(struct kvm *kvm, struct its_ite *ite)
 	list_del(&ite->ite_list);
 
 	/* This put matches the get in vgic_add_lpi. */
-	if (ite->irq)
+	if (ite->irq) {
+		if (ite->irq->hw)
+			WARN_ON(its_unmap_vlpi(ite->irq->host_irq));
+
 		vgic_put_irq(kvm, ite->irq);
+	}
 
 	kfree(ite);
 }
-- 
2.14.1

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

* [PATCH v4 12/26] KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

When the guest issues an affinity change, we need to tell the physical
ITS that we're now targetting a new vcpu.  This is done by extracting
the current mapping, updating the target, and reapplying the mapping.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index c9b1c0967426..42ffb9084bb7 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -337,11 +337,25 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 
 static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
 {
+	int ret = 0;
+
 	spin_lock(&irq->irq_lock);
 	irq->target_vcpu = vcpu;
 	spin_unlock(&irq->irq_lock);
 
-	return 0;
+	if (irq->hw) {
+		struct its_vlpi_map map;
+
+		ret = its_get_vlpi(irq->host_irq, &map);
+		if (ret)
+			return ret;
+
+		map.vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+
+		ret = its_map_vlpi(irq->host_irq, &map);
+	}
+
+	return ret;
 }
 
 /*
-- 
2.14.1

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

* [PATCH v4 12/26] KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

When the guest issues an affinity change, we need to tell the physical
ITS that we're now targetting a new vcpu.  This is done by extracting
the current mapping, updating the target, and reapplying the mapping.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 16 +++++++++++++++-
 1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index c9b1c0967426..42ffb9084bb7 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -337,11 +337,25 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
 
 static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
 {
+	int ret = 0;
+
 	spin_lock(&irq->irq_lock);
 	irq->target_vcpu = vcpu;
 	spin_unlock(&irq->irq_lock);
 
-	return 0;
+	if (irq->hw) {
+		struct its_vlpi_map map;
+
+		ret = its_get_vlpi(irq->host_irq, &map);
+		if (ret)
+			return ret;
+
+		map.vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
+
+		ret = its_map_vlpi(irq->host_irq, &map);
+	}
+
+	return ret;
 }
 
 /*
-- 
2.14.1

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

* [PATCH v4 13/26] KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

Handling CLEAR is pretty easy. Just ask the ITS driver to clear
the corresponding pending bit (which will turn into a CLEAR
command on the physical side).

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 42ffb9084bb7..5778b50911e8 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1070,6 +1070,10 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
 
 	ite->irq->pending_latch = false;
 
+	if (ite->irq->hw)
+		return irq_set_irqchip_state(ite->irq->host_irq,
+					     IRQCHIP_STATE_PENDING, false);
+
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 13/26] KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Handling CLEAR is pretty easy. Just ask the ITS driver to clear
the corresponding pending bit (which will turn into a CLEAR
command on the physical side).

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 42ffb9084bb7..5778b50911e8 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1070,6 +1070,10 @@ static int vgic_its_cmd_handle_clear(struct kvm *kvm, struct vgic_its *its,
 
 	ite->irq->pending_latch = false;
 
+	if (ite->irq->hw)
+		return irq_set_irqchip_state(ite->irq->host_irq,
+					     IRQCHIP_STATE_PENDING, false);
+
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 14/26] KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

The current implementation of MOVALL doesn't allow us to call
into the core ITS code as we hold a number of spinlocks.

Let's try a method used in other parts of the code, were we copy
the intids of the candicate interrupts, and then do whatever
we need to do with them outside of the critical section.

This allows us to move the interrupts one by one, at the expense
of a bit of CPU time. Who cares? MOVALL is such a stupid command
anyway...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 5778b50911e8..0b7e648e7a0c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1148,11 +1148,12 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
 static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
 				      u64 *its_cmd)
 {
-	struct vgic_dist *dist = &kvm->arch.vgic;
 	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
 	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
 	struct kvm_vcpu *vcpu1, *vcpu2;
 	struct vgic_irq *irq;
+	u32 *intids;
+	int irq_count, i;
 
 	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
 	    target2_addr >= atomic_read(&kvm->online_vcpus))
@@ -1164,19 +1165,19 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
 	vcpu1 = kvm_get_vcpu(kvm, target1_addr);
 	vcpu2 = kvm_get_vcpu(kvm, target2_addr);
 
-	spin_lock(&dist->lpi_list_lock);
+	irq_count = vgic_copy_lpi_list(vcpu1, &intids);
+	if (irq_count < 0)
+		return irq_count;
 
-	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
-		spin_lock(&irq->irq_lock);
+	for (i = 0; i < irq_count; i++) {
+		irq = vgic_get_irq(kvm, NULL, intids[i]);
 
-		if (irq->target_vcpu == vcpu1)
-			irq->target_vcpu = vcpu2;
+		update_affinity(irq, vcpu2);
 
-		spin_unlock(&irq->irq_lock);
+		vgic_put_irq(kvm, irq);
 	}
 
-	spin_unlock(&dist->lpi_list_lock);
-
+	kfree(intids);
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 14/26] KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The current implementation of MOVALL doesn't allow us to call
into the core ITS code as we hold a number of spinlocks.

Let's try a method used in other parts of the code, were we copy
the intids of the candicate interrupts, and then do whatever
we need to do with them outside of the critical section.

This allows us to move the interrupts one by one, at the expense
of a bit of CPU time. Who cares? MOVALL is such a stupid command
anyway...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 19 ++++++++++---------
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 5778b50911e8..0b7e648e7a0c 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1148,11 +1148,12 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
 static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
 				      u64 *its_cmd)
 {
-	struct vgic_dist *dist = &kvm->arch.vgic;
 	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
 	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
 	struct kvm_vcpu *vcpu1, *vcpu2;
 	struct vgic_irq *irq;
+	u32 *intids;
+	int irq_count, i;
 
 	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
 	    target2_addr >= atomic_read(&kvm->online_vcpus))
@@ -1164,19 +1165,19 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
 	vcpu1 = kvm_get_vcpu(kvm, target1_addr);
 	vcpu2 = kvm_get_vcpu(kvm, target2_addr);
 
-	spin_lock(&dist->lpi_list_lock);
+	irq_count = vgic_copy_lpi_list(vcpu1, &intids);
+	if (irq_count < 0)
+		return irq_count;
 
-	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
-		spin_lock(&irq->irq_lock);
+	for (i = 0; i < irq_count; i++) {
+		irq = vgic_get_irq(kvm, NULL, intids[i]);
 
-		if (irq->target_vcpu == vcpu1)
-			irq->target_vcpu = vcpu2;
+		update_affinity(irq, vcpu2);
 
-		spin_unlock(&irq->irq_lock);
+		vgic_put_irq(kvm, irq);
 	}
 
-	spin_unlock(&dist->lpi_list_lock);
-
+	kfree(intids);
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 15/26] KVM: arm/arm64: GICv4: Propagate property updates to VLPIs
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

Upon updating a property, we propagate it all the way to the physical
ITS, and ask for an INV command to be executed there.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 0b7e648e7a0c..2e77c7c83942 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -296,6 +296,9 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 		spin_unlock(&irq->irq_lock);
 	}
 
+	if (irq->hw)
+		return its_prop_update_vlpi(irq->host_irq, prop, true);
+
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 15/26] KVM: arm/arm64: GICv4: Propagate property updates to VLPIs
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Upon updating a property, we propagate it all the way to the physical
ITS, and ask for an INV command to be executed there.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 0b7e648e7a0c..2e77c7c83942 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -296,6 +296,9 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 		spin_unlock(&irq->irq_lock);
 	}
 
+	if (irq->hw)
+		return its_prop_update_vlpi(irq->host_irq, prop, true);
+
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 16/26] KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

Since when updating the properties one LPI at a time, there is no
need to perform an INV each time we read one. Instead, we rely
on the final VINVALL that gets sent to the ITS to do the work.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2e77c7c83942..eb72eb027060 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -38,7 +38,7 @@ static int vgic_its_save_tables_v0(struct vgic_its *its);
 static int vgic_its_restore_tables_v0(struct vgic_its *its);
 static int vgic_its_commit_v0(struct vgic_its *its);
 static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu);
+			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
 
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
@@ -106,7 +106,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
 	 * However we only have those structs for mapped IRQs, so we read in
 	 * the respective config data from memory here upon mapping the LPI.
 	 */
-	ret = update_lpi_config(kvm, irq, NULL);
+	ret = update_lpi_config(kvm, irq, NULL, false);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -273,7 +273,7 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
  * VCPU. Unconditionally applies if filter_vcpu is NULL.
  */
 static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu)
+			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
 {
 	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
 	u8 prop;
@@ -297,7 +297,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 	}
 
 	if (irq->hw)
-		return its_prop_update_vlpi(irq->host_irq, prop, true);
+		return its_prop_update_vlpi(irq->host_irq, prop, needs_inv);
 
 	return 0;
 }
@@ -1096,7 +1096,7 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
 	if (!ite)
 		return E_ITS_INV_UNMAPPED_INTERRUPT;
 
-	return update_lpi_config(kvm, ite->irq, NULL);
+	return update_lpi_config(kvm, ite->irq, NULL, true);
 }
 
 /*
@@ -1131,12 +1131,15 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
 		irq = vgic_get_irq(kvm, NULL, intids[i]);
 		if (!irq)
 			continue;
-		update_lpi_config(kvm, irq, vcpu);
+		update_lpi_config(kvm, irq, vcpu, false);
 		vgic_put_irq(kvm, irq);
 	}
 
 	kfree(intids);
 
+	if (vcpu->arch.vgic_cpu.vgic_v3.its_vpe.its_vm)
+		its_invall_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe);
+
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 16/26] KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

Since when updating the properties one LPI at a time, there is no
need to perform an INV each time we read one. Instead, we rely
on the final VINVALL that gets sent to the ITS to do the work.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index 2e77c7c83942..eb72eb027060 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -38,7 +38,7 @@ static int vgic_its_save_tables_v0(struct vgic_its *its);
 static int vgic_its_restore_tables_v0(struct vgic_its *its);
 static int vgic_its_commit_v0(struct vgic_its *its);
 static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu);
+			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
 
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
@@ -106,7 +106,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
 	 * However we only have those structs for mapped IRQs, so we read in
 	 * the respective config data from memory here upon mapping the LPI.
 	 */
-	ret = update_lpi_config(kvm, irq, NULL);
+	ret = update_lpi_config(kvm, irq, NULL, false);
 	if (ret)
 		return ERR_PTR(ret);
 
@@ -273,7 +273,7 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
  * VCPU. Unconditionally applies if filter_vcpu is NULL.
  */
 static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu)
+			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
 {
 	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
 	u8 prop;
@@ -297,7 +297,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 	}
 
 	if (irq->hw)
-		return its_prop_update_vlpi(irq->host_irq, prop, true);
+		return its_prop_update_vlpi(irq->host_irq, prop, needs_inv);
 
 	return 0;
 }
@@ -1096,7 +1096,7 @@ static int vgic_its_cmd_handle_inv(struct kvm *kvm, struct vgic_its *its,
 	if (!ite)
 		return E_ITS_INV_UNMAPPED_INTERRUPT;
 
-	return update_lpi_config(kvm, ite->irq, NULL);
+	return update_lpi_config(kvm, ite->irq, NULL, true);
 }
 
 /*
@@ -1131,12 +1131,15 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
 		irq = vgic_get_irq(kvm, NULL, intids[i]);
 		if (!irq)
 			continue;
-		update_lpi_config(kvm, irq, vcpu);
+		update_lpi_config(kvm, irq, vcpu, false);
 		vgic_put_irq(kvm, irq);
 	}
 
 	kfree(intids);
 
+	if (vcpu->arch.vgic_cpu.vgic_v3.its_vpe.its_vm)
+		its_invall_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe);
+
 	return 0;
 }
 
-- 
2.14.1

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

* [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

When the VLPI gets mapped, it must inherit the configuration of
the LPI configured at the vITS level. For that purpose, let's make
update_lpi_config globally available and call it just after
having performed the VLPI map operation.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 6 ++----
 virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
 virt/kvm/arm/vgic/vgic.h     | 2 ++
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index eb72eb027060..f434748439ee 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -37,8 +37,6 @@
 static int vgic_its_save_tables_v0(struct vgic_its *its);
 static int vgic_its_restore_tables_v0(struct vgic_its *its);
 static int vgic_its_commit_v0(struct vgic_its *its);
-static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
 
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
@@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
  * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
  * VCPU. Unconditionally applies if filter_vcpu is NULL.
  */
-static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
+int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
 {
 	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
 	u8 prop;
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index ba1dd3162eba..b79a0450bb1c 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
 	irq->hw		= true;
 	irq->host_irq	= virq;
 
+	/* Force the property update and invalidate */
+	update_lpi_config(kvm, irq, NULL, true);
 out:
 	mutex_unlock(&its->its_lock);
 	return ret;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c4105f613f57..1bd2e28ac097 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -239,6 +239,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
 int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
 			 u32 devid, u32 eventid, struct vgic_irq **irq);
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
+int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+		      struct kvm_vcpu *filter_vcpu, bool needs_inv);
 
 bool vgic_supports_direct_msis(struct kvm *kvm);
 int vgic_v4_init(struct kvm *kvm);
-- 
2.14.1

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

* [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

When the VLPI gets mapped, it must inherit the configuration of
the LPI configured at the vITS level. For that purpose, let's make
update_lpi_config globally available and call it just after
having performed the VLPI map operation.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 6 ++----
 virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
 virt/kvm/arm/vgic/vgic.h     | 2 ++
 3 files changed, 6 insertions(+), 4 deletions(-)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index eb72eb027060..f434748439ee 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -37,8 +37,6 @@
 static int vgic_its_save_tables_v0(struct vgic_its *its);
 static int vgic_its_restore_tables_v0(struct vgic_its *its);
 static int vgic_its_commit_v0(struct vgic_its *its);
-static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
 
 /*
  * Creates a new (reference to a) struct vgic_irq for a given LPI.
@@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
  * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
  * VCPU. Unconditionally applies if filter_vcpu is NULL.
  */
-static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
-			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
+int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
 {
 	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
 	u8 prop;
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index ba1dd3162eba..b79a0450bb1c 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
 	irq->hw		= true;
 	irq->host_irq	= virq;
 
+	/* Force the property update and invalidate */
+	update_lpi_config(kvm, irq, NULL, true);
 out:
 	mutex_unlock(&its->its_lock);
 	return ret;
diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
index c4105f613f57..1bd2e28ac097 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -239,6 +239,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
 int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
 			 u32 devid, u32 eventid, struct vgic_irq **irq);
 struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
+int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
+		      struct kvm_vcpu *filter_vcpu, bool needs_inv);
 
 bool vgic_supports_direct_msis(struct kvm *kvm);
 int vgic_v4_init(struct kvm *kvm);
-- 
2.14.1

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

* [PATCH v4 18/26] KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

When a vPE exits, the pending_last flag is set when there are
pending VLPIs stored in the pending table. Similarily, we set
this flag when a doorbell interrupt fires, as it indicates the
same condition.

Let's update kvm_vgic_vcpu_pending_irq() to account for that
flag as well, making a vcpu runnable when set.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 9d557efd1f7d..0691a2250949 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -769,6 +769,9 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 	if (!vcpu->kvm->arch.vgic.enabled)
 		return false;
 
+	if (vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last)
+		return true;
+
 	spin_lock(&vgic_cpu->ap_list_lock);
 
 	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-- 
2.14.1

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

* [PATCH v4 18/26] KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

When a vPE exits, the pending_last flag is set when there are
pending VLPIs stored in the pending table. Similarily, we set
this flag when a doorbell interrupt fires, as it indicates the
same condition.

Let's update kvm_vgic_vcpu_pending_irq() to account for that
flag as well, making a vcpu runnable when set.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 9d557efd1f7d..0691a2250949 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -769,6 +769,9 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 	if (!vcpu->kvm->arch.vgic.enabled)
 		return false;
 
+	if (vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last)
+		return true;
+
 	spin_lock(&vgic_cpu->ap_list_lock);
 
 	list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-- 
2.14.1

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

* [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

When a vPE is not running, a VLPI being made pending results in a
doorbell interrupt being delivered. Let's handle this interrupt
and update the pending_last flag that indicates that VLPIs are
pending. The corresponding vcpu is also kicked into action.

Special care is taken care of not allowing the doorbell to be
enabled at request time (this is controlled separately), and
to make the disabling on the interrupt non-lazy.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index b79a0450bb1c..2c250ee37878 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -16,11 +16,23 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kvm_host.h>
 
 #include "vgic.h"
 
+static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
+{
+	struct kvm_vcpu *vcpu = info;
+
+	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
+	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
+	kvm_vcpu_kick(vcpu);
+
+	return IRQ_HANDLED;
+}
+
 /**
  * vgic_v4_init - Initialize the GICv4 data structures
  * @kvm:	Pointer to the VM being initialized
@@ -60,6 +72,33 @@ int vgic_v4_init(struct kvm *kvm)
 		return ret;
 	}
 
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		int irq = dist->its_vm.vpes[i]->irq;
+
+		/*
+		 * Don't automatically enable the doorbell, as we're
+		 * flipping it back and forth when the vcpu gets
+		 * blocked. Also disable the lazy disabling, as the
+		 * doorbell could kick us out of the guest too
+		 * early...
+		 */
+		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		ret = request_irq(irq, vgic_v4_doorbell_handler,
+				  0, "vcpu", vcpu);
+		if (ret) {
+			kvm_err("failed to allocate vcpu IRQ%d\n", irq);
+			/*
+			 * Trick: adjust the number of vpes so we know
+			 * how many to nuke on teardown...
+			 */
+			dist->its_vm.nr_vpes = i;
+			break;
+		}
+	}
+
+	if (ret)
+		vgic_v4_teardown(kvm);
+
 	return ret;
 }
 
@@ -72,10 +111,19 @@ int vgic_v4_init(struct kvm *kvm)
 void vgic_v4_teardown(struct kvm *kvm)
 {
 	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
+	int i;
 
 	if (!its_vm->vpes)
 		return;
 
+	for (i = 0; i < its_vm->nr_vpes; i++) {
+		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
+		int irq = its_vm->vpes[i]->irq;
+
+		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		free_irq(irq, vcpu);
+	}
+
 	its_free_vcpu_irqs(its_vm);
 	kfree(its_vm->vpes);
 	its_vm->nr_vpes = 0;
-- 
2.14.1

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

* [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

When a vPE is not running, a VLPI being made pending results in a
doorbell interrupt being delivered. Let's handle this interrupt
and update the pending_last flag that indicates that VLPIs are
pending. The corresponding vcpu is also kicked into action.

Special care is taken care of not allowing the doorbell to be
enabled at request time (this is controlled separately), and
to make the disabling on the interrupt non-lazy.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index b79a0450bb1c..2c250ee37878 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -16,11 +16,23 @@
  */
 
 #include <linux/interrupt.h>
+#include <linux/irq.h>
 #include <linux/irqdomain.h>
 #include <linux/kvm_host.h>
 
 #include "vgic.h"
 
+static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
+{
+	struct kvm_vcpu *vcpu = info;
+
+	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
+	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
+	kvm_vcpu_kick(vcpu);
+
+	return IRQ_HANDLED;
+}
+
 /**
  * vgic_v4_init - Initialize the GICv4 data structures
  * @kvm:	Pointer to the VM being initialized
@@ -60,6 +72,33 @@ int vgic_v4_init(struct kvm *kvm)
 		return ret;
 	}
 
+	kvm_for_each_vcpu(i, vcpu, kvm) {
+		int irq = dist->its_vm.vpes[i]->irq;
+
+		/*
+		 * Don't automatically enable the doorbell, as we're
+		 * flipping it back and forth when the vcpu gets
+		 * blocked. Also disable the lazy disabling, as the
+		 * doorbell could kick us out of the guest too
+		 * early...
+		 */
+		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		ret = request_irq(irq, vgic_v4_doorbell_handler,
+				  0, "vcpu", vcpu);
+		if (ret) {
+			kvm_err("failed to allocate vcpu IRQ%d\n", irq);
+			/*
+			 * Trick: adjust the number of vpes so we know
+			 * how many to nuke on teardown...
+			 */
+			dist->its_vm.nr_vpes = i;
+			break;
+		}
+	}
+
+	if (ret)
+		vgic_v4_teardown(kvm);
+
 	return ret;
 }
 
@@ -72,10 +111,19 @@ int vgic_v4_init(struct kvm *kvm)
 void vgic_v4_teardown(struct kvm *kvm)
 {
 	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
+	int i;
 
 	if (!its_vm->vpes)
 		return;
 
+	for (i = 0; i < its_vm->nr_vpes; i++) {
+		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
+		int irq = its_vm->vpes[i]->irq;
+
+		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		free_irq(irq, vcpu);
+	}
+
 	its_free_vcpu_irqs(its_vm);
 	kfree(its_vm->vpes);
 	its_vm->nr_vpes = 0;
-- 
2.14.1

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

* [PATCH v4 20/26] KVM: arm/arm64: GICv4: Use the doorbell interrupt as an unblocking source
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

The doorbell interrupt is only useful if the vcpu is blocked on WFI.
In all other cases, recieving a doorbell interrupt is just a waste
of cycles.

So let's only enable the doorbell if a vcpu is getting blocked,
and disable it when it is unblocked. This is very similar to
what we're doing for the background timer.

Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_vgic.h      |  3 +++
 virt/kvm/arm/arm.c          |  2 ++
 virt/kvm/arm/vgic/vgic-v4.c | 18 ++++++++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 2f750c770bf2..8c896540a72c 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -381,4 +381,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);
+
 #endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 8388c1cc23f6..092a4ec03e57 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -316,11 +316,13 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
 {
 	kvm_timer_schedule(vcpu);
+	kvm_vgic_v4_enable_doorbell(vcpu);
 }
 
 void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
 {
 	kvm_timer_unschedule(vcpu);
+	kvm_vgic_v4_disable_doorbell(vcpu);
 }
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 2c250ee37878..5ee69aec990a 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -235,3 +235,21 @@ 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);
+	}
+}
-- 
2.14.1

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

* [PATCH v4 20/26] KVM: arm/arm64: GICv4: Use the doorbell interrupt as an unblocking source
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The doorbell interrupt is only useful if the vcpu is blocked on WFI.
In all other cases, recieving a doorbell interrupt is just a waste
of cycles.

So let's only enable the doorbell if a vcpu is getting blocked,
and disable it when it is unblocked. This is very similar to
what we're doing for the background timer.

Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/kvm/arm_vgic.h      |  3 +++
 virt/kvm/arm/arm.c          |  2 ++
 virt/kvm/arm/vgic/vgic-v4.c | 18 ++++++++++++++++++
 3 files changed, 23 insertions(+)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 2f750c770bf2..8c896540a72c 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -381,4 +381,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);
+
 #endif /* __KVM_ARM_VGIC_H */
diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
index 8388c1cc23f6..092a4ec03e57 100644
--- a/virt/kvm/arm/arm.c
+++ b/virt/kvm/arm/arm.c
@@ -316,11 +316,13 @@ int kvm_cpu_has_pending_timer(struct kvm_vcpu *vcpu)
 void kvm_arch_vcpu_blocking(struct kvm_vcpu *vcpu)
 {
 	kvm_timer_schedule(vcpu);
+	kvm_vgic_v4_enable_doorbell(vcpu);
 }
 
 void kvm_arch_vcpu_unblocking(struct kvm_vcpu *vcpu)
 {
 	kvm_timer_unschedule(vcpu);
+	kvm_vgic_v4_disable_doorbell(vcpu);
 }
 
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 2c250ee37878..5ee69aec990a 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -235,3 +235,21 @@ 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);
+	}
+}
-- 
2.14.1

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

* [PATCH v4 21/26] KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

The redistributor needs to be told which vPE is about to be run,
and tells us whether there is any pending VLPI on exit.

Let's add the scheduling calls to the vgic flush/sync functions,
allowing the VLPIs to be delivered to the guest.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 39 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c    |  4 ++++
 virt/kvm/arm/vgic/vgic.h    |  2 ++
 3 files changed, 45 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 5ee69aec990a..68a2ef6df161 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -130,6 +130,45 @@ void vgic_v4_teardown(struct kvm *kvm)
 	its_vm->vpes = NULL;
 }
 
+int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	if (!vgic_supports_direct_msis(vcpu->kvm))
+		return 0;
+
+	return its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, false);
+}
+
+int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
+	int err;
+
+	if (!vgic_supports_direct_msis(vcpu->kvm))
+		return 0;
+
+	/*
+	 * Before making the VPE resident, make sure the redistributor
+	 * corresponding to our current CPU expects us here. See the
+	 * 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()));
+	if (err)
+		return err;
+
+	err = its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, true);
+	if (err)
+		return err;
+
+	/*
+	 * 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;
+}
+
 static struct vgic_its *vgic_get_its(struct kvm *kvm,
 				     struct kvm_kernel_irq_routing_entry *irq_entry)
 {
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 0691a2250949..71ca0ff1b35a 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -709,6 +709,8 @@ 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;
@@ -721,6 +723,8 @@ void kvm_vgic_sync_hwstate(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 1bd2e28ac097..1c65750892d7 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -245,5 +245,7 @@ int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 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.14.1

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

* [PATCH v4 21/26] KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The redistributor needs to be told which vPE is about to be run,
and tells us whether there is any pending VLPI on exit.

Let's add the scheduling calls to the vgic flush/sync functions,
allowing the VLPIs to be delivered to the guest.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 39 +++++++++++++++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic.c    |  4 ++++
 virt/kvm/arm/vgic/vgic.h    |  2 ++
 3 files changed, 45 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 5ee69aec990a..68a2ef6df161 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -130,6 +130,45 @@ void vgic_v4_teardown(struct kvm *kvm)
 	its_vm->vpes = NULL;
 }
 
+int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu)
+{
+	if (!vgic_supports_direct_msis(vcpu->kvm))
+		return 0;
+
+	return its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, false);
+}
+
+int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
+{
+	int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
+	int err;
+
+	if (!vgic_supports_direct_msis(vcpu->kvm))
+		return 0;
+
+	/*
+	 * Before making the VPE resident, make sure the redistributor
+	 * corresponding to our current CPU expects us here. See the
+	 * 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()));
+	if (err)
+		return err;
+
+	err = its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, true);
+	if (err)
+		return err;
+
+	/*
+	 * 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;
+}
+
 static struct vgic_its *vgic_get_its(struct kvm *kvm,
 				     struct kvm_kernel_irq_routing_entry *irq_entry)
 {
diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
index 0691a2250949..71ca0ff1b35a 100644
--- a/virt/kvm/arm/vgic/vgic.c
+++ b/virt/kvm/arm/vgic/vgic.c
@@ -709,6 +709,8 @@ 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;
@@ -721,6 +723,8 @@ void kvm_vgic_sync_hwstate(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 1bd2e28ac097..1c65750892d7 100644
--- a/virt/kvm/arm/vgic/vgic.h
+++ b/virt/kvm/arm/vgic/vgic.h
@@ -245,5 +245,7 @@ int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
 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.14.1

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

* [PATCH v4 22/26] KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm
  Cc: Christoffer Dall, Eric Auger, Shanker Donthineni, Mark Rutland,
	Shameerali Kolothum Thodi, Andre Przywara

In order for VLPIs to be delivered to the guest, we must make
sure that the cpuif is always enabled, irrespective of the
presence of virtual interrupt in the LRs.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/hyp/vgic-v3-sr.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 91728faa13fd..f5c3d6d7019e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -258,7 +258,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
 		}
 	} else {
-		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+		if (static_branch_unlikely(&vgic_v3_cpuif_trap) ||
+		    cpu_if->its_vpe.its_vm)
 			write_gicreg(0, ICH_HCR_EL2);
 
 		cpu_if->vgic_elrsr = 0xffff;
@@ -337,9 +338,11 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 		/*
 		 * If we need to trap system registers, we must write
 		 * ICH_HCR_EL2 anyway, even if no interrupts are being
-		 * injected,
+		 * injected. Same thing if GICv4 is used, as VLPI
+		 * delivery is gated by ICH_HCR_EL2.En.
 		 */
-		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+		if (static_branch_unlikely(&vgic_v3_cpuif_trap) ||
+		    cpu_if->its_vpe.its_vm)
 			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 	}
 
-- 
2.14.1

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

* [PATCH v4 22/26] KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

In order for VLPIs to be delivered to the guest, we must make
sure that the cpuif is always enabled, irrespective of the
presence of virtual interrupt in the LRs.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/hyp/vgic-v3-sr.c | 9 ++++++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 91728faa13fd..f5c3d6d7019e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -258,7 +258,8 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
 		}
 	} else {
-		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+		if (static_branch_unlikely(&vgic_v3_cpuif_trap) ||
+		    cpu_if->its_vpe.its_vm)
 			write_gicreg(0, ICH_HCR_EL2);
 
 		cpu_if->vgic_elrsr = 0xffff;
@@ -337,9 +338,11 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 		/*
 		 * If we need to trap system registers, we must write
 		 * ICH_HCR_EL2 anyway, even if no interrupts are being
-		 * injected,
+		 * injected. Same thing if GICv4 is used, as VLPI
+		 * delivery is gated by ICH_HCR_EL2.En.
 		 */
-		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+		if (static_branch_unlikely(&vgic_v3_cpuif_trap) ||
+		    cpu_if->its_vpe.its_vm)
 			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 	}
 
-- 
2.14.1

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

* [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

The GICv4 architecture doesn't make it easy for save/restore to
work, as it doesn't give any guarantee that the pending state
is written into the pending table.

So let's not take any chance, and let's return an error if
we encounter any LPI that has the HW bit set.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f434748439ee..01aa4d9d405e 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
 	list_for_each_entry(ite, &device->itt_head, ite_list) {
 		gpa_t gpa = base + ite->event_id * ite_esz;
 
+		/*
+		 * If an LPI carries the HW bit, this means that this
+		 * interrupt is controlled by GICv4, and we do not
+		 * have direct access to that state. Let's simply fail
+		 * the save operation...
+		 */
+		if (ite->irq->hw)
+			return -EINVAL;
+
 		ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
 		if (ret)
 			return ret;
-- 
2.14.1

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

* [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

The GICv4 architecture doesn't make it easy for save/restore to
work, as it doesn't give any guarantee that the pending state
is written into the pending table.

So let's not take any chance, and let's return an error if
we encounter any LPI that has the HW bit set.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
 1 file changed, 9 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
index f434748439ee..01aa4d9d405e 100644
--- a/virt/kvm/arm/vgic/vgic-its.c
+++ b/virt/kvm/arm/vgic/vgic-its.c
@@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
 	list_for_each_entry(ite, &device->itt_head, ite_list) {
 		gpa_t gpa = base + ite->event_id * ite_esz;
 
+		/*
+		 * If an LPI carries the HW bit, this means that this
+		 * interrupt is controlled by GICv4, and we do not
+		 * have direct access to that state. Let's simply fail
+		 * the save operation...
+		 */
+		if (ite->irq->hw)
+			return -EINVAL;
+
 		ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
 		if (ret)
 			return ret;
-- 
2.14.1

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

* [PATCH v4 24/26] KVM: arm/arm64: GICv4: Enable VLPI support
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:33   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

All it takes is the has_v4 flag to be set in gic_kvm_info
as well as "kvm-arm.vgic_v4_enable=1" being passed on the
command line for GICv4 to be enabled in KVM.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  4 ++++
 virt/kvm/arm/vgic/vgic-v3.c                     | 14 ++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 05496622b4ef..93c8fff399eb 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1874,6 +1874,10 @@
 			[KVM,ARM] Trap guest accesses to GICv3 common
 			system registers
 
+	kvm-arm.vgic_v4_enable=
+			[KVM,ARM] Allow use of GICv4 for direct injection of
+			LPIs.
+
 	kvm-intel.ept=	[KVM,Intel] Disable extended page tables
 			(virtualized MMU) support on capable Intel chips.
 			Default is 1 (enabled)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 96ea597db0e7..405733678c2f 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -24,6 +24,7 @@
 static bool group0_trap;
 static bool group1_trap;
 static bool common_trap;
+static bool gicv4_enable;
 
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
@@ -459,6 +460,12 @@ static int __init early_common_trap_cfg(char *buf)
 }
 early_param("kvm-arm.vgic_v3_common_trap", early_common_trap_cfg);
 
+static int __init early_gicv4_enable(char *buf)
+{
+	return strtobool(buf, &gicv4_enable);
+}
+early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
@@ -478,6 +485,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	kvm_vgic_global_state.can_emulate_gicv2 = false;
 	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
 
+	/* GICv4 support? */
+	if (info->has_v4) {
+		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
+		kvm_info("GICv4 support %sabled\n",
+			 gicv4_enable ? "en" : "dis");
+	}
+
 	if (!info->vcpu.start) {
 		kvm_info("GICv3: no GICV resource entry\n");
 		kvm_vgic_global_state.vcpu_base = 0;
-- 
2.14.1

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

* [PATCH v4 24/26] KVM: arm/arm64: GICv4: Enable VLPI support
@ 2017-10-06 15:33   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:33 UTC (permalink / raw)
  To: linux-arm-kernel

All it takes is the has_v4 flag to be set in gic_kvm_info
as well as "kvm-arm.vgic_v4_enable=1" being passed on the
command line for GICv4 to be enabled in KVM.

Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/admin-guide/kernel-parameters.txt |  4 ++++
 virt/kvm/arm/vgic/vgic-v3.c                     | 14 ++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/Documentation/admin-guide/kernel-parameters.txt b/Documentation/admin-guide/kernel-parameters.txt
index 05496622b4ef..93c8fff399eb 100644
--- a/Documentation/admin-guide/kernel-parameters.txt
+++ b/Documentation/admin-guide/kernel-parameters.txt
@@ -1874,6 +1874,10 @@
 			[KVM,ARM] Trap guest accesses to GICv3 common
 			system registers
 
+	kvm-arm.vgic_v4_enable=
+			[KVM,ARM] Allow use of GICv4 for direct injection of
+			LPIs.
+
 	kvm-intel.ept=	[KVM,Intel] Disable extended page tables
 			(virtualized MMU) support on capable Intel chips.
 			Default is 1 (enabled)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 96ea597db0e7..405733678c2f 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -24,6 +24,7 @@
 static bool group0_trap;
 static bool group1_trap;
 static bool common_trap;
+static bool gicv4_enable;
 
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
@@ -459,6 +460,12 @@ static int __init early_common_trap_cfg(char *buf)
 }
 early_param("kvm-arm.vgic_v3_common_trap", early_common_trap_cfg);
 
+static int __init early_gicv4_enable(char *buf)
+{
+	return strtobool(buf, &gicv4_enable);
+}
+early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
@@ -478,6 +485,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	kvm_vgic_global_state.can_emulate_gicv2 = false;
 	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
 
+	/* GICv4 support? */
+	if (info->has_v4) {
+		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
+		kvm_info("GICv4 support %sabled\n",
+			 gicv4_enable ? "en" : "dis");
+	}
+
 	if (!info->vcpu.start) {
 		kvm_info("GICv3: no GICV resource entry\n");
 		kvm_vgic_global_state.vcpu_base = 0;
-- 
2.14.1

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:34   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:34 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
cohabit with CPUs limited to GICv3 in the same system.

This is mad (the scheduler would have to be made aware of the v4
capability), and we're certainly not going to support this any
time soon. So let's check that all online CPUs are GICv4 capable,
and disable the functionnality if not.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqchip/arm-gic-v3.h |  2 ++
 virt/kvm/arm/vgic/vgic-v3.c        | 27 +++++++++++++++++++++++++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 1ea576c8126f..dfa4a51643d6 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -532,6 +532,8 @@
 #define ICH_VTR_SEIS_MASK		(1 << ICH_VTR_SEIS_SHIFT)
 #define ICH_VTR_A3V_SHIFT		21
 #define ICH_VTR_A3V_MASK		(1 << ICH_VTR_A3V_SHIFT)
+#define ICH_VTR_nV4_SHIFT		20
+#define ICH_VTR_nV4_MASK		(1 << ICH_VTR_nV4_SHIFT)
 
 #define ICC_IAR1_EL1_SPURIOUS		0x3ff
 
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 405733678c2f..da99df50a818 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -466,9 +466,19 @@ static int __init early_gicv4_enable(char *buf)
 }
 early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
 
+static void vgic_check_v4_cpuif(void *param)
+{
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+	bool *v4 = param;
+
+	*v4 = !(ich_vtr_el2 & ICH_VTR_nV4_MASK);
+	if (!*v4)
+		kvm_info("CPU%d is not GICv4 capable\n", smp_processor_id());
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
- * @node:	pointer to the DT node
+ * @info:	pointer to the firmware-agnostic GIC information
  *
  * Returns 0 if a GICv3 has been found, returns an error code otherwise
  */
@@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	kvm_vgic_global_state.can_emulate_gicv2 = false;
 	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
 
-	/* GICv4 support? */
+	/*
+	 * GICv4 support? We need to check on all CPUs in case of some
+	 * extremely creative form of big-little brain damage...
+	 */
 	if (info->has_v4) {
+		int cpu;
+
+		for_each_online_cpu(cpu) {
+			bool enable;
+
+			smp_call_function_single(cpu, vgic_check_v4_cpuif,
+						 &enable, 1);
+			gicv4_enable = gicv4_enable && enable;
+		}
+
 		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
 		kvm_info("GICv4 support %sabled\n",
 			 gicv4_enable ? "en" : "dis");
-- 
2.14.1

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-06 15:34   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
cohabit with CPUs limited to GICv3 in the same system.

This is mad (the scheduler would have to be made aware of the v4
capability), and we're certainly not going to support this any
time soon. So let's check that all online CPUs are GICv4 capable,
and disable the functionnality if not.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqchip/arm-gic-v3.h |  2 ++
 virt/kvm/arm/vgic/vgic-v3.c        | 27 +++++++++++++++++++++++++--
 2 files changed, 27 insertions(+), 2 deletions(-)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 1ea576c8126f..dfa4a51643d6 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -532,6 +532,8 @@
 #define ICH_VTR_SEIS_MASK		(1 << ICH_VTR_SEIS_SHIFT)
 #define ICH_VTR_A3V_SHIFT		21
 #define ICH_VTR_A3V_MASK		(1 << ICH_VTR_A3V_SHIFT)
+#define ICH_VTR_nV4_SHIFT		20
+#define ICH_VTR_nV4_MASK		(1 << ICH_VTR_nV4_SHIFT)
 
 #define ICC_IAR1_EL1_SPURIOUS		0x3ff
 
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 405733678c2f..da99df50a818 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -466,9 +466,19 @@ static int __init early_gicv4_enable(char *buf)
 }
 early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
 
+static void vgic_check_v4_cpuif(void *param)
+{
+	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
+	bool *v4 = param;
+
+	*v4 = !(ich_vtr_el2 & ICH_VTR_nV4_MASK);
+	if (!*v4)
+		kvm_info("CPU%d is not GICv4 capable\n", smp_processor_id());
+}
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
- * @node:	pointer to the DT node
+ * @info:	pointer to the firmware-agnostic GIC information
  *
  * Returns 0 if a GICv3 has been found, returns an error code otherwise
  */
@@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	kvm_vgic_global_state.can_emulate_gicv2 = false;
 	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
 
-	/* GICv4 support? */
+	/*
+	 * GICv4 support? We need to check on all CPUs in case of some
+	 * extremely creative form of big-little brain damage...
+	 */
 	if (info->has_v4) {
+		int cpu;
+
+		for_each_online_cpu(cpu) {
+			bool enable;
+
+			smp_call_function_single(cpu, vgic_check_v4_cpuif,
+						 &enable, 1);
+			gicv4_enable = gicv4_enable && enable;
+		}
+
 		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
 		kvm_info("GICv4 support %sabled\n",
 			 gicv4_enable ? "en" : "dis");
-- 
2.14.1

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

* [PATCH v4 26/26] KVM: arm/arm64: GICv4: Theory of operations
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-06 15:34   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:34 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

Yet another braindump so I can free some cells...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 68a2ef6df161..b87806fea554 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -22,6 +22,73 @@
 
 #include "vgic.h"
 
+/*
+ * How KVM uses GICv4 (insert rude comments here):
+ *
+ * The vgic-v4 layer acts as a bridge between several entities:
+ * - The GICv4 ITS representation offered by the ITS driver
+ * - VFIO, which is in charge of the PCI endpoint
+ * - The virtual ITS, which is the only thing the guest sees
+ *
+ * The configuration of VLPIs is triggered by a callback from VFIO,
+ * instructing KVM that a PCI device has been configured to deliver
+ * MSIs to a vITS.
+ *
+ * kvm_vgic_v4_set_forwarding() is thus called with the routing entry,
+ * and this is used to find the corresponding vITS data structures
+ * (ITS instance, device, event and irq) using a process that is
+ * extremely similar to the injection of an MSI.
+ *
+ * At this stage, we can link the guest's view of an LPI (uniquely
+ * identified by the routing entry) and the host irq, using the GICv4
+ * driver mapping operation. Should the mapping succeed, we've then
+ * successfully upgraded the guest's LPI to a VLPI. We can then start
+ * with updating GICv4's view of the property table and generating an
+ * INValidation in order to kickstart the delivery of this VLPI to the
+ * guest directly, without software intervention. Well, almost.
+ *
+ * When the PCI endpoint is deconfigured, this operation is reversed
+ * with VFIO calling kvm_vgic_v4_unset_forwarding().
+ *
+ * Once the VLPI has been mapped, it needs to follow any change the
+ * guest performs on its LPI through the vITS. For that, a number of
+ * command handlers have hooks to communicate these changes to the HW:
+ * - Any invalidation triggers a call to its_prop_update_vlpi()
+ * - The INT command results in a irq_set_irqchip_state(), which
+ *   generates an INT on the corresponding VLPI.
+ * - The CLEAR command results in a irq_set_irqchip_state(), which
+ *   generates an CLEAR on the corresponding VLPI.
+ * - DISCARD translates into an unmap, similar to a call to
+ *   kvm_vgic_v4_unset_forwarding().
+ * - MOVI is translated by an update of the existing mapping, changing
+ *   the target vcpu, resulting in a VMOVI being generated.
+ * - MOVALL is translated by a string of mapping updates (similar to
+ *   the handling of MOVI). MOVALL is horrible.
+ *
+ * Note that a DISCARD/MAPTI sequence emitted from the guest without
+ * reprogramming the PCI endpoint after MAPTI does not result in a
+ * VLPI being mapped, as there is no callback from VFIO (the guest
+ * will get the interrupt via the normal SW injection). Fixing this is
+ * not trivial, and requires some horrible messing with the VFIO
+ * internals. Not fun. Don't do that.
+ *
+ * Then there is the scheduling. Each time a vcpu is about to run on a
+ * physical CPU, KVM must tell the corresponding redistributor about
+ * 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.
+ *
+ * Finally, the doorbell handling: Each vcpu is allocated an interrupt
+ * which will fire each time a VLPI is made pending whilst the vcpu is
+ * not running. Each time the vcpu gets blocked, the doorbell
+ * interrupt gets enabled. When the vcpu is unblocked (for whatever
+ * reason), the doorbell interrupt is disabled.
+ */
+
 static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 {
 	struct kvm_vcpu *vcpu = info;
-- 
2.14.1

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

* [PATCH v4 26/26] KVM: arm/arm64: GICv4: Theory of operations
@ 2017-10-06 15:34   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-06 15:34 UTC (permalink / raw)
  To: linux-arm-kernel

Yet another braindump so I can free some cells...

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 67 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index 68a2ef6df161..b87806fea554 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -22,6 +22,73 @@
 
 #include "vgic.h"
 
+/*
+ * How KVM uses GICv4 (insert rude comments here):
+ *
+ * The vgic-v4 layer acts as a bridge between several entities:
+ * - The GICv4 ITS representation offered by the ITS driver
+ * - VFIO, which is in charge of the PCI endpoint
+ * - The virtual ITS, which is the only thing the guest sees
+ *
+ * The configuration of VLPIs is triggered by a callback from VFIO,
+ * instructing KVM that a PCI device has been configured to deliver
+ * MSIs to a vITS.
+ *
+ * kvm_vgic_v4_set_forwarding() is thus called with the routing entry,
+ * and this is used to find the corresponding vITS data structures
+ * (ITS instance, device, event and irq) using a process that is
+ * extremely similar to the injection of an MSI.
+ *
+ * At this stage, we can link the guest's view of an LPI (uniquely
+ * identified by the routing entry) and the host irq, using the GICv4
+ * driver mapping operation. Should the mapping succeed, we've then
+ * successfully upgraded the guest's LPI to a VLPI. We can then start
+ * with updating GICv4's view of the property table and generating an
+ * INValidation in order to kickstart the delivery of this VLPI to the
+ * guest directly, without software intervention. Well, almost.
+ *
+ * When the PCI endpoint is deconfigured, this operation is reversed
+ * with VFIO calling kvm_vgic_v4_unset_forwarding().
+ *
+ * Once the VLPI has been mapped, it needs to follow any change the
+ * guest performs on its LPI through the vITS. For that, a number of
+ * command handlers have hooks to communicate these changes to the HW:
+ * - Any invalidation triggers a call to its_prop_update_vlpi()
+ * - The INT command results in a irq_set_irqchip_state(), which
+ *   generates an INT on the corresponding VLPI.
+ * - The CLEAR command results in a irq_set_irqchip_state(), which
+ *   generates an CLEAR on the corresponding VLPI.
+ * - DISCARD translates into an unmap, similar to a call to
+ *   kvm_vgic_v4_unset_forwarding().
+ * - MOVI is translated by an update of the existing mapping, changing
+ *   the target vcpu, resulting in a VMOVI being generated.
+ * - MOVALL is translated by a string of mapping updates (similar to
+ *   the handling of MOVI). MOVALL is horrible.
+ *
+ * Note that a DISCARD/MAPTI sequence emitted from the guest without
+ * reprogramming the PCI endpoint after MAPTI does not result in a
+ * VLPI being mapped, as there is no callback from VFIO (the guest
+ * will get the interrupt via the normal SW injection). Fixing this is
+ * not trivial, and requires some horrible messing with the VFIO
+ * internals. Not fun. Don't do that.
+ *
+ * Then there is the scheduling. Each time a vcpu is about to run on a
+ * physical CPU, KVM must tell the corresponding redistributor about
+ * 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.
+ *
+ * Finally, the doorbell handling: Each vcpu is allocated an interrupt
+ * which will fire each time a VLPI is made pending whilst the vcpu is
+ * not running. Each time the vcpu gets blocked, the doorbell
+ * interrupt gets enabled. When the vcpu is unblocked (for whatever
+ * reason), the doorbell interrupt is disabled.
+ */
+
 static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 {
 	struct kvm_vcpu *vcpu = info;
-- 
2.14.1

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

* Re: [PATCH v4 00/26] KVM/ARM: Add support for GICv4
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-08 16:45   ` Shanker Donthineni
  -1 siblings, 0 replies; 117+ messages in thread
From: Shanker Donthineni @ 2017-10-08 16:45 UTC (permalink / raw)
  To: Marc Zyngier, linux-arm-kernel, kvmarm, kvm
  Cc: Mark Rutland, Andre Przywara, Shameerali Kolothum Thodi,
	Eric Auger, Christoffer Dall

Hi Marc,

I've tested this patch series on QDF2400 server platform using NVME card, the basic
functionality works fine and the below log messages shows around 70 interrupts
are delivered to vCPU directly.


Tested-by: Shanker Donthineni <shankerd@codeaurora.org>


>From guest kernel:
 /mnt # cat /proc/interrupts | grep ITS
 51:         83   ITS-MSI 32768 Edge      nvme0q0, nvme0q1
 52:          0   ITS-MSI 16384 Edge      virtio0-config
 53:          0   ITS-MSI 16385 Edge      virtio0-input.0
 54:          0   ITS-MSI 16386 Edge      virtio0-output.0
 
>From host kernel:
 /mnt # cat /proc/interrupts | grep GICv4
 388:          9  GICv4-vpe   0 Edge      vcpu

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* [PATCH v4 00/26] KVM/ARM: Add support for GICv4
@ 2017-10-08 16:45   ` Shanker Donthineni
  0 siblings, 0 replies; 117+ messages in thread
From: Shanker Donthineni @ 2017-10-08 16:45 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

I've tested this patch series on QDF2400 server platform using NVME card, the basic
functionality works fine and the below log messages shows around 70 interrupts
are delivered to vCPU directly.


Tested-by: Shanker Donthineni <shankerd@codeaurora.org>


>From guest kernel:
 /mnt # cat /proc/interrupts | grep ITS
 51:         83   ITS-MSI 32768 Edge      nvme0q0, nvme0q1
 52:          0   ITS-MSI 16384 Edge      virtio0-config
 53:          0   ITS-MSI 16385 Edge      virtio0-input.0
 54:          0   ITS-MSI 16386 Edge      virtio0-output.0
 
>From host kernel:
 /mnt # cat /proc/interrupts | grep GICv4
 388:          9  GICv4-vpe   0 Edge      vcpu

-- 
Shanker Donthineni
Qualcomm Datacenter Technologies, Inc. as an affiliate of Qualcomm Technologies, Inc.
Qualcomm Technologies, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project.

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

* Re: [PATCH v4 00/26] KVM/ARM: Add support for GICv4
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-09 17:52   ` Konrad Rzeszutek Wilk
  -1 siblings, 0 replies; 117+ messages in thread
From: Konrad Rzeszutek Wilk @ 2017-10-09 17:52 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:35PM +0100, Marc Zyngier wrote:
> This series implements full support for GICv4 in KVM, bringing direct
> injection of MSIs to arm and arm64, assuming you have the right
> hardware (which is quite unlikely).
> 
> To get an idea of the design, I'd recommend you start with commit
> 7954907bedaf as well as patch #26, which try to shed some light on the
> approach that I've taken. And before that, please digest some of the
> GICv3/GICv4 architecture documentation[1] (less than 800 pages!). Once
> you feel reasonably insane, you'll be in the right mood to read the

You may want to update the link:

s/pfd/pdf/

(Does that mean you typed this by hand, my gosh, you really are breathing
this everyday) :-)

> code (no, I didn't bother changing the above, I already hit LWN/QotW
> once).

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

* [PATCH v4 00/26] KVM/ARM: Add support for GICv4
@ 2017-10-09 17:52   ` Konrad Rzeszutek Wilk
  0 siblings, 0 replies; 117+ messages in thread
From: Konrad Rzeszutek Wilk @ 2017-10-09 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:35PM +0100, Marc Zyngier wrote:
> This series implements full support for GICv4 in KVM, bringing direct
> injection of MSIs to arm and arm64, assuming you have the right
> hardware (which is quite unlikely).
> 
> To get an idea of the design, I'd recommend you start with commit
> 7954907bedaf as well as patch #26, which try to shed some light on the
> approach that I've taken. And before that, please digest some of the
> GICv3/GICv4 architecture documentation[1] (less than 800 pages!). Once
> you feel reasonably insane, you'll be in the right mood to read the

You may want to update the link:

s/pfd/pdf/

(Does that mean you typed this by hand, my gosh, you really are breathing
this everyday) :-)

> code (no, I didn't bother changing the above, I already hit LWN/QotW
> once).

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

* Re: [PATCH v4 00/26] KVM/ARM: Add support for GICv4
  2017-10-09 17:52   ` Konrad Rzeszutek Wilk
@ 2017-10-09 18:02     ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-09 18:02 UTC (permalink / raw)
  To: Konrad Rzeszutek Wilk
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Mark Rutland, Shameerali Kolothum Thodi,
	Andre Przywara

On 09/10/17 18:52, Konrad Rzeszutek Wilk wrote:
> On Fri, Oct 06, 2017 at 04:33:35PM +0100, Marc Zyngier wrote:
>> This series implements full support for GICv4 in KVM, bringing direct
>> injection of MSIs to arm and arm64, assuming you have the right
>> hardware (which is quite unlikely).
>>
>> To get an idea of the design, I'd recommend you start with commit
>> 7954907bedaf as well as patch #26, which try to shed some light on the
>> approach that I've taken. And before that, please digest some of the
>> GICv3/GICv4 architecture documentation[1] (less than 800 pages!). Once
>> you feel reasonably insane, you'll be in the right mood to read the
> 
> You may want to update the link:
> 
> s/pfd/pdf/
> 
> (Does that mean you typed this by hand, my gosh, you really are breathing
> this everyday) :-)
I am, and I'm feeling pretty dizzy. You can't imagine the kind of fumes
this thing generates... ;-)

I probably copy/pasted the URL, edited something, messed up the URL,
fixed it (sort of), and ended posting the crap (twice!) without even
realizing. Oh well. I'll blame the spec, as always.

Thanks for the heads up!

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH v4 00/26] KVM/ARM: Add support for GICv4
@ 2017-10-09 18:02     ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-09 18:02 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/10/17 18:52, Konrad Rzeszutek Wilk wrote:
> On Fri, Oct 06, 2017 at 04:33:35PM +0100, Marc Zyngier wrote:
>> This series implements full support for GICv4 in KVM, bringing direct
>> injection of MSIs to arm and arm64, assuming you have the right
>> hardware (which is quite unlikely).
>>
>> To get an idea of the design, I'd recommend you start with commit
>> 7954907bedaf as well as patch #26, which try to shed some light on the
>> approach that I've taken. And before that, please digest some of the
>> GICv3/GICv4 architecture documentation[1] (less than 800 pages!). Once
>> you feel reasonably insane, you'll be in the right mood to read the
> 
> You may want to update the link:
> 
> s/pfd/pdf/
> 
> (Does that mean you typed this by hand, my gosh, you really are breathing
> this everyday) :-)
I am, and I'm feeling pretty dizzy. You can't imagine the kind of fumes
this thing generates... ;-)

I probably copy/pasted the URL, edited something, messed up the URL,
fixed it (sort of), and ended posting the crap (twice!) without even
realizing. Oh well. I'll blame the spec, as always.

Thanks for the heads up!

	M.
-- 
Jazz is not dead. It just smells funny...

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

* [PATCH v4 27/26] KVM: arm/arm64: GICv4: Prevent userspace from changing doorbell affinity
  2017-10-06 15:33 ` Marc Zyngier
@ 2017-10-19 15:48   ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-19 15:48 UTC (permalink / raw)
  To: linux-arm-kernel, kvmarm, kvm; +Cc: Andre Przywara

We so far allocate the doorbell interrupts without taking any
special measure regarding the affinity of these interrupts. We
simply move them around as required when the vcpu gets scheduled
on a different CPU.

But that's counting without userspace (and the evil irqbalance) that
can try and move the VPE interrupt around, causing the ITS code
to emit VMOVP commands and remap the doorbell to another redistributor.
Worse, this can happen while the vcpu is running, causing all kind
of trouble if the VPE is already resident, and we end-up in UNPRED
territory.

So let's take a definitive action and prevent userspace from messing
with us. This is just a matter of adding IRQ_NO_BALANCING to the
set of flags we already have, letting the kernel in sole control
of the affinity.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

This extra patch goes on top of the current GICv4 patches, and is hence
being posted with a weird sequence number...

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index b87806fea554..c3dbab714328 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -89,6 +89,8 @@
  * reason), the doorbell interrupt is disabled.
  */
 
+#define DB_IRQ_FLAGS	(IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY | IRQ_NO_BALANCING)
+
 static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 {
 	struct kvm_vcpu *vcpu = info;
@@ -149,7 +151,7 @@ int vgic_v4_init(struct kvm *kvm)
 		 * doorbell could kick us out of the guest too
 		 * early...
 		 */
-		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		irq_set_status_flags(irq, DB_IRQ_FLAGS);
 		ret = request_irq(irq, vgic_v4_doorbell_handler,
 				  0, "vcpu", vcpu);
 		if (ret) {
@@ -187,7 +189,7 @@ void vgic_v4_teardown(struct kvm *kvm)
 		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
 		int irq = its_vm->vpes[i]->irq;
 
-		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		irq_clear_status_flags(irq, DB_IRQ_FLAGS);
 		free_irq(irq, vcpu);
 	}
 
-- 
2.14.1

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

* [PATCH v4 27/26] KVM: arm/arm64: GICv4: Prevent userspace from changing doorbell affinity
@ 2017-10-19 15:48   ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-19 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

We so far allocate the doorbell interrupts without taking any
special measure regarding the affinity of these interrupts. We
simply move them around as required when the vcpu gets scheduled
on a different CPU.

But that's counting without userspace (and the evil irqbalance) that
can try and move the VPE interrupt around, causing the ITS code
to emit VMOVP commands and remap the doorbell to another redistributor.
Worse, this can happen while the vcpu is running, causing all kind
of trouble if the VPE is already resident, and we end-up in UNPRED
territory.

So let's take a definitive action and prevent userspace from messing
with us. This is just a matter of adding IRQ_NO_BALANCING to the
set of flags we already have, letting the kernel in sole control
of the affinity.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v4.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

This extra patch goes on top of the current GICv4 patches, and is hence
being posted with a weird sequence number...

diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
index b87806fea554..c3dbab714328 100644
--- a/virt/kvm/arm/vgic/vgic-v4.c
+++ b/virt/kvm/arm/vgic/vgic-v4.c
@@ -89,6 +89,8 @@
  * reason), the doorbell interrupt is disabled.
  */
 
+#define DB_IRQ_FLAGS	(IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY | IRQ_NO_BALANCING)
+
 static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
 {
 	struct kvm_vcpu *vcpu = info;
@@ -149,7 +151,7 @@ int vgic_v4_init(struct kvm *kvm)
 		 * doorbell could kick us out of the guest too
 		 * early...
 		 */
-		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		irq_set_status_flags(irq, DB_IRQ_FLAGS);
 		ret = request_irq(irq, vgic_v4_doorbell_handler,
 				  0, "vcpu", vcpu);
 		if (ret) {
@@ -187,7 +189,7 @@ void vgic_v4_teardown(struct kvm *kvm)
 		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
 		int irq = its_vm->vpes[i]->irq;
 
-		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
+		irq_clear_status_flags(irq, DB_IRQ_FLAGS);
 		free_irq(irq, vcpu);
 	}
 
-- 
2.14.1

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

* Re: [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 14:44     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 14:44 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:37PM +0100, Marc Zyngier wrote:
> From: Eric Auger <eric.auger@redhat.com>
> 
> We want to reuse the core of the map/unmap functions for IRQ
> forwarding. Let's move the computation of the hwirq in
> kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
> the host_irq is added to struct vgic_irq.
> 
> We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
> handle as a parameter.
> 

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

Marc,
  I need a signed-off-by from you on this patch.

Thanks,
-Christoffer

> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  include/kvm/arm_vgic.h    |  8 ++++---
>  virt/kvm/arm/arch_timer.c | 24 +------------------
>  virt/kvm/arm/vgic/vgic.c  | 60 +++++++++++++++++++++++++++++++++++------------
>  3 files changed, 51 insertions(+), 41 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 34dba516ef24..53f631bdec75 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -116,6 +116,7 @@ struct vgic_irq {
>  	bool hw;			/* Tied to HW IRQ */
>  	struct kref refcount;		/* Used for LPIs */
>  	u32 hwintid;			/* HW INTID number */
> +	unsigned int host_irq;		/* linux irq corresponding to hwintid */
>  	union {
>  		u8 targets;			/* GICv2 target VCPUs mask */
>  		u32 mpidr;			/* GICv3 target VCPU */
> @@ -307,9 +308,10 @@ void kvm_vgic_init_cpu_hardware(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level, void *owner);
> -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
> -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
> -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
> +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
> +			  u32 vintid);
> +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
> +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
>  
>  int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>  
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 8e89d63005c7..b24e2f7b363a 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -647,9 +647,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
>  {
>  	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>  	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
> -	struct irq_desc *desc;
> -	struct irq_data *data;
> -	int phys_irq;
>  	int ret;
>  
>  	if (timer->enabled)
> @@ -667,26 +664,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
>  		return -EINVAL;
>  	}
>  
> -	/*
> -	 * Find the physical IRQ number corresponding to the host_vtimer_irq
> -	 */
> -	desc = irq_to_desc(host_vtimer_irq);
> -	if (!desc) {
> -		kvm_err("%s: no interrupt descriptor\n", __func__);
> -		return -EINVAL;
> -	}
> -
> -	data = irq_desc_get_irq_data(desc);
> -	while (data->parent_data)
> -		data = data->parent_data;
> -
> -	phys_irq = data->hwirq;
> -
> -	/*
> -	 * Tell the VGIC that the virtual interrupt is tied to a
> -	 * physical interrupt. We do that once per VCPU.
> -	 */
> -	ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
> +	ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq);
>  	if (ret)
>  		return ret;
>  
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index fed717e07938..9d557efd1f7d 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -17,6 +17,8 @@
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
>  #include <linux/list_sort.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
>  
>  #include "vgic.h"
>  
> @@ -403,38 +405,66 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  	return 0;
>  }
>  
> -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
> +/* @irq->irq_lock must be held */
> +static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
> +			    unsigned int host_irq)
>  {
> -	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	struct irq_desc *desc;
> +	struct irq_data *data;
>  
> -	BUG_ON(!irq);
> -
> -	spin_lock(&irq->irq_lock);
> +	/*
> +	 * Find the physical IRQ number corresponding to @host_irq
> +	 */
> +	desc = irq_to_desc(host_irq);
> +	if (!desc) {
> +		kvm_err("%s: no interrupt descriptor\n", __func__);
> +		return -EINVAL;
> +	}
> +	data = irq_desc_get_irq_data(desc);
> +	while (data->parent_data)
> +		data = data->parent_data;
>  
>  	irq->hw = true;
> -	irq->hwintid = phys_irq;
> +	irq->host_irq = host_irq;
> +	irq->hwintid = data->hwirq;
> +	return 0;
> +}
> +
> +/* @irq->irq_lock must be held */
> +static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
> +{
> +	irq->hw = false;
> +	irq->hwintid = 0;
> +}
> +
> +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
> +			  u32 vintid)
> +{
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
> +	int ret;
>  
> +	BUG_ON(!irq);
> +
> +	spin_lock(&irq->irq_lock);
> +	ret = kvm_vgic_map_irq(vcpu, irq, host_irq);
>  	spin_unlock(&irq->irq_lock);
>  	vgic_put_irq(vcpu->kvm, irq);
>  
> -	return 0;
> +	return ret;
>  }
>  
> -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
> +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
>  {
>  	struct vgic_irq *irq;
>  
>  	if (!vgic_initialized(vcpu->kvm))
>  		return -EAGAIN;
>  
> -	irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
>  	BUG_ON(!irq);
>  
>  	spin_lock(&irq->irq_lock);
> -
> -	irq->hw = false;
> -	irq->hwintid = 0;
> -
> +	kvm_vgic_unmap_irq(irq);
>  	spin_unlock(&irq->irq_lock);
>  	vgic_put_irq(vcpu->kvm, irq);
>  
> @@ -772,9 +802,9 @@ void vgic_kick_vcpus(struct kvm *kvm)
>  	}
>  }
>  
> -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
> +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
>  {
> -	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
>  	bool map_is_active;
>  
>  	spin_lock(&irq->irq_lock);
> -- 
> 2.14.1
> 

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

* [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
@ 2017-10-25 14:44     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 14:44 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:37PM +0100, Marc Zyngier wrote:
> From: Eric Auger <eric.auger@redhat.com>
> 
> We want to reuse the core of the map/unmap functions for IRQ
> forwarding. Let's move the computation of the hwirq in
> kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
> the host_irq is added to struct vgic_irq.
> 
> We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
> handle as a parameter.
> 

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

Marc,
  I need a signed-off-by from you on this patch.

Thanks,
-Christoffer

> Signed-off-by: Eric Auger <eric.auger@redhat.com>
> ---
>  include/kvm/arm_vgic.h    |  8 ++++---
>  virt/kvm/arm/arch_timer.c | 24 +------------------
>  virt/kvm/arm/vgic/vgic.c  | 60 +++++++++++++++++++++++++++++++++++------------
>  3 files changed, 51 insertions(+), 41 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 34dba516ef24..53f631bdec75 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -116,6 +116,7 @@ struct vgic_irq {
>  	bool hw;			/* Tied to HW IRQ */
>  	struct kref refcount;		/* Used for LPIs */
>  	u32 hwintid;			/* HW INTID number */
> +	unsigned int host_irq;		/* linux irq corresponding to hwintid */
>  	union {
>  		u8 targets;			/* GICv2 target VCPUs mask */
>  		u32 mpidr;			/* GICv3 target VCPU */
> @@ -307,9 +308,10 @@ void kvm_vgic_init_cpu_hardware(void);
>  
>  int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  			bool level, void *owner);
> -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq);
> -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq);
> -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq);
> +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
> +			  u32 vintid);
> +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid);
> +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid);
>  
>  int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu);
>  
> diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
> index 8e89d63005c7..b24e2f7b363a 100644
> --- a/virt/kvm/arm/arch_timer.c
> +++ b/virt/kvm/arm/arch_timer.c
> @@ -647,9 +647,6 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
>  {
>  	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
>  	struct arch_timer_context *vtimer = vcpu_vtimer(vcpu);
> -	struct irq_desc *desc;
> -	struct irq_data *data;
> -	int phys_irq;
>  	int ret;
>  
>  	if (timer->enabled)
> @@ -667,26 +664,7 @@ int kvm_timer_enable(struct kvm_vcpu *vcpu)
>  		return -EINVAL;
>  	}
>  
> -	/*
> -	 * Find the physical IRQ number corresponding to the host_vtimer_irq
> -	 */
> -	desc = irq_to_desc(host_vtimer_irq);
> -	if (!desc) {
> -		kvm_err("%s: no interrupt descriptor\n", __func__);
> -		return -EINVAL;
> -	}
> -
> -	data = irq_desc_get_irq_data(desc);
> -	while (data->parent_data)
> -		data = data->parent_data;
> -
> -	phys_irq = data->hwirq;
> -
> -	/*
> -	 * Tell the VGIC that the virtual interrupt is tied to a
> -	 * physical interrupt. We do that once per VCPU.
> -	 */
> -	ret = kvm_vgic_map_phys_irq(vcpu, vtimer->irq.irq, phys_irq);
> +	ret = kvm_vgic_map_phys_irq(vcpu, host_vtimer_irq, vtimer->irq.irq);
>  	if (ret)
>  		return ret;
>  
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index fed717e07938..9d557efd1f7d 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -17,6 +17,8 @@
>  #include <linux/kvm.h>
>  #include <linux/kvm_host.h>
>  #include <linux/list_sort.h>
> +#include <linux/interrupt.h>
> +#include <linux/irq.h>
>  
>  #include "vgic.h"
>  
> @@ -403,38 +405,66 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
>  	return 0;
>  }
>  
> -int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, u32 virt_irq, u32 phys_irq)
> +/* @irq->irq_lock must be held */
> +static int kvm_vgic_map_irq(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
> +			    unsigned int host_irq)
>  {
> -	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	struct irq_desc *desc;
> +	struct irq_data *data;
>  
> -	BUG_ON(!irq);
> -
> -	spin_lock(&irq->irq_lock);
> +	/*
> +	 * Find the physical IRQ number corresponding to @host_irq
> +	 */
> +	desc = irq_to_desc(host_irq);
> +	if (!desc) {
> +		kvm_err("%s: no interrupt descriptor\n", __func__);
> +		return -EINVAL;
> +	}
> +	data = irq_desc_get_irq_data(desc);
> +	while (data->parent_data)
> +		data = data->parent_data;
>  
>  	irq->hw = true;
> -	irq->hwintid = phys_irq;
> +	irq->host_irq = host_irq;
> +	irq->hwintid = data->hwirq;
> +	return 0;
> +}
> +
> +/* @irq->irq_lock must be held */
> +static inline void kvm_vgic_unmap_irq(struct vgic_irq *irq)
> +{
> +	irq->hw = false;
> +	irq->hwintid = 0;
> +}
> +
> +int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
> +			  u32 vintid)
> +{
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
> +	int ret;
>  
> +	BUG_ON(!irq);
> +
> +	spin_lock(&irq->irq_lock);
> +	ret = kvm_vgic_map_irq(vcpu, irq, host_irq);
>  	spin_unlock(&irq->irq_lock);
>  	vgic_put_irq(vcpu->kvm, irq);
>  
> -	return 0;
> +	return ret;
>  }
>  
> -int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int virt_irq)
> +int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
>  {
>  	struct vgic_irq *irq;
>  
>  	if (!vgic_initialized(vcpu->kvm))
>  		return -EAGAIN;
>  
> -	irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
>  	BUG_ON(!irq);
>  
>  	spin_lock(&irq->irq_lock);
> -
> -	irq->hw = false;
> -	irq->hwintid = 0;
> -
> +	kvm_vgic_unmap_irq(irq);
>  	spin_unlock(&irq->irq_lock);
>  	vgic_put_irq(vcpu->kvm, irq);
>  
> @@ -772,9 +802,9 @@ void vgic_kick_vcpus(struct kvm *kvm)
>  	}
>  }
>  
> -bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int virt_irq)
> +bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
>  {
> -	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, virt_irq);
> +	struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
>  	bool map_is_active;
>  
>  	spin_lock(&irq->irq_lock);
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 06/26] KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 14:50     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 14:50 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:41PM +0100, Marc Zyngier wrote:
> In order help integrating the vITS code with GICv4, let's add
> a new helper that deals with updating the affinity of an LPI,
> which will later be augmented with super duper extra GICv4
> goodness.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 475dffd0a44c..8ee03f1e89fc 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -335,6 +335,15 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
>  	return i;
>  }
>  
> +static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
> +{
> +	spin_lock(&irq->irq_lock);
> +	irq->target_vcpu = vcpu;
> +	spin_unlock(&irq->irq_lock);
> +
> +	return 0;
> +}
> +
>  /*
>   * Promotes the ITS view of affinity of an ITTE (which redistributor this LPI
>   * is targeting) to the VGIC's view, which deals with target VCPUs.
> @@ -349,10 +358,7 @@ static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
>  		return;
>  
>  	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
> -
> -	spin_lock(&ite->irq->irq_lock);
> -	ite->irq->target_vcpu = vcpu;
> -	spin_unlock(&ite->irq->irq_lock);
> +	update_affinity(ite->irq, vcpu);
>  }
>  
>  /*
> @@ -693,11 +699,7 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
>  	ite->collection = collection;
>  	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
>  
> -	spin_lock(&ite->irq->irq_lock);
> -	ite->irq->target_vcpu = vcpu;
> -	spin_unlock(&ite->irq->irq_lock);
> -
> -	return 0;
> +	return update_affinity(ite->irq, vcpu);
>  }
>  
>  /*
> -- 
> 2.14.1
> 

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

* [PATCH v4 06/26] KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI
@ 2017-10-25 14:50     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 14:50 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:41PM +0100, Marc Zyngier wrote:
> In order help integrating the vITS code with GICv4, let's add
> a new helper that deals with updating the affinity of an LPI,
> which will later be augmented with super duper extra GICv4
> goodness.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-its.c | 20 +++++++++++---------
>  1 file changed, 11 insertions(+), 9 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 475dffd0a44c..8ee03f1e89fc 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -335,6 +335,15 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
>  	return i;
>  }
>  
> +static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
> +{
> +	spin_lock(&irq->irq_lock);
> +	irq->target_vcpu = vcpu;
> +	spin_unlock(&irq->irq_lock);
> +
> +	return 0;
> +}
> +
>  /*
>   * Promotes the ITS view of affinity of an ITTE (which redistributor this LPI
>   * is targeting) to the VGIC's view, which deals with target VCPUs.
> @@ -349,10 +358,7 @@ static void update_affinity_ite(struct kvm *kvm, struct its_ite *ite)
>  		return;
>  
>  	vcpu = kvm_get_vcpu(kvm, ite->collection->target_addr);
> -
> -	spin_lock(&ite->irq->irq_lock);
> -	ite->irq->target_vcpu = vcpu;
> -	spin_unlock(&ite->irq->irq_lock);
> +	update_affinity(ite->irq, vcpu);
>  }
>  
>  /*
> @@ -693,11 +699,7 @@ static int vgic_its_cmd_handle_movi(struct kvm *kvm, struct vgic_its *its,
>  	ite->collection = collection;
>  	vcpu = kvm_get_vcpu(kvm, collection->target_addr);
>  
> -	spin_lock(&ite->irq->irq_lock);
> -	ite->irq->target_vcpu = vcpu;
> -	spin_unlock(&ite->irq->irq_lock);
> -
> -	return 0;
> +	return update_affinity(ite->irq, vcpu);
>  }
>  
>  /*
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 07/26] KVM: arm/arm64: GICv4: Add property field and per-VM predicate
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 14:54     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 14:54 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Mark Rutland, Shameerali Kolothum Thodi,
	Andre Przywara

On Fri, Oct 06, 2017 at 04:33:42PM +0100, Marc Zyngier wrote:
> Add a new has_gicv4 field in the global VGIC state that indicates
> whether the HW is GICv4 capable, as a per-VM predicate indicating
> if there is a possibility for a VM to support direct injection
> (the above being true and the VM having an ITS).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  include/kvm/arm_vgic.h           | 3 +++
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 5 +++++
>  virt/kvm/arm/vgic/vgic.h         | 2 ++
>  3 files changed, 10 insertions(+)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 53f631bdec75..ba9fb450aa1b 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -73,6 +73,9 @@ struct vgic_global {
>  	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
>  	bool			can_emulate_gicv2;
>  
> +	/* Hardware has GICv4? */
> +	bool			has_gicv4;
> +
>  	/* GIC system register CPU interface */
>  	struct static_key_false gicv3_cpuif;
>  
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 408ef06638fc..f87fd17b2eb9 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -54,6 +54,11 @@ bool vgic_has_its(struct kvm *kvm)
>  	return dist->has_its;
>  }
>  
> +bool vgic_supports_direct_msis(struct kvm *kvm)
> +{
> +	return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
> +}
> +
>  static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
>  					    gpa_t addr, unsigned int len)
>  {
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 31b70326b966..e67ccb6a6250 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -240,4 +240,6 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
>  			 u32 devid, u32 eventid, struct vgic_irq **irq);
>  struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
>  
> +bool vgic_supports_direct_msis(struct kvm *kvm);
> +
>  #endif
> -- 
> 2.14.1
> 

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

* [PATCH v4 07/26] KVM: arm/arm64: GICv4: Add property field and per-VM predicate
@ 2017-10-25 14:54     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 14:54 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:42PM +0100, Marc Zyngier wrote:
> Add a new has_gicv4 field in the global VGIC state that indicates
> whether the HW is GICv4 capable, as a per-VM predicate indicating
> if there is a possibility for a VM to support direct injection
> (the above being true and the VM having an ITS).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  include/kvm/arm_vgic.h           | 3 +++
>  virt/kvm/arm/vgic/vgic-mmio-v3.c | 5 +++++
>  virt/kvm/arm/vgic/vgic.h         | 2 ++
>  3 files changed, 10 insertions(+)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 53f631bdec75..ba9fb450aa1b 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -73,6 +73,9 @@ struct vgic_global {
>  	/* Only needed for the legacy KVM_CREATE_IRQCHIP */
>  	bool			can_emulate_gicv2;
>  
> +	/* Hardware has GICv4? */
> +	bool			has_gicv4;
> +
>  	/* GIC system register CPU interface */
>  	struct static_key_false gicv3_cpuif;
>  
> diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> index 408ef06638fc..f87fd17b2eb9 100644
> --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
> @@ -54,6 +54,11 @@ bool vgic_has_its(struct kvm *kvm)
>  	return dist->has_its;
>  }
>  
> +bool vgic_supports_direct_msis(struct kvm *kvm)
> +{
> +	return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
> +}
> +
>  static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
>  					    gpa_t addr, unsigned int len)
>  {
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index 31b70326b966..e67ccb6a6250 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -240,4 +240,6 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
>  			 u32 devid, u32 eventid, struct vgic_irq **irq);
>  struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
>  
> +bool vgic_supports_direct_msis(struct kvm *kvm);
> +
>  #endif
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 08/26] KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 15:46     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 15:46 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:43PM +0100, Marc Zyngier wrote:
> In order to control the GICv4 view of virtual CPUs, we rely
> on an irqdomain allocated for that purpose. Let's add a couple
> of helpers to that effect.
> 
> At the same time, the vgic data structures gain new fields to
> track all this... erm... wonderful stuff.
> 
> The way we hook into the vgic init is slightly convoluted. We
> need the vgic to be initialized (in order to guarantee that
> the number of vcpus is now fixed), and we must have a vITS
> (otherwise this is all very pointless). So we end-up calling
> the init from both vgic_init and vgic_its_create.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/kvm/Makefile         |  1 +
>  arch/arm64/kvm/Makefile       |  1 +
>  include/kvm/arm_vgic.h        | 19 ++++++++++
>  virt/kvm/arm/vgic/vgic-init.c |  9 +++++
>  virt/kvm/arm/vgic/vgic-its.c  |  8 +++++
>  virt/kvm/arm/vgic/vgic-v4.c   | 83 +++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |  2 ++
>  7 files changed, 123 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v4.c
> 
> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> index d9beee652d36..0a1dd2cdb928 100644
> --- a/arch/arm/kvm/Makefile
> +++ b/arch/arm/kvm/Makefile
> @@ -31,6 +31,7 @@ obj-y += $(KVM)/arm/vgic/vgic-init.o
>  obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
>  obj-y += $(KVM)/arm/vgic/vgic-v2.o
>  obj-y += $(KVM)/arm/vgic/vgic-v3.o
> +obj-y += $(KVM)/arm/vgic/vgic-v4.o
>  obj-y += $(KVM)/arm/vgic/vgic-mmio.o
>  obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
>  obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index 5d9810086c25..c30fd388ef80 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -26,6 +26,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
> +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v4.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index ba9fb450aa1b..7eeb6c2a2f9c 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -26,6 +26,8 @@
>  #include <linux/list.h>
>  #include <linux/jump_label.h>
>  
> +#include <linux/irqchip/arm-gic-v4.h>
> +
>  #define VGIC_V3_MAX_CPUS	255
>  #define VGIC_V2_MAX_CPUS	8
>  #define VGIC_NR_IRQS_LEGACY     256
> @@ -236,6 +238,15 @@ struct vgic_dist {
>  
>  	/* used by vgic-debug */
>  	struct vgic_state_iter *iter;
> +
> +	/*
> +	 * GICv4 ITS per-VM data, containing the IRQ domain, the VPE
> +	 * array, the property table pointer as well as allocation
> +	 * data. This essentially ties the Linux IRQ core and ITS
> +	 * together, and avoids leaking KVM's data structures anywhere
> +	 * else.
> +	 */
> +	struct its_vm		its_vm;
>  };
>  
>  struct vgic_v2_cpu_if {
> @@ -254,6 +265,14 @@ struct vgic_v3_cpu_if {
>  	u32		vgic_ap0r[4];
>  	u32		vgic_ap1r[4];
>  	u64		vgic_lr[VGIC_V3_MAX_LRS];
> +
> +	/*
> +	 * GICv4 ITS per-VPE data, containing the doorbell IRQ, the
> +	 * pending table pointer, the its_vm pointer and a few other
> +	 * HW specific things. As for the its_vm structure, this is
> +	 * linking the Linux IRQ subsystem and the ITS together.
> +	 */
> +	struct its_vpe	its_vpe;
>  };
>  
>  struct vgic_cpu {
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 5801261f3add..c2749387615b 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -285,6 +285,12 @@ int vgic_init(struct kvm *kvm)
>  	if (ret)
>  		goto out;
>  
> +	if (vgic_has_its(kvm) && vgic_supports_direct_msis(kvm)) {

vgic_supports_direct_msis() already checks vgic_has_its(), so you can
drop that check here.

> +		ret = vgic_v4_init(kvm);
> +		if (ret)
> +			goto out;
> +	}
> +
>  	kvm_for_each_vcpu(i, vcpu, kvm)
>  		kvm_vgic_vcpu_enable(vcpu);
>  
> @@ -320,6 +326,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
>  
>  	kfree(dist->spis);
>  	dist->nr_spis = 0;
> +
> +	if (vgic_supports_direct_msis(kvm))
> +		vgic_v4_teardown(kvm);
>  }
>  
>  void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 8ee03f1e89fc..89768d2b6a91 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1603,6 +1603,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
>  	if (!its)
>  		return -ENOMEM;
>  
> +	if (vgic_initialized(dev->kvm)) {
> +		int ret = vgic_v4_init(dev->kvm);
> +		if (ret) {
> +			kfree(its);
> +			return ret;
> +		}
> +	}
> +	
>  	mutex_init(&its->its_lock);
>  	mutex_init(&its->cmd_lock);
>  
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> new file mode 100644
> index 000000000000..c794f0cef09e
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -0,0 +1,83 @@
> +/*
> + * Copyright (C) 2017 ARM Ltd.
> + * Author: Marc Zyngier <marc.zyngier@arm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +/**
> + * vgic_v4_init - Initialize the GICv4 data structures
> + * @kvm:	Pointer to the VM being initialized
> + *
> + * We may be called each time a vITS is created, or when the
> + * vgic is initialized. This relies on kvm->lock to be
> + * held. In both cases, the number of vcpus should now be
> + * fixed.
> + */
> +int vgic_v4_init(struct kvm *kvm)
> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct kvm_vcpu *vcpu;
> +	int i, nr_vcpus, ret;
> +
> +	if (dist->its_vm.vpes)
> +		return 0;
> +
> +	nr_vcpus = atomic_read(&kvm->online_vcpus);
> +
> +	dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
> +				    GFP_KERNEL);
> +	if (!dist->its_vm.vpes)
> +		return -ENOMEM;
> +
> +	dist->its_vm.nr_vpes = nr_vcpus;
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		dist->its_vm.vpes[i] = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
> +
> +	ret = its_alloc_vcpu_irqs(&dist->its_vm);
> +	if (ret < 0) {
> +		kvm_err("VPE IRQ allocation failure\n");
> +		kfree(dist->its_vm.vpes);
> +		dist->its_vm.nr_vpes = 0;
> +		dist->its_vm.vpes = NULL;
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * vgic_v4_teardown - Free the GICv4 data structures
> + * @kvm:	Pointer to the VM being destroyed
> + *
> + * Relies on kvm->lock to be held.
> + */
> +void vgic_v4_teardown(struct kvm *kvm)
> +{
> +	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
> +
> +	if (!its_vm->vpes)
> +		return;
> +
> +	its_free_vcpu_irqs(its_vm);
> +	kfree(its_vm->vpes);
> +	its_vm->nr_vpes = 0;
> +	its_vm->vpes = NULL;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index e67ccb6a6250..c4105f613f57 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -241,5 +241,7 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
>  struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
>  
>  bool vgic_supports_direct_msis(struct kvm *kvm);
> +int vgic_v4_init(struct kvm *kvm);
> +void vgic_v4_teardown(struct kvm *kvm);
>  
>  #endif
> -- 
> 2.14.1
> 
Otherwise:

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

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

* [PATCH v4 08/26] KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain
@ 2017-10-25 15:46     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 15:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:43PM +0100, Marc Zyngier wrote:
> In order to control the GICv4 view of virtual CPUs, we rely
> on an irqdomain allocated for that purpose. Let's add a couple
> of helpers to that effect.
> 
> At the same time, the vgic data structures gain new fields to
> track all this... erm... wonderful stuff.
> 
> The way we hook into the vgic init is slightly convoluted. We
> need the vgic to be initialized (in order to guarantee that
> the number of vcpus is now fixed), and we must have a vITS
> (otherwise this is all very pointless). So we end-up calling
> the init from both vgic_init and vgic_its_create.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm/kvm/Makefile         |  1 +
>  arch/arm64/kvm/Makefile       |  1 +
>  include/kvm/arm_vgic.h        | 19 ++++++++++
>  virt/kvm/arm/vgic/vgic-init.c |  9 +++++
>  virt/kvm/arm/vgic/vgic-its.c  |  8 +++++
>  virt/kvm/arm/vgic/vgic-v4.c   | 83 +++++++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.h      |  2 ++
>  7 files changed, 123 insertions(+)
>  create mode 100644 virt/kvm/arm/vgic/vgic-v4.c
> 
> diff --git a/arch/arm/kvm/Makefile b/arch/arm/kvm/Makefile
> index d9beee652d36..0a1dd2cdb928 100644
> --- a/arch/arm/kvm/Makefile
> +++ b/arch/arm/kvm/Makefile
> @@ -31,6 +31,7 @@ obj-y += $(KVM)/arm/vgic/vgic-init.o
>  obj-y += $(KVM)/arm/vgic/vgic-irqfd.o
>  obj-y += $(KVM)/arm/vgic/vgic-v2.o
>  obj-y += $(KVM)/arm/vgic/vgic-v3.o
> +obj-y += $(KVM)/arm/vgic/vgic-v4.o
>  obj-y += $(KVM)/arm/vgic/vgic-mmio.o
>  obj-y += $(KVM)/arm/vgic/vgic-mmio-v2.o
>  obj-y += $(KVM)/arm/vgic/vgic-mmio-v3.o
> diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
> index 5d9810086c25..c30fd388ef80 100644
> --- a/arch/arm64/kvm/Makefile
> +++ b/arch/arm64/kvm/Makefile
> @@ -26,6 +26,7 @@ kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-init.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-irqfd.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v2.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v3.o
> +kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-v4.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v2.o
>  kvm-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/vgic/vgic-mmio-v3.o
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index ba9fb450aa1b..7eeb6c2a2f9c 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -26,6 +26,8 @@
>  #include <linux/list.h>
>  #include <linux/jump_label.h>
>  
> +#include <linux/irqchip/arm-gic-v4.h>
> +
>  #define VGIC_V3_MAX_CPUS	255
>  #define VGIC_V2_MAX_CPUS	8
>  #define VGIC_NR_IRQS_LEGACY     256
> @@ -236,6 +238,15 @@ struct vgic_dist {
>  
>  	/* used by vgic-debug */
>  	struct vgic_state_iter *iter;
> +
> +	/*
> +	 * GICv4 ITS per-VM data, containing the IRQ domain, the VPE
> +	 * array, the property table pointer as well as allocation
> +	 * data. This essentially ties the Linux IRQ core and ITS
> +	 * together, and avoids leaking KVM's data structures anywhere
> +	 * else.
> +	 */
> +	struct its_vm		its_vm;
>  };
>  
>  struct vgic_v2_cpu_if {
> @@ -254,6 +265,14 @@ struct vgic_v3_cpu_if {
>  	u32		vgic_ap0r[4];
>  	u32		vgic_ap1r[4];
>  	u64		vgic_lr[VGIC_V3_MAX_LRS];
> +
> +	/*
> +	 * GICv4 ITS per-VPE data, containing the doorbell IRQ, the
> +	 * pending table pointer, the its_vm pointer and a few other
> +	 * HW specific things. As for the its_vm structure, this is
> +	 * linking the Linux IRQ subsystem and the ITS together.
> +	 */
> +	struct its_vpe	its_vpe;
>  };
>  
>  struct vgic_cpu {
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index 5801261f3add..c2749387615b 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -285,6 +285,12 @@ int vgic_init(struct kvm *kvm)
>  	if (ret)
>  		goto out;
>  
> +	if (vgic_has_its(kvm) && vgic_supports_direct_msis(kvm)) {

vgic_supports_direct_msis() already checks vgic_has_its(), so you can
drop that check here.

> +		ret = vgic_v4_init(kvm);
> +		if (ret)
> +			goto out;
> +	}
> +
>  	kvm_for_each_vcpu(i, vcpu, kvm)
>  		kvm_vgic_vcpu_enable(vcpu);
>  
> @@ -320,6 +326,9 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
>  
>  	kfree(dist->spis);
>  	dist->nr_spis = 0;
> +
> +	if (vgic_supports_direct_msis(kvm))
> +		vgic_v4_teardown(kvm);
>  }
>  
>  void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu)
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 8ee03f1e89fc..89768d2b6a91 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1603,6 +1603,14 @@ static int vgic_its_create(struct kvm_device *dev, u32 type)
>  	if (!its)
>  		return -ENOMEM;
>  
> +	if (vgic_initialized(dev->kvm)) {
> +		int ret = vgic_v4_init(dev->kvm);
> +		if (ret) {
> +			kfree(its);
> +			return ret;
> +		}
> +	}
> +	
>  	mutex_init(&its->its_lock);
>  	mutex_init(&its->cmd_lock);
>  
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> new file mode 100644
> index 000000000000..c794f0cef09e
> --- /dev/null
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -0,0 +1,83 @@
> +/*
> + * Copyright (C) 2017 ARM Ltd.
> + * Author: Marc Zyngier <marc.zyngier@arm.com>
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + * You should have received a copy of the GNU General Public License
> + * along with this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include <linux/interrupt.h>
> +#include <linux/irqdomain.h>
> +#include <linux/kvm_host.h>
> +
> +#include "vgic.h"
> +
> +/**
> + * vgic_v4_init - Initialize the GICv4 data structures
> + * @kvm:	Pointer to the VM being initialized
> + *
> + * We may be called each time a vITS is created, or when the
> + * vgic is initialized. This relies on kvm->lock to be
> + * held. In both cases, the number of vcpus should now be
> + * fixed.
> + */
> +int vgic_v4_init(struct kvm *kvm)
> +{
> +	struct vgic_dist *dist = &kvm->arch.vgic;
> +	struct kvm_vcpu *vcpu;
> +	int i, nr_vcpus, ret;
> +
> +	if (dist->its_vm.vpes)
> +		return 0;
> +
> +	nr_vcpus = atomic_read(&kvm->online_vcpus);
> +
> +	dist->its_vm.vpes = kzalloc(sizeof(*dist->its_vm.vpes) * nr_vcpus,
> +				    GFP_KERNEL);
> +	if (!dist->its_vm.vpes)
> +		return -ENOMEM;
> +
> +	dist->its_vm.nr_vpes = nr_vcpus;
> +
> +	kvm_for_each_vcpu(i, vcpu, kvm)
> +		dist->its_vm.vpes[i] = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
> +
> +	ret = its_alloc_vcpu_irqs(&dist->its_vm);
> +	if (ret < 0) {
> +		kvm_err("VPE IRQ allocation failure\n");
> +		kfree(dist->its_vm.vpes);
> +		dist->its_vm.nr_vpes = 0;
> +		dist->its_vm.vpes = NULL;
> +		return ret;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * vgic_v4_teardown - Free the GICv4 data structures
> + * @kvm:	Pointer to the VM being destroyed
> + *
> + * Relies on kvm->lock to be held.
> + */
> +void vgic_v4_teardown(struct kvm *kvm)
> +{
> +	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
> +
> +	if (!its_vm->vpes)
> +		return;
> +
> +	its_free_vcpu_irqs(its_vm);
> +	kfree(its_vm->vpes);
> +	its_vm->nr_vpes = 0;
> +	its_vm->vpes = NULL;
> +}
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index e67ccb6a6250..c4105f613f57 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -241,5 +241,7 @@ int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
>  struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
>  
>  bool vgic_supports_direct_msis(struct kvm *kvm);
> +int vgic_v4_init(struct kvm *kvm);
> +void vgic_v4_teardown(struct kvm *kvm);
>  
>  #endif
> -- 
> 2.14.1
> 
Otherwise:

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

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

* Re: [PATCH v4 09/26] KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 15:58     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 15:58 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Mark Rutland, Shameerali Kolothum Thodi,
	Andre Przywara

On Fri, Oct 06, 2017 at 04:33:44PM +0100, Marc Zyngier wrote:
> Let's use the irq bypass mechanism introduced for platform device
> interrupts to intercept the virtual PCIe endpoint configuration
> and establish our LPI->VLPI mapping.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  include/kvm/arm_vgic.h      |   8 ++++
>  virt/kvm/arm/arm.c          |   6 ++-
>  virt/kvm/arm/vgic/vgic-v4.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 116 insertions(+), 2 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 7eeb6c2a2f9c..2f750c770bf2 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -373,4 +373,12 @@ int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
>  
>  int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner);
>  
> +struct kvm_kernel_irq_routing_entry;
> +
> +int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq,
> +			       struct kvm_kernel_irq_routing_entry *irq_entry);
> +
> +int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
> +				 struct kvm_kernel_irq_routing_entry *irq_entry);
> +
>  #endif /* __KVM_ARM_VGIC_H */
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index 5d5218ecd547..8388c1cc23f6 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -1462,7 +1462,8 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
>  	struct kvm_kernel_irqfd *irqfd =
>  		container_of(cons, struct kvm_kernel_irqfd, consumer);
>  
> -	return 0;
> +	return kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
> +					  &irqfd->irq_entry);
>  }
>  void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
>  				      struct irq_bypass_producer *prod)
> @@ -1470,7 +1471,8 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
>  	struct kvm_kernel_irqfd *irqfd =
>  		container_of(cons, struct kvm_kernel_irqfd, consumer);
>  
> -	return;
> +	kvm_vgic_v4_unset_forwarding(irqfd->kvm, prod->irq,
> +				     &irqfd->irq_entry);
>  }
>  
>  void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons)
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index c794f0cef09e..ba1dd3162eba 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -81,3 +81,107 @@ void vgic_v4_teardown(struct kvm *kvm)
>  	its_vm->nr_vpes = 0;
>  	its_vm->vpes = NULL;
>  }
> +
> +static struct vgic_its *vgic_get_its(struct kvm *kvm,
> +				     struct kvm_kernel_irq_routing_entry *irq_entry)
> +{
> +	struct kvm_msi msi  = (struct kvm_msi) {
> +		.address_lo	= irq_entry->msi.address_lo,
> +		.address_hi	= irq_entry->msi.address_hi,
> +		.data		= irq_entry->msi.data,
> +		.flags		= irq_entry->msi.flags,
> +		.devid		= irq_entry->msi.devid,
> +	};
> +
> +	/*
> +	 * Get a reference on the LPI. If NULL, this is not a valid
> +	 * translation for any of our vITSs.
> +	 */
> +	return vgic_msi_to_its(kvm, &msi);
> +}
> +
> +int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
> +			       struct kvm_kernel_irq_routing_entry *irq_entry)
> +{
> +	struct vgic_its *its;
> +	struct vgic_irq *irq;
> +	struct its_vlpi_map map;
> +	int ret;
> +
> +	if (!vgic_supports_direct_msis(kvm))
> +		return 0;
> +
> +	/*
> +	 * Get the ITS, and escape early on error (not a valid
> +	 * doorbell for any of our vITSs).
> +	 */
> +	its = vgic_get_its(kvm, irq_entry);
> +	if (IS_ERR(its))
> +		return 0;
> +
> +	mutex_lock(&its->its_lock);
> +
> +	/* Perform then actual DevID/EventID -> LPI translation. */
> +	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
> +				   irq_entry->msi.data, &irq);
> +	if (ret)
> +		goto out;
> +
> +	/*
> +	 * Emit the mapping request. If it fails, the ITS probably
> +	 * isn't v4 compatible, so let's silently bail out. Holding
> +	 * the ITS lock should ensure that nothing can modify the
> +	 * target vcpu.
> +	 */
> +	map = (struct its_vlpi_map) {
> +		.vm		= &kvm->arch.vgic.its_vm,
> +		.vpe		= &irq->target_vcpu->arch.vgic_cpu.vgic_v3.its_vpe,
> +		.vintid		= irq->intid,
> +		.db_enabled	= true,
> +	};
> +
> +	ret = its_map_vlpi(virq, &map);
> +	if (ret)
> +		goto out;
> +
> +	irq->hw		= true;
> +	irq->host_irq	= virq;
> +
> +out:
> +	mutex_unlock(&its->its_lock);
> +	return ret;
> +}
> +
> +int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq,
> +				 struct kvm_kernel_irq_routing_entry *irq_entry)
> +{
> +	struct vgic_its *its;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	if (!vgic_supports_direct_msis(kvm))
> +		return 0;
> +
> +	/*
> +	 * Get the ITS, and escape early on error (not a valid
> +	 * doorbell for any of our vITSs).
> +	 */
> +	its = vgic_get_its(kvm, irq_entry);
> +	if (IS_ERR(its))
> +		return 0;
> +
> +	mutex_lock(&its->its_lock);
> +
> +	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
> +				   irq_entry->msi.data, &irq);
> +	if (ret)
> +		goto out;
> +
> +	WARN_ON(!(irq->hw && irq->host_irq == virq));
> +	irq->hw = false;
> +	ret = its_unmap_vlpi(virq);
> +
> +out:
> +	mutex_unlock(&its->its_lock);
> +	return ret;
> +}
> -- 
> 2.14.1
> 

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

* [PATCH v4 09/26] KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass
@ 2017-10-25 15:58     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:44PM +0100, Marc Zyngier wrote:
> Let's use the irq bypass mechanism introduced for platform device
> interrupts to intercept the virtual PCIe endpoint configuration
> and establish our LPI->VLPI mapping.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  include/kvm/arm_vgic.h      |   8 ++++
>  virt/kvm/arm/arm.c          |   6 ++-
>  virt/kvm/arm/vgic/vgic-v4.c | 104 ++++++++++++++++++++++++++++++++++++++++++++
>  3 files changed, 116 insertions(+), 2 deletions(-)
> 
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 7eeb6c2a2f9c..2f750c770bf2 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -373,4 +373,12 @@ int kvm_vgic_setup_default_irq_routing(struct kvm *kvm);
>  
>  int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner);
>  
> +struct kvm_kernel_irq_routing_entry;
> +
> +int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int irq,
> +			       struct kvm_kernel_irq_routing_entry *irq_entry);
> +
> +int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int irq,
> +				 struct kvm_kernel_irq_routing_entry *irq_entry);
> +
>  #endif /* __KVM_ARM_VGIC_H */
> diff --git a/virt/kvm/arm/arm.c b/virt/kvm/arm/arm.c
> index 5d5218ecd547..8388c1cc23f6 100644
> --- a/virt/kvm/arm/arm.c
> +++ b/virt/kvm/arm/arm.c
> @@ -1462,7 +1462,8 @@ int kvm_arch_irq_bypass_add_producer(struct irq_bypass_consumer *cons,
>  	struct kvm_kernel_irqfd *irqfd =
>  		container_of(cons, struct kvm_kernel_irqfd, consumer);
>  
> -	return 0;
> +	return kvm_vgic_v4_set_forwarding(irqfd->kvm, prod->irq,
> +					  &irqfd->irq_entry);
>  }
>  void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
>  				      struct irq_bypass_producer *prod)
> @@ -1470,7 +1471,8 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
>  	struct kvm_kernel_irqfd *irqfd =
>  		container_of(cons, struct kvm_kernel_irqfd, consumer);
>  
> -	return;
> +	kvm_vgic_v4_unset_forwarding(irqfd->kvm, prod->irq,
> +				     &irqfd->irq_entry);
>  }
>  
>  void kvm_arch_irq_bypass_stop(struct irq_bypass_consumer *cons)
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index c794f0cef09e..ba1dd3162eba 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -81,3 +81,107 @@ void vgic_v4_teardown(struct kvm *kvm)
>  	its_vm->nr_vpes = 0;
>  	its_vm->vpes = NULL;
>  }
> +
> +static struct vgic_its *vgic_get_its(struct kvm *kvm,
> +				     struct kvm_kernel_irq_routing_entry *irq_entry)
> +{
> +	struct kvm_msi msi  = (struct kvm_msi) {
> +		.address_lo	= irq_entry->msi.address_lo,
> +		.address_hi	= irq_entry->msi.address_hi,
> +		.data		= irq_entry->msi.data,
> +		.flags		= irq_entry->msi.flags,
> +		.devid		= irq_entry->msi.devid,
> +	};
> +
> +	/*
> +	 * Get a reference on the LPI. If NULL, this is not a valid
> +	 * translation for any of our vITSs.
> +	 */
> +	return vgic_msi_to_its(kvm, &msi);
> +}
> +
> +int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
> +			       struct kvm_kernel_irq_routing_entry *irq_entry)
> +{
> +	struct vgic_its *its;
> +	struct vgic_irq *irq;
> +	struct its_vlpi_map map;
> +	int ret;
> +
> +	if (!vgic_supports_direct_msis(kvm))
> +		return 0;
> +
> +	/*
> +	 * Get the ITS, and escape early on error (not a valid
> +	 * doorbell for any of our vITSs).
> +	 */
> +	its = vgic_get_its(kvm, irq_entry);
> +	if (IS_ERR(its))
> +		return 0;
> +
> +	mutex_lock(&its->its_lock);
> +
> +	/* Perform then actual DevID/EventID -> LPI translation. */
> +	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
> +				   irq_entry->msi.data, &irq);
> +	if (ret)
> +		goto out;
> +
> +	/*
> +	 * Emit the mapping request. If it fails, the ITS probably
> +	 * isn't v4 compatible, so let's silently bail out. Holding
> +	 * the ITS lock should ensure that nothing can modify the
> +	 * target vcpu.
> +	 */
> +	map = (struct its_vlpi_map) {
> +		.vm		= &kvm->arch.vgic.its_vm,
> +		.vpe		= &irq->target_vcpu->arch.vgic_cpu.vgic_v3.its_vpe,
> +		.vintid		= irq->intid,
> +		.db_enabled	= true,
> +	};
> +
> +	ret = its_map_vlpi(virq, &map);
> +	if (ret)
> +		goto out;
> +
> +	irq->hw		= true;
> +	irq->host_irq	= virq;
> +
> +out:
> +	mutex_unlock(&its->its_lock);
> +	return ret;
> +}
> +
> +int kvm_vgic_v4_unset_forwarding(struct kvm *kvm, int virq,
> +				 struct kvm_kernel_irq_routing_entry *irq_entry)
> +{
> +	struct vgic_its *its;
> +	struct vgic_irq *irq;
> +	int ret;
> +
> +	if (!vgic_supports_direct_msis(kvm))
> +		return 0;
> +
> +	/*
> +	 * Get the ITS, and escape early on error (not a valid
> +	 * doorbell for any of our vITSs).
> +	 */
> +	its = vgic_get_its(kvm, irq_entry);
> +	if (IS_ERR(its))
> +		return 0;
> +
> +	mutex_lock(&its->its_lock);
> +
> +	ret = vgic_its_resolve_lpi(kvm, its, irq_entry->msi.devid,
> +				   irq_entry->msi.data, &irq);
> +	if (ret)
> +		goto out;
> +
> +	WARN_ON(!(irq->hw && irq->host_irq == virq));
> +	irq->hw = false;
> +	ret = its_unmap_vlpi(virq);
> +
> +out:
> +	mutex_unlock(&its->its_lock);
> +	return ret;
> +}
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 12/26] KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 16:22     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 16:22 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:47PM +0100, Marc Zyngier wrote:
> When the guest issues an affinity change, we need to tell the physical
> ITS that we're now targetting a new vcpu.  This is done by extracting
> the current mapping, updating the target, and reapplying the mapping.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-its.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index c9b1c0967426..42ffb9084bb7 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -337,11 +337,25 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
>  
>  static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
>  {
> +	int ret = 0;
> +
>  	spin_lock(&irq->irq_lock);
>  	irq->target_vcpu = vcpu;
>  	spin_unlock(&irq->irq_lock);
>  
> -	return 0;
> +	if (irq->hw) {
> +		struct its_vlpi_map map;
> +
> +		ret = its_get_vlpi(irq->host_irq, &map);
> +		if (ret)
> +			return ret;
> +
> +		map.vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
> +
> +		ret = its_map_vlpi(irq->host_irq, &map);
> +	}
> +
> +	return ret;
>  }
>  
>  /*
> -- 
> 2.14.1
> 

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

* [PATCH v4 12/26] KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS
@ 2017-10-25 16:22     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 16:22 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:47PM +0100, Marc Zyngier wrote:
> When the guest issues an affinity change, we need to tell the physical
> ITS that we're now targetting a new vcpu.  This is done by extracting
> the current mapping, updating the target, and reapplying the mapping.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-its.c | 16 +++++++++++++++-
>  1 file changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index c9b1c0967426..42ffb9084bb7 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -337,11 +337,25 @@ static int vgic_copy_lpi_list(struct kvm_vcpu *vcpu, u32 **intid_ptr)
>  
>  static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
>  {
> +	int ret = 0;
> +
>  	spin_lock(&irq->irq_lock);
>  	irq->target_vcpu = vcpu;
>  	spin_unlock(&irq->irq_lock);
>  
> -	return 0;
> +	if (irq->hw) {
> +		struct its_vlpi_map map;
> +
> +		ret = its_get_vlpi(irq->host_irq, &map);
> +		if (ret)
> +			return ret;
> +
> +		map.vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
> +
> +		ret = its_map_vlpi(irq->host_irq, &map);
> +	}
> +
> +	return ret;
>  }
>  
>  /*
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 14/26] KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 16:27     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 16:27 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:49PM +0100, Marc Zyngier wrote:
> The current implementation of MOVALL doesn't allow us to call
> into the core ITS code as we hold a number of spinlocks.
> 
> Let's try a method used in other parts of the code, were we copy
> the intids of the candicate interrupts, and then do whatever
> we need to do with them outside of the critical section.
> 
> This allows us to move the interrupts one by one, at the expense
> of a bit of CPU time. Who cares? MOVALL is such a stupid command
> anyway...
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-its.c | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 5778b50911e8..0b7e648e7a0c 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1148,11 +1148,12 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
>  static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
>  				      u64 *its_cmd)
>  {
> -	struct vgic_dist *dist = &kvm->arch.vgic;
>  	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
>  	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
>  	struct kvm_vcpu *vcpu1, *vcpu2;
>  	struct vgic_irq *irq;
> +	u32 *intids;
> +	int irq_count, i;
>  
>  	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
>  	    target2_addr >= atomic_read(&kvm->online_vcpus))
> @@ -1164,19 +1165,19 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
>  	vcpu1 = kvm_get_vcpu(kvm, target1_addr);
>  	vcpu2 = kvm_get_vcpu(kvm, target2_addr);
>  
> -	spin_lock(&dist->lpi_list_lock);
> +	irq_count = vgic_copy_lpi_list(vcpu1, &intids);
> +	if (irq_count < 0)
> +		return irq_count;
>  
> -	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
> -		spin_lock(&irq->irq_lock);
> +	for (i = 0; i < irq_count; i++) {
> +		irq = vgic_get_irq(kvm, NULL, intids[i]);
>  
> -		if (irq->target_vcpu == vcpu1)
> -			irq->target_vcpu = vcpu2;
> +		update_affinity(irq, vcpu2);
>  
> -		spin_unlock(&irq->irq_lock);
> +		vgic_put_irq(kvm, irq);
>  	}
>  
> -	spin_unlock(&dist->lpi_list_lock);
> -
> +	kfree(intids);
>  	return 0;
>  }
>  
> -- 
> 2.14.1
> 

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

* [PATCH v4 14/26] KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE
@ 2017-10-25 16:27     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 16:27 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:49PM +0100, Marc Zyngier wrote:
> The current implementation of MOVALL doesn't allow us to call
> into the core ITS code as we hold a number of spinlocks.
> 
> Let's try a method used in other parts of the code, were we copy
> the intids of the candicate interrupts, and then do whatever
> we need to do with them outside of the critical section.
> 
> This allows us to move the interrupts one by one, at the expense
> of a bit of CPU time. Who cares? MOVALL is such a stupid command
> anyway...
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-its.c | 19 ++++++++++---------
>  1 file changed, 10 insertions(+), 9 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index 5778b50911e8..0b7e648e7a0c 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1148,11 +1148,12 @@ static int vgic_its_cmd_handle_invall(struct kvm *kvm, struct vgic_its *its,
>  static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
>  				      u64 *its_cmd)
>  {
> -	struct vgic_dist *dist = &kvm->arch.vgic;
>  	u32 target1_addr = its_cmd_get_target_addr(its_cmd);
>  	u32 target2_addr = its_cmd_mask_field(its_cmd, 3, 16, 32);
>  	struct kvm_vcpu *vcpu1, *vcpu2;
>  	struct vgic_irq *irq;
> +	u32 *intids;
> +	int irq_count, i;
>  
>  	if (target1_addr >= atomic_read(&kvm->online_vcpus) ||
>  	    target2_addr >= atomic_read(&kvm->online_vcpus))
> @@ -1164,19 +1165,19 @@ static int vgic_its_cmd_handle_movall(struct kvm *kvm, struct vgic_its *its,
>  	vcpu1 = kvm_get_vcpu(kvm, target1_addr);
>  	vcpu2 = kvm_get_vcpu(kvm, target2_addr);
>  
> -	spin_lock(&dist->lpi_list_lock);
> +	irq_count = vgic_copy_lpi_list(vcpu1, &intids);
> +	if (irq_count < 0)
> +		return irq_count;
>  
> -	list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
> -		spin_lock(&irq->irq_lock);
> +	for (i = 0; i < irq_count; i++) {
> +		irq = vgic_get_irq(kvm, NULL, intids[i]);
>  
> -		if (irq->target_vcpu == vcpu1)
> -			irq->target_vcpu = vcpu2;
> +		update_affinity(irq, vcpu2);
>  
> -		spin_unlock(&irq->irq_lock);
> +		vgic_put_irq(kvm, irq);
>  	}
>  
> -	spin_unlock(&dist->lpi_list_lock);
> -
> +	kfree(intids);
>  	return 0;
>  }
>  
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-25 16:48     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 16:48 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvmarm, kvm, Andre Przywara

On Fri, Oct 06, 2017 at 04:33:52PM +0100, Marc Zyngier wrote:
> When the VLPI gets mapped, it must inherit the configuration of
> the LPI configured at the vITS level. For that purpose, let's make
> update_lpi_config globally available and call it just after
> having performed the VLPI map operation.
> 
> Acked-by: Christoffer Dall <cdall@linaro.org>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 6 ++----
>  virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
>  virt/kvm/arm/vgic/vgic.h     | 2 ++
>  3 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index eb72eb027060..f434748439ee 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -37,8 +37,6 @@
>  static int vgic_its_save_tables_v0(struct vgic_its *its);
>  static int vgic_its_restore_tables_v0(struct vgic_its *its);
>  static int vgic_its_commit_v0(struct vgic_its *its);
> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
>  
>  /*
>   * Creates a new (reference to a) struct vgic_irq for a given LPI.
> @@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
>   * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
>   * VCPU. Unconditionally applies if filter_vcpu is NULL.
>   */
> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
>  {
>  	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
>  	u8 prop;
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index ba1dd3162eba..b79a0450bb1c 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
>  	irq->hw		= true;
>  	irq->host_irq	= virq;
>  
> +	/* Force the property update and invalidate */
> +	update_lpi_config(kvm, irq, NULL, true);

Actually, when re-reading this patch, this looks weird to me.

I think this needs to either be done as part of the map, or before the
map, to prevent for example a disabled interrupt from the guest'ss PoV
to fire when it doesn't expect it.

Thanks,
-Christoffer

>  out:
>  	mutex_unlock(&its->its_lock);
>  	return ret;
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c4105f613f57..1bd2e28ac097 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -239,6 +239,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
>  int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
>  			 u32 devid, u32 eventid, struct vgic_irq **irq);
>  struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv);
>  
>  bool vgic_supports_direct_msis(struct kvm *kvm);
>  int vgic_v4_init(struct kvm *kvm);
> -- 
> 2.14.1
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
@ 2017-10-25 16:48     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-25 16:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:52PM +0100, Marc Zyngier wrote:
> When the VLPI gets mapped, it must inherit the configuration of
> the LPI configured at the vITS level. For that purpose, let's make
> update_lpi_config globally available and call it just after
> having performed the VLPI map operation.
> 
> Acked-by: Christoffer Dall <cdall@linaro.org>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 6 ++----
>  virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
>  virt/kvm/arm/vgic/vgic.h     | 2 ++
>  3 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index eb72eb027060..f434748439ee 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -37,8 +37,6 @@
>  static int vgic_its_save_tables_v0(struct vgic_its *its);
>  static int vgic_its_restore_tables_v0(struct vgic_its *its);
>  static int vgic_its_commit_v0(struct vgic_its *its);
> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
>  
>  /*
>   * Creates a new (reference to a) struct vgic_irq for a given LPI.
> @@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
>   * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
>   * VCPU. Unconditionally applies if filter_vcpu is NULL.
>   */
> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
>  {
>  	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
>  	u8 prop;
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index ba1dd3162eba..b79a0450bb1c 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
>  	irq->hw		= true;
>  	irq->host_irq	= virq;
>  
> +	/* Force the property update and invalidate */
> +	update_lpi_config(kvm, irq, NULL, true);

Actually, when re-reading this patch, this looks weird to me.

I think this needs to either be done as part of the map, or before the
map, to prevent for example a disabled interrupt from the guest'ss PoV
to fire when it doesn't expect it.

Thanks,
-Christoffer

>  out:
>  	mutex_unlock(&its->its_lock);
>  	return ret;
> diff --git a/virt/kvm/arm/vgic/vgic.h b/virt/kvm/arm/vgic/vgic.h
> index c4105f613f57..1bd2e28ac097 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -239,6 +239,8 @@ static inline int vgic_v3_max_apr_idx(struct kvm_vcpu *vcpu)
>  int vgic_its_resolve_lpi(struct kvm *kvm, struct vgic_its *its,
>  			 u32 devid, u32 eventid, struct vgic_irq **irq);
>  struct vgic_its *vgic_msi_to_its(struct kvm *kvm, struct kvm_msi *msi);
> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv);
>  
>  bool vgic_supports_direct_msis(struct kvm *kvm);
>  int vgic_v4_init(struct kvm *kvm);
> -- 
> 2.14.1
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  2017-10-25 16:48     ` Christoffer Dall
@ 2017-10-25 17:01       ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-25 17:01 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: linux-arm-kernel, kvmarm, kvm, Andre Przywara

On Wed, Oct 25 2017 at  6:48:27 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> On Fri, Oct 06, 2017 at 04:33:52PM +0100, Marc Zyngier wrote:
>> When the VLPI gets mapped, it must inherit the configuration of
>> the LPI configured at the vITS level. For that purpose, let's make
>> update_lpi_config globally available and call it just after
>> having performed the VLPI map operation.
>> 
>> Acked-by: Christoffer Dall <cdall@linaro.org>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 6 ++----
>>  virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
>>  virt/kvm/arm/vgic/vgic.h     | 2 ++
>>  3 files changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index eb72eb027060..f434748439ee 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -37,8 +37,6 @@
>>  static int vgic_its_save_tables_v0(struct vgic_its *its);
>>  static int vgic_its_restore_tables_v0(struct vgic_its *its);
>>  static int vgic_its_commit_v0(struct vgic_its *its);
>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
>>  
>>  /*
>>   * Creates a new (reference to a) struct vgic_irq for a given LPI.
>> @@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
>>   * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
>>   * VCPU. Unconditionally applies if filter_vcpu is NULL.
>>   */
>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
>> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
>>  {
>>  	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
>>  	u8 prop;
>> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
>> index ba1dd3162eba..b79a0450bb1c 100644
>> --- a/virt/kvm/arm/vgic/vgic-v4.c
>> +++ b/virt/kvm/arm/vgic/vgic-v4.c
>> @@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
>>  	irq->hw		= true;
>>  	irq->host_irq	= virq;
>>  
>> +	/* Force the property update and invalidate */
>> +	update_lpi_config(kvm, irq, NULL, true);
>
> Actually, when re-reading this patch, this looks weird to me.
>
> I think this needs to either be done as part of the map, or before the
> map, to prevent for example a disabled interrupt from the guest'ss PoV
> to fire when it doesn't expect it.

Indeed, that's a good point. I don't really like making it part of the
VLPI mapping, as this is an ITS thing (and the property update is more a
redistributor concept), but moving it it before the map is probably the
best thing to do. Thanks for pointing this out!

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
@ 2017-10-25 17:01       ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-25 17:01 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 25 2017 at  6:48:27 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> On Fri, Oct 06, 2017 at 04:33:52PM +0100, Marc Zyngier wrote:
>> When the VLPI gets mapped, it must inherit the configuration of
>> the LPI configured at the vITS level. For that purpose, let's make
>> update_lpi_config globally available and call it just after
>> having performed the VLPI map operation.
>> 
>> Acked-by: Christoffer Dall <cdall@linaro.org>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 6 ++----
>>  virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
>>  virt/kvm/arm/vgic/vgic.h     | 2 ++
>>  3 files changed, 6 insertions(+), 4 deletions(-)
>> 
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index eb72eb027060..f434748439ee 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -37,8 +37,6 @@
>>  static int vgic_its_save_tables_v0(struct vgic_its *its);
>>  static int vgic_its_restore_tables_v0(struct vgic_its *its);
>>  static int vgic_its_commit_v0(struct vgic_its *its);
>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
>>  
>>  /*
>>   * Creates a new (reference to a) struct vgic_irq for a given LPI.
>> @@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
>>   * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
>>   * VCPU. Unconditionally applies if filter_vcpu is NULL.
>>   */
>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
>> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
>>  {
>>  	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
>>  	u8 prop;
>> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
>> index ba1dd3162eba..b79a0450bb1c 100644
>> --- a/virt/kvm/arm/vgic/vgic-v4.c
>> +++ b/virt/kvm/arm/vgic/vgic-v4.c
>> @@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
>>  	irq->hw		= true;
>>  	irq->host_irq	= virq;
>>  
>> +	/* Force the property update and invalidate */
>> +	update_lpi_config(kvm, irq, NULL, true);
>
> Actually, when re-reading this patch, this looks weird to me.
>
> I think this needs to either be done as part of the map, or before the
> map, to prevent for example a disabled interrupt from the guest'ss PoV
> to fire when it doesn't expect it.

Indeed, that's a good point. I don't really like making it part of the
VLPI mapping, as this is an ITS thing (and the property update is more a
redistributor concept), but moving it it before the map is probably the
best thing to do. Thanks for pointing this out!

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
  2017-10-25 17:01       ` Marc Zyngier
@ 2017-10-26  8:21         ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-26  8:21 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: Andre Przywara, kvmarm, linux-arm-kernel, kvm

On Wed, Oct 25 2017 at  6:01:01 pm BST, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On Wed, Oct 25 2017 at  6:48:27 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
>> On Fri, Oct 06, 2017 at 04:33:52PM +0100, Marc Zyngier wrote:
>>> When the VLPI gets mapped, it must inherit the configuration of
>>> the LPI configured at the vITS level. For that purpose, let's make
>>> update_lpi_config globally available and call it just after
>>> having performed the VLPI map operation.
>>> 
>>> Acked-by: Christoffer Dall <cdall@linaro.org>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  virt/kvm/arm/vgic/vgic-its.c | 6 ++----
>>>  virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
>>>  virt/kvm/arm/vgic/vgic.h     | 2 ++
>>>  3 files changed, 6 insertions(+), 4 deletions(-)
>>> 
>>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>>> index eb72eb027060..f434748439ee 100644
>>> --- a/virt/kvm/arm/vgic/vgic-its.c
>>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>>> @@ -37,8 +37,6 @@
>>>  static int vgic_its_save_tables_v0(struct vgic_its *its);
>>>  static int vgic_its_restore_tables_v0(struct vgic_its *its);
>>>  static int vgic_its_commit_v0(struct vgic_its *its);
>>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
>>>  
>>>  /*
>>>   * Creates a new (reference to a) struct vgic_irq for a given LPI.
>>> @@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
>>>   * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
>>>   * VCPU. Unconditionally applies if filter_vcpu is NULL.
>>>   */
>>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
>>> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>>> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
>>>  {
>>>  	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
>>>  	u8 prop;
>>> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
>>> index ba1dd3162eba..b79a0450bb1c 100644
>>> --- a/virt/kvm/arm/vgic/vgic-v4.c
>>> +++ b/virt/kvm/arm/vgic/vgic-v4.c
>>> @@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
>>>  	irq->hw		= true;
>>>  	irq->host_irq	= virq;
>>>  
>>> +	/* Force the property update and invalidate */
>>> +	update_lpi_config(kvm, irq, NULL, true);
>>
>> Actually, when re-reading this patch, this looks weird to me.
>>
>> I think this needs to either be done as part of the map, or before the
>> map, to prevent for example a disabled interrupt from the guest'ss PoV
>> to fire when it doesn't expect it.
>
> Indeed, that's a good point. I don't really like making it part of the
> VLPI mapping, as this is an ITS thing (and the property update is more a
> redistributor concept), but moving it it before the map is probably the
> best thing to do. Thanks for pointing this out!

Scratch that. Doing it before the map cannot succeed, as the ITS driver
explicitly refuses to do any VLPI changes until this is actually mapped
(which is a completely unreasonable behaviour).

I guess that leaves setting the properties as part of the map operation
the only viable choice. I'll give it a go.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time
@ 2017-10-26  8:21         ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-26  8:21 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 25 2017 at  6:01:01 pm BST, Marc Zyngier <marc.zyngier@arm.com> wrote:
> On Wed, Oct 25 2017 at  6:48:27 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
>> On Fri, Oct 06, 2017 at 04:33:52PM +0100, Marc Zyngier wrote:
>>> When the VLPI gets mapped, it must inherit the configuration of
>>> the LPI configured at the vITS level. For that purpose, let's make
>>> update_lpi_config globally available and call it just after
>>> having performed the VLPI map operation.
>>> 
>>> Acked-by: Christoffer Dall <cdall@linaro.org>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  virt/kvm/arm/vgic/vgic-its.c | 6 ++----
>>>  virt/kvm/arm/vgic/vgic-v4.c  | 2 ++
>>>  virt/kvm/arm/vgic/vgic.h     | 2 ++
>>>  3 files changed, 6 insertions(+), 4 deletions(-)
>>> 
>>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>>> index eb72eb027060..f434748439ee 100644
>>> --- a/virt/kvm/arm/vgic/vgic-its.c
>>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>>> @@ -37,8 +37,6 @@
>>>  static int vgic_its_save_tables_v0(struct vgic_its *its);
>>>  static int vgic_its_restore_tables_v0(struct vgic_its *its);
>>>  static int vgic_its_commit_v0(struct vgic_its *its);
>>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv);
>>>  
>>>  /*
>>>   * Creates a new (reference to a) struct vgic_irq for a given LPI.
>>> @@ -272,8 +270,8 @@ static struct its_collection *find_collection(struct vgic_its *its, int coll_id)
>>>   * If filter_vcpu is not NULL, applies only if the IRQ is targeting this
>>>   * VCPU. Unconditionally applies if filter_vcpu is NULL.
>>>   */
>>> -static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>>> -			     struct kvm_vcpu *filter_vcpu, bool needs_inv)
>>> +int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>>> +		      struct kvm_vcpu *filter_vcpu, bool needs_inv)
>>>  {
>>>  	u64 propbase = GICR_PROPBASER_ADDRESS(kvm->arch.vgic.propbaser);
>>>  	u8 prop;
>>> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
>>> index ba1dd3162eba..b79a0450bb1c 100644
>>> --- a/virt/kvm/arm/vgic/vgic-v4.c
>>> +++ b/virt/kvm/arm/vgic/vgic-v4.c
>>> @@ -147,6 +147,8 @@ int kvm_vgic_v4_set_forwarding(struct kvm *kvm, int virq,
>>>  	irq->hw		= true;
>>>  	irq->host_irq	= virq;
>>>  
>>> +	/* Force the property update and invalidate */
>>> +	update_lpi_config(kvm, irq, NULL, true);
>>
>> Actually, when re-reading this patch, this looks weird to me.
>>
>> I think this needs to either be done as part of the map, or before the
>> map, to prevent for example a disabled interrupt from the guest'ss PoV
>> to fire when it doesn't expect it.
>
> Indeed, that's a good point. I don't really like making it part of the
> VLPI mapping, as this is an ITS thing (and the property update is more a
> redistributor concept), but moving it it before the map is probably the
> best thing to do. Thanks for pointing this out!

Scratch that. Doing it before the map cannot succeed, as the ITS driver
explicitly refuses to do any VLPI changes until this is actually mapped
(which is a completely unreasonable behaviour).

I guess that leaves setting the properties as part of the map operation
the only viable choice. I'll give it a go.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
  2017-10-25 14:44     ` Christoffer Dall
@ 2017-10-26 13:05       ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-26 13:05 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Mark Rutland, Shameerali Kolothum Thodi,
	Andre Przywara

On Wed, Oct 25 2017 at  4:44:43 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> On Fri, Oct 06, 2017 at 04:33:37PM +0100, Marc Zyngier wrote:
>> From: Eric Auger <eric.auger@redhat.com>
>> 
>> We want to reuse the core of the map/unmap functions for IRQ
>> forwarding. Let's move the computation of the hwirq in
>> kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
>> the host_irq is added to struct vgic_irq.
>> 
>> We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
>> handle as a parameter.
>> 
>
> Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
>
> Marc,
>   I need a signed-off-by from you on this patch.

Ah, my bad. I'll fix that for the next round (real soon now...)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq
@ 2017-10-26 13:05       ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-26 13:05 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, Oct 25 2017 at  4:44:43 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> On Fri, Oct 06, 2017 at 04:33:37PM +0100, Marc Zyngier wrote:
>> From: Eric Auger <eric.auger@redhat.com>
>> 
>> We want to reuse the core of the map/unmap functions for IRQ
>> forwarding. Let's move the computation of the hwirq in
>> kvm_vgic_map_phys_irq and pass the linux IRQ as parameter.
>> the host_irq is added to struct vgic_irq.
>> 
>> We introduce kvm_vgic_map/unmap_irq which take a struct vgic_irq
>> handle as a parameter.
>> 
>
> Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
>
> Marc,
>   I need a signed-off-by from you on this patch.

Ah, my bad. I'll fix that for the next round (real soon now...)

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-26 14:28     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 14:28 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:33:54PM +0100, Marc Zyngier wrote:
> When a vPE is not running, a VLPI being made pending results in a
> doorbell interrupt being delivered. Let's handle this interrupt
> and update the pending_last flag that indicates that VLPIs are
> pending. The corresponding vcpu is also kicked into action.
> 
> Special care is taken care of not allowing the doorbell to be
> enabled at request time (this is controlled separately), and
> to make the disabling on the interrupt non-lazy.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index b79a0450bb1c..2c250ee37878 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -16,11 +16,23 @@
>   */
>  
>  #include <linux/interrupt.h>
> +#include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kvm_host.h>
>  
>  #include "vgic.h"
>  
> +static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
> +{
> +	struct kvm_vcpu *vcpu = info;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
> +	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
> +	kvm_vcpu_kick(vcpu);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  /**
>   * vgic_v4_init - Initialize the GICv4 data structures
>   * @kvm:	Pointer to the VM being initialized
> @@ -60,6 +72,33 @@ int vgic_v4_init(struct kvm *kvm)
>  		return ret;
>  	}
>  
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		int irq = dist->its_vm.vpes[i]->irq;
> +
> +		/*
> +		 * Don't automatically enable the doorbell, as we're
> +		 * flipping it back and forth when the vcpu gets
> +		 * blocked. Also disable the lazy disabling, as the
> +		 * doorbell could kick us out of the guest too
> +		 * early...
> +		 */
> +		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		ret = request_irq(irq, vgic_v4_doorbell_handler,
> +				  0, "vcpu", vcpu);
> +		if (ret) {
> +			kvm_err("failed to allocate vcpu IRQ%d\n", irq);
> +			/*
> +			 * Trick: adjust the number of vpes so we know
> +			 * how many to nuke on teardown...
> +			 */
> +			dist->its_vm.nr_vpes = i;
> +			break;
> +		}
> +	}
> +
> +	if (ret)
> +		vgic_v4_teardown(kvm);
> +
>  	return ret;
>  }
>  
> @@ -72,10 +111,19 @@ int vgic_v4_init(struct kvm *kvm)
>  void vgic_v4_teardown(struct kvm *kvm)
>  {
>  	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
> +	int i;
>  
>  	if (!its_vm->vpes)
>  		return;
>  
> +	for (i = 0; i < its_vm->nr_vpes; i++) {
> +		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
> +		int irq = its_vm->vpes[i]->irq;
> +
> +		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		free_irq(irq, vcpu);
> +	}
> +
>  	its_free_vcpu_irqs(its_vm);
>  	kfree(its_vm->vpes);
>  	its_vm->nr_vpes = 0;
> -- 
> 2.14.1
> 

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

* [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling
@ 2017-10-26 14:28     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 14:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:54PM +0100, Marc Zyngier wrote:
> When a vPE is not running, a VLPI being made pending results in a
> doorbell interrupt being delivered. Let's handle this interrupt
> and update the pending_last flag that indicates that VLPIs are
> pending. The corresponding vcpu is also kicked into action.
> 
> Special care is taken care of not allowing the doorbell to be
> enabled at request time (this is controlled separately), and
> to make the disabling on the interrupt non-lazy.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index b79a0450bb1c..2c250ee37878 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -16,11 +16,23 @@
>   */
>  
>  #include <linux/interrupt.h>
> +#include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kvm_host.h>
>  
>  #include "vgic.h"
>  
> +static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
> +{
> +	struct kvm_vcpu *vcpu = info;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
> +	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
> +	kvm_vcpu_kick(vcpu);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  /**
>   * vgic_v4_init - Initialize the GICv4 data structures
>   * @kvm:	Pointer to the VM being initialized
> @@ -60,6 +72,33 @@ int vgic_v4_init(struct kvm *kvm)
>  		return ret;
>  	}
>  
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		int irq = dist->its_vm.vpes[i]->irq;
> +
> +		/*
> +		 * Don't automatically enable the doorbell, as we're
> +		 * flipping it back and forth when the vcpu gets
> +		 * blocked. Also disable the lazy disabling, as the
> +		 * doorbell could kick us out of the guest too
> +		 * early...
> +		 */
> +		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		ret = request_irq(irq, vgic_v4_doorbell_handler,
> +				  0, "vcpu", vcpu);
> +		if (ret) {
> +			kvm_err("failed to allocate vcpu IRQ%d\n", irq);
> +			/*
> +			 * Trick: adjust the number of vpes so we know
> +			 * how many to nuke on teardown...
> +			 */
> +			dist->its_vm.nr_vpes = i;
> +			break;
> +		}
> +	}
> +
> +	if (ret)
> +		vgic_v4_teardown(kvm);
> +
>  	return ret;
>  }
>  
> @@ -72,10 +111,19 @@ int vgic_v4_init(struct kvm *kvm)
>  void vgic_v4_teardown(struct kvm *kvm)
>  {
>  	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
> +	int i;
>  
>  	if (!its_vm->vpes)
>  		return;
>  
> +	for (i = 0; i < its_vm->nr_vpes; i++) {
> +		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
> +		int irq = its_vm->vpes[i]->irq;
> +
> +		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		free_irq(irq, vcpu);
> +	}
> +
>  	its_free_vcpu_irqs(its_vm);
>  	kfree(its_vm->vpes);
>  	its_vm->nr_vpes = 0;
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 21/26] KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-26 15:24     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:24 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Mark Rutland, Shameerali Kolothum Thodi,
	Andre Przywara

On Fri, Oct 06, 2017 at 04:33:56PM +0100, Marc Zyngier wrote:
> The redistributor needs to be told which vPE is about to be run,
> and tells us whether there is any pending VLPI on exit.
> 
> Let's add the scheduling calls to the vgic flush/sync functions,
> allowing the VLPIs to be delivered to the guest.
> 

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 39 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c    |  4 ++++
>  virt/kvm/arm/vgic/vgic.h    |  2 ++
>  3 files changed, 45 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index 5ee69aec990a..68a2ef6df161 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -130,6 +130,45 @@ void vgic_v4_teardown(struct kvm *kvm)
>  	its_vm->vpes = NULL;
>  }
>  
> +int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	if (!vgic_supports_direct_msis(vcpu->kvm))
> +		return 0;
> +
> +	return its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, false);
> +}
> +
> +int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
> +	int err;
> +
> +	if (!vgic_supports_direct_msis(vcpu->kvm))
> +		return 0;
> +
> +	/*
> +	 * Before making the VPE resident, make sure the redistributor
> +	 * corresponding to our current CPU expects us here. See the
> +	 * 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()));
> +	if (err)
> +		return err;
> +
> +	err = its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, true);
> +	if (err)
> +		return err;
> +
> +	/*
> +	 * 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;
> +}
> +
>  static struct vgic_its *vgic_get_its(struct kvm *kvm,
>  				     struct kvm_kernel_irq_routing_entry *irq_entry)
>  {
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 0691a2250949..71ca0ff1b35a 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -709,6 +709,8 @@ 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;
> @@ -721,6 +723,8 @@ void kvm_vgic_sync_hwstate(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 1bd2e28ac097..1c65750892d7 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -245,5 +245,7 @@ int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>  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.14.1
> 

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

* [PATCH v4 21/26] KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync
@ 2017-10-26 15:24     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:24 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:56PM +0100, Marc Zyngier wrote:
> The redistributor needs to be told which vPE is about to be run,
> and tells us whether there is any pending VLPI on exit.
> 
> Let's add the scheduling calls to the vgic flush/sync functions,
> allowing the VLPIs to be delivered to the guest.
> 

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 39 +++++++++++++++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic.c    |  4 ++++
>  virt/kvm/arm/vgic/vgic.h    |  2 ++
>  3 files changed, 45 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index 5ee69aec990a..68a2ef6df161 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -130,6 +130,45 @@ void vgic_v4_teardown(struct kvm *kvm)
>  	its_vm->vpes = NULL;
>  }
>  
> +int vgic_v4_sync_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	if (!vgic_supports_direct_msis(vcpu->kvm))
> +		return 0;
> +
> +	return its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, false);
> +}
> +
> +int vgic_v4_flush_hwstate(struct kvm_vcpu *vcpu)
> +{
> +	int irq = vcpu->arch.vgic_cpu.vgic_v3.its_vpe.irq;
> +	int err;
> +
> +	if (!vgic_supports_direct_msis(vcpu->kvm))
> +		return 0;
> +
> +	/*
> +	 * Before making the VPE resident, make sure the redistributor
> +	 * corresponding to our current CPU expects us here. See the
> +	 * 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()));
> +	if (err)
> +		return err;
> +
> +	err = its_schedule_vpe(&vcpu->arch.vgic_cpu.vgic_v3.its_vpe, true);
> +	if (err)
> +		return err;
> +
> +	/*
> +	 * 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;
> +}
> +
>  static struct vgic_its *vgic_get_its(struct kvm *kvm,
>  				     struct kvm_kernel_irq_routing_entry *irq_entry)
>  {
> diff --git a/virt/kvm/arm/vgic/vgic.c b/virt/kvm/arm/vgic/vgic.c
> index 0691a2250949..71ca0ff1b35a 100644
> --- a/virt/kvm/arm/vgic/vgic.c
> +++ b/virt/kvm/arm/vgic/vgic.c
> @@ -709,6 +709,8 @@ 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;
> @@ -721,6 +723,8 @@ void kvm_vgic_sync_hwstate(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 1bd2e28ac097..1c65750892d7 100644
> --- a/virt/kvm/arm/vgic/vgic.h
> +++ b/virt/kvm/arm/vgic/vgic.h
> @@ -245,5 +245,7 @@ int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
>  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.14.1
> 

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

* Re: [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-26 15:25     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:25 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Mark Rutland, Shameerali Kolothum Thodi,
	Andre Przywara

On Fri, Oct 06, 2017 at 04:33:54PM +0100, Marc Zyngier wrote:
> When a vPE is not running, a VLPI being made pending results in a
> doorbell interrupt being delivered. Let's handle this interrupt
> and update the pending_last flag that indicates that VLPIs are
> pending. The corresponding vcpu is also kicked into action.
> 
> Special care is taken care of not allowing the doorbell to be
> enabled at request time (this is controlled separately), and

super nit: this first sentence is pretty hard to understand...

> to make the disabling on the interrupt non-lazy.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index b79a0450bb1c..2c250ee37878 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -16,11 +16,23 @@
>   */
>  
>  #include <linux/interrupt.h>
> +#include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kvm_host.h>
>  
>  #include "vgic.h"
>  
> +static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
> +{
> +	struct kvm_vcpu *vcpu = info;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
> +	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
> +	kvm_vcpu_kick(vcpu);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  /**
>   * vgic_v4_init - Initialize the GICv4 data structures
>   * @kvm:	Pointer to the VM being initialized
> @@ -60,6 +72,33 @@ int vgic_v4_init(struct kvm *kvm)
>  		return ret;
>  	}
>  
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		int irq = dist->its_vm.vpes[i]->irq;
> +
> +		/*
> +		 * Don't automatically enable the doorbell, as we're
> +		 * flipping it back and forth when the vcpu gets
> +		 * blocked. Also disable the lazy disabling, as the
> +		 * doorbell could kick us out of the guest too
> +		 * early...
> +		 */
> +		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		ret = request_irq(irq, vgic_v4_doorbell_handler,
> +				  0, "vcpu", vcpu);
> +		if (ret) {
> +			kvm_err("failed to allocate vcpu IRQ%d\n", irq);
> +			/*
> +			 * Trick: adjust the number of vpes so we know
> +			 * how many to nuke on teardown...
> +			 */
> +			dist->its_vm.nr_vpes = i;
> +			break;
> +		}
> +	}
> +
> +	if (ret)
> +		vgic_v4_teardown(kvm);
> +
>  	return ret;
>  }
>  
> @@ -72,10 +111,19 @@ int vgic_v4_init(struct kvm *kvm)
>  void vgic_v4_teardown(struct kvm *kvm)
>  {
>  	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
> +	int i;
>  
>  	if (!its_vm->vpes)
>  		return;
>  
> +	for (i = 0; i < its_vm->nr_vpes; i++) {
> +		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
> +		int irq = its_vm->vpes[i]->irq;
> +
> +		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		free_irq(irq, vcpu);
> +	}
> +
>  	its_free_vcpu_irqs(its_vm);
>  	kfree(its_vm->vpes);
>  	its_vm->nr_vpes = 0;
> -- 
> 2.14.1
> 

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

* [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling
@ 2017-10-26 15:25     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:25 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:54PM +0100, Marc Zyngier wrote:
> When a vPE is not running, a VLPI being made pending results in a
> doorbell interrupt being delivered. Let's handle this interrupt
> and update the pending_last flag that indicates that VLPIs are
> pending. The corresponding vcpu is also kicked into action.
> 
> Special care is taken care of not allowing the doorbell to be
> enabled at request time (this is controlled separately), and

super nit: this first sentence is pretty hard to understand...

> to make the disabling on the interrupt non-lazy.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index b79a0450bb1c..2c250ee37878 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -16,11 +16,23 @@
>   */
>  
>  #include <linux/interrupt.h>
> +#include <linux/irq.h>
>  #include <linux/irqdomain.h>
>  #include <linux/kvm_host.h>
>  
>  #include "vgic.h"
>  
> +static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
> +{
> +	struct kvm_vcpu *vcpu = info;
> +
> +	vcpu->arch.vgic_cpu.vgic_v3.its_vpe.pending_last = true;
> +	kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
> +	kvm_vcpu_kick(vcpu);
> +
> +	return IRQ_HANDLED;
> +}
> +
>  /**
>   * vgic_v4_init - Initialize the GICv4 data structures
>   * @kvm:	Pointer to the VM being initialized
> @@ -60,6 +72,33 @@ int vgic_v4_init(struct kvm *kvm)
>  		return ret;
>  	}
>  
> +	kvm_for_each_vcpu(i, vcpu, kvm) {
> +		int irq = dist->its_vm.vpes[i]->irq;
> +
> +		/*
> +		 * Don't automatically enable the doorbell, as we're
> +		 * flipping it back and forth when the vcpu gets
> +		 * blocked. Also disable the lazy disabling, as the
> +		 * doorbell could kick us out of the guest too
> +		 * early...
> +		 */
> +		irq_set_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		ret = request_irq(irq, vgic_v4_doorbell_handler,
> +				  0, "vcpu", vcpu);
> +		if (ret) {
> +			kvm_err("failed to allocate vcpu IRQ%d\n", irq);
> +			/*
> +			 * Trick: adjust the number of vpes so we know
> +			 * how many to nuke on teardown...
> +			 */
> +			dist->its_vm.nr_vpes = i;
> +			break;
> +		}
> +	}
> +
> +	if (ret)
> +		vgic_v4_teardown(kvm);
> +
>  	return ret;
>  }
>  
> @@ -72,10 +111,19 @@ int vgic_v4_init(struct kvm *kvm)
>  void vgic_v4_teardown(struct kvm *kvm)
>  {
>  	struct its_vm *its_vm = &kvm->arch.vgic.its_vm;
> +	int i;
>  
>  	if (!its_vm->vpes)
>  		return;
>  
> +	for (i = 0; i < its_vm->nr_vpes; i++) {
> +		struct kvm_vcpu *vcpu = kvm_get_vcpu(kvm, i);
> +		int irq = its_vm->vpes[i]->irq;
> +
> +		irq_clear_status_flags(irq, IRQ_NOAUTOEN | IRQ_DISABLE_UNLAZY);
> +		free_irq(irq, vcpu);
> +	}
> +
>  	its_free_vcpu_irqs(its_vm);
>  	kfree(its_vm->vpes);
>  	its_vm->nr_vpes = 0;
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
  2017-10-06 15:33   ` Marc Zyngier
@ 2017-10-26 15:28     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:28 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvmarm, kvm, Andre Przywara

On Fri, Oct 06, 2017 at 04:33:58PM +0100, Marc Zyngier wrote:
> The GICv4 architecture doesn't make it easy for save/restore to
> work, as it doesn't give any guarantee that the pending state
> is written into the pending table.
> 
> So let's not take any chance, and let's return an error if
> we encounter any LPI that has the HW bit set.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index f434748439ee..01aa4d9d405e 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
>  	list_for_each_entry(ite, &device->itt_head, ite_list) {
>  		gpa_t gpa = base + ite->event_id * ite_esz;
>  
> +		/*
> +		 * If an LPI carries the HW bit, this means that this
> +		 * interrupt is controlled by GICv4, and we do not
> +		 * have direct access to that state. Let's simply fail
> +		 * the save operation...
> +		 */
> +		if (ite->irq->hw)
> +			return -EINVAL;

Will this conflict with other error messages, and will QEMU have a
reasonable way to tell the user what's going on?

Perhaps we shoul document the return code in the ITS device doc and
choose something unique, like -EBUSY?

Thanks,
-Christoffer

> +
>  		ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
>  		if (ret)
>  			return ret;
> -- 
> 2.14.1
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
@ 2017-10-26 15:28     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:28 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:33:58PM +0100, Marc Zyngier wrote:
> The GICv4 architecture doesn't make it easy for save/restore to
> work, as it doesn't give any guarantee that the pending state
> is written into the pending table.
> 
> So let's not take any chance, and let's return an error if
> we encounter any LPI that has the HW bit set.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
>  1 file changed, 9 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> index f434748439ee..01aa4d9d405e 100644
> --- a/virt/kvm/arm/vgic/vgic-its.c
> +++ b/virt/kvm/arm/vgic/vgic-its.c
> @@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
>  	list_for_each_entry(ite, &device->itt_head, ite_list) {
>  		gpa_t gpa = base + ite->event_id * ite_esz;
>  
> +		/*
> +		 * If an LPI carries the HW bit, this means that this
> +		 * interrupt is controlled by GICv4, and we do not
> +		 * have direct access to that state. Let's simply fail
> +		 * the save operation...
> +		 */
> +		if (ite->irq->hw)
> +			return -EINVAL;

Will this conflict with other error messages, and will QEMU have a
reasonable way to tell the user what's going on?

Perhaps we shoul document the return code in the ITS device doc and
choose something unique, like -EBUSY?

Thanks,
-Christoffer

> +
>  		ret = vgic_its_save_ite(its, device, ite, gpa, ite_esz);
>  		if (ret)
>  			return ret;
> -- 
> 2.14.1
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-06 15:34   ` Marc Zyngier
@ 2017-10-26 15:31     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:31 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvmarm, kvm, Andre Przywara

On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
> cohabit with CPUs limited to GICv3 in the same system.
> 
> This is mad (the scheduler would have to be made aware of the v4
> capability), and we're certainly not going to support this any
> time soon. So let's check that all online CPUs are GICv4 capable,
> and disable the functionnality if not.
> 

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |  2 ++
>  virt/kvm/arm/vgic/vgic-v3.c        | 27 +++++++++++++++++++++++++--
>  2 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 1ea576c8126f..dfa4a51643d6 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -532,6 +532,8 @@
>  #define ICH_VTR_SEIS_MASK		(1 << ICH_VTR_SEIS_SHIFT)
>  #define ICH_VTR_A3V_SHIFT		21
>  #define ICH_VTR_A3V_MASK		(1 << ICH_VTR_A3V_SHIFT)
> +#define ICH_VTR_nV4_SHIFT		20
> +#define ICH_VTR_nV4_MASK		(1 << ICH_VTR_nV4_SHIFT)
>  
>  #define ICC_IAR1_EL1_SPURIOUS		0x3ff
>  
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 405733678c2f..da99df50a818 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -466,9 +466,19 @@ static int __init early_gicv4_enable(char *buf)
>  }
>  early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
>  
> +static void vgic_check_v4_cpuif(void *param)
> +{
> +	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +	bool *v4 = param;
> +
> +	*v4 = !(ich_vtr_el2 & ICH_VTR_nV4_MASK);
> +	if (!*v4)
> +		kvm_info("CPU%d is not GICv4 capable\n", smp_processor_id());
> +}
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
> - * @node:	pointer to the DT node
> + * @info:	pointer to the firmware-agnostic GIC information
>   *
>   * Returns 0 if a GICv3 has been found, returns an error code otherwise
>   */
> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>  
> -	/* GICv4 support? */
> +	/*
> +	 * GICv4 support? We need to check on all CPUs in case of some
> +	 * extremely creative form of big-little brain damage...
> +	 */
>  	if (info->has_v4) {
> +		int cpu;
> +
> +		for_each_online_cpu(cpu) {
> +			bool enable;
> +
> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> +						 &enable, 1);
> +			gicv4_enable = gicv4_enable && enable;
> +		}
> +
>  		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
>  		kvm_info("GICv4 support %sabled\n",
>  			 gicv4_enable ? "en" : "dis");
> -- 
> 2.14.1
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm@lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-26 15:31     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
> cohabit with CPUs limited to GICv3 in the same system.
> 
> This is mad (the scheduler would have to be made aware of the v4
> capability), and we're certainly not going to support this any
> time soon. So let's check that all online CPUs are GICv4 capable,
> and disable the functionnality if not.
> 

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>

> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |  2 ++
>  virt/kvm/arm/vgic/vgic-v3.c        | 27 +++++++++++++++++++++++++--
>  2 files changed, 27 insertions(+), 2 deletions(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 1ea576c8126f..dfa4a51643d6 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -532,6 +532,8 @@
>  #define ICH_VTR_SEIS_MASK		(1 << ICH_VTR_SEIS_SHIFT)
>  #define ICH_VTR_A3V_SHIFT		21
>  #define ICH_VTR_A3V_MASK		(1 << ICH_VTR_A3V_SHIFT)
> +#define ICH_VTR_nV4_SHIFT		20
> +#define ICH_VTR_nV4_MASK		(1 << ICH_VTR_nV4_SHIFT)
>  
>  #define ICC_IAR1_EL1_SPURIOUS		0x3ff
>  
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 405733678c2f..da99df50a818 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -466,9 +466,19 @@ static int __init early_gicv4_enable(char *buf)
>  }
>  early_param("kvm-arm.vgic_v4_enable", early_gicv4_enable);
>  
> +static void vgic_check_v4_cpuif(void *param)
> +{
> +	u32 ich_vtr_el2 = kvm_call_hyp(__vgic_v3_get_ich_vtr_el2);
> +	bool *v4 = param;
> +
> +	*v4 = !(ich_vtr_el2 & ICH_VTR_nV4_MASK);
> +	if (!*v4)
> +		kvm_info("CPU%d is not GICv4 capable\n", smp_processor_id());
> +}
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
> - * @node:	pointer to the DT node
> + * @info:	pointer to the firmware-agnostic GIC information
>   *
>   * Returns 0 if a GICv3 has been found, returns an error code otherwise
>   */
> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>  
> -	/* GICv4 support? */
> +	/*
> +	 * GICv4 support? We need to check on all CPUs in case of some
> +	 * extremely creative form of big-little brain damage...
> +	 */
>  	if (info->has_v4) {
> +		int cpu;
> +
> +		for_each_online_cpu(cpu) {
> +			bool enable;
> +
> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> +						 &enable, 1);
> +			gicv4_enable = gicv4_enable && enable;
> +		}
> +
>  		kvm_vgic_global_state.has_gicv4 = gicv4_enable;
>  		kvm_info("GICv4 support %sabled\n",
>  			 gicv4_enable ? "en" : "dis");
> -- 
> 2.14.1
> 
> _______________________________________________
> kvmarm mailing list
> kvmarm at lists.cs.columbia.edu
> https://lists.cs.columbia.edu/mailman/listinfo/kvmarm

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

* Re: [PATCH v4 26/26] KVM: arm/arm64: GICv4: Theory of operations
  2017-10-06 15:34   ` Marc Zyngier
@ 2017-10-26 15:32     ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:32 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

On Fri, Oct 06, 2017 at 04:34:01PM +0100, Marc Zyngier wrote:
> Yet another braindump so I can free some cells...
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index 68a2ef6df161..b87806fea554 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -22,6 +22,73 @@
>  
>  #include "vgic.h"
>  
> +/*
> + * How KVM uses GICv4 (insert rude comments here):
> + *
> + * The vgic-v4 layer acts as a bridge between several entities:
> + * - The GICv4 ITS representation offered by the ITS driver
> + * - VFIO, which is in charge of the PCI endpoint
> + * - The virtual ITS, which is the only thing the guest sees
> + *
> + * The configuration of VLPIs is triggered by a callback from VFIO,
> + * instructing KVM that a PCI device has been configured to deliver
> + * MSIs to a vITS.
> + *
> + * kvm_vgic_v4_set_forwarding() is thus called with the routing entry,
> + * and this is used to find the corresponding vITS data structures
> + * (ITS instance, device, event and irq) using a process that is
> + * extremely similar to the injection of an MSI.
> + *
> + * At this stage, we can link the guest's view of an LPI (uniquely
> + * identified by the routing entry) and the host irq, using the GICv4
> + * driver mapping operation. Should the mapping succeed, we've then
> + * successfully upgraded the guest's LPI to a VLPI. We can then start
> + * with updating GICv4's view of the property table and generating an
> + * INValidation in order to kickstart the delivery of this VLPI to the
> + * guest directly, without software intervention. Well, almost.
> + *
> + * When the PCI endpoint is deconfigured, this operation is reversed
> + * with VFIO calling kvm_vgic_v4_unset_forwarding().
> + *
> + * Once the VLPI has been mapped, it needs to follow any change the
> + * guest performs on its LPI through the vITS. For that, a number of
> + * command handlers have hooks to communicate these changes to the HW:
> + * - Any invalidation triggers a call to its_prop_update_vlpi()
> + * - The INT command results in a irq_set_irqchip_state(), which
> + *   generates an INT on the corresponding VLPI.
> + * - The CLEAR command results in a irq_set_irqchip_state(), which
> + *   generates an CLEAR on the corresponding VLPI.
> + * - DISCARD translates into an unmap, similar to a call to
> + *   kvm_vgic_v4_unset_forwarding().
> + * - MOVI is translated by an update of the existing mapping, changing
> + *   the target vcpu, resulting in a VMOVI being generated.
> + * - MOVALL is translated by a string of mapping updates (similar to
> + *   the handling of MOVI). MOVALL is horrible.
> + *
> + * Note that a DISCARD/MAPTI sequence emitted from the guest without
> + * reprogramming the PCI endpoint after MAPTI does not result in a
> + * VLPI being mapped, as there is no callback from VFIO (the guest
> + * will get the interrupt via the normal SW injection). Fixing this is
> + * not trivial, and requires some horrible messing with the VFIO
> + * internals. Not fun. Don't do that.
> + *
> + * Then there is the scheduling. Each time a vcpu is about to run on a
> + * physical CPU, KVM must tell the corresponding redistributor about
> + * 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.
> + *
> + * Finally, the doorbell handling: Each vcpu is allocated an interrupt
> + * which will fire each time a VLPI is made pending whilst the vcpu is
> + * not running. Each time the vcpu gets blocked, the doorbell
> + * interrupt gets enabled. When the vcpu is unblocked (for whatever
> + * reason), the doorbell interrupt is disabled.
> + */
> +
>  static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
>  {
>  	struct kvm_vcpu *vcpu = info;
> -- 
> 2.14.1
> 

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

* [PATCH v4 26/26] KVM: arm/arm64: GICv4: Theory of operations
@ 2017-10-26 15:32     ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-26 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 06, 2017 at 04:34:01PM +0100, Marc Zyngier wrote:
> Yet another braindump so I can free some cells...
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Christoffer Dall <christoffer.dall@linaro.org>

> ---
>  virt/kvm/arm/vgic/vgic-v4.c | 67 +++++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 67 insertions(+)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v4.c b/virt/kvm/arm/vgic/vgic-v4.c
> index 68a2ef6df161..b87806fea554 100644
> --- a/virt/kvm/arm/vgic/vgic-v4.c
> +++ b/virt/kvm/arm/vgic/vgic-v4.c
> @@ -22,6 +22,73 @@
>  
>  #include "vgic.h"
>  
> +/*
> + * How KVM uses GICv4 (insert rude comments here):
> + *
> + * The vgic-v4 layer acts as a bridge between several entities:
> + * - The GICv4 ITS representation offered by the ITS driver
> + * - VFIO, which is in charge of the PCI endpoint
> + * - The virtual ITS, which is the only thing the guest sees
> + *
> + * The configuration of VLPIs is triggered by a callback from VFIO,
> + * instructing KVM that a PCI device has been configured to deliver
> + * MSIs to a vITS.
> + *
> + * kvm_vgic_v4_set_forwarding() is thus called with the routing entry,
> + * and this is used to find the corresponding vITS data structures
> + * (ITS instance, device, event and irq) using a process that is
> + * extremely similar to the injection of an MSI.
> + *
> + * At this stage, we can link the guest's view of an LPI (uniquely
> + * identified by the routing entry) and the host irq, using the GICv4
> + * driver mapping operation. Should the mapping succeed, we've then
> + * successfully upgraded the guest's LPI to a VLPI. We can then start
> + * with updating GICv4's view of the property table and generating an
> + * INValidation in order to kickstart the delivery of this VLPI to the
> + * guest directly, without software intervention. Well, almost.
> + *
> + * When the PCI endpoint is deconfigured, this operation is reversed
> + * with VFIO calling kvm_vgic_v4_unset_forwarding().
> + *
> + * Once the VLPI has been mapped, it needs to follow any change the
> + * guest performs on its LPI through the vITS. For that, a number of
> + * command handlers have hooks to communicate these changes to the HW:
> + * - Any invalidation triggers a call to its_prop_update_vlpi()
> + * - The INT command results in a irq_set_irqchip_state(), which
> + *   generates an INT on the corresponding VLPI.
> + * - The CLEAR command results in a irq_set_irqchip_state(), which
> + *   generates an CLEAR on the corresponding VLPI.
> + * - DISCARD translates into an unmap, similar to a call to
> + *   kvm_vgic_v4_unset_forwarding().
> + * - MOVI is translated by an update of the existing mapping, changing
> + *   the target vcpu, resulting in a VMOVI being generated.
> + * - MOVALL is translated by a string of mapping updates (similar to
> + *   the handling of MOVI). MOVALL is horrible.
> + *
> + * Note that a DISCARD/MAPTI sequence emitted from the guest without
> + * reprogramming the PCI endpoint after MAPTI does not result in a
> + * VLPI being mapped, as there is no callback from VFIO (the guest
> + * will get the interrupt via the normal SW injection). Fixing this is
> + * not trivial, and requires some horrible messing with the VFIO
> + * internals. Not fun. Don't do that.
> + *
> + * Then there is the scheduling. Each time a vcpu is about to run on a
> + * physical CPU, KVM must tell the corresponding redistributor about
> + * 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.
> + *
> + * Finally, the doorbell handling: Each vcpu is allocated an interrupt
> + * which will fire each time a VLPI is made pending whilst the vcpu is
> + * not running. Each time the vcpu gets blocked, the doorbell
> + * interrupt gets enabled. When the vcpu is unblocked (for whatever
> + * reason), the doorbell interrupt is disabled.
> + */
> +
>  static irqreturn_t vgic_v4_doorbell_handler(int irq, void *info)
>  {
>  	struct kvm_vcpu *vcpu = info;
> -- 
> 2.14.1
> 

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-06 15:34   ` Marc Zyngier
@ 2017-10-26 15:48     ` Mark Rutland
  -1 siblings, 0 replies; 117+ messages in thread
From: Mark Rutland @ 2017-10-26 15:48 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvm, Andre Przywara, kvmarm

Hi,

On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
> cohabit with CPUs limited to GICv3 in the same system.
> 
> This is mad (the scheduler would have to be made aware of the v4
> capability), and we're certainly not going to support this any
> time soon. So let's check that all online CPUs are GICv4 capable,
> and disable the functionnality if not.

I just spotted this because of Christoffer's review; apologies for the late
drive-by comment...

> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>  
> -	/* GICv4 support? */
> +	/*
> +	 * GICv4 support? We need to check on all CPUs in case of some
> +	 * extremely creative form of big-little brain damage...
> +	 */
>  	if (info->has_v4) {
> +		int cpu;
> +
> +		for_each_online_cpu(cpu) {
> +			bool enable;
> +
> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> +						 &enable, 1);
> +			gicv4_enable = gicv4_enable && enable;
> +		}

With maxcpus=N on the command line, CPUs can be brought online late, so we
might need this in a hotplug callback (and/or in the arm64 cpufeature
framework) to handle that case.

Thanks,
Mark.

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-26 15:48     ` Mark Rutland
  0 siblings, 0 replies; 117+ messages in thread
From: Mark Rutland @ 2017-10-26 15:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
> cohabit with CPUs limited to GICv3 in the same system.
> 
> This is mad (the scheduler would have to be made aware of the v4
> capability), and we're certainly not going to support this any
> time soon. So let's check that all online CPUs are GICv4 capable,
> and disable the functionnality if not.

I just spotted this because of Christoffer's review; apologies for the late
drive-by comment...

> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>  
> -	/* GICv4 support? */
> +	/*
> +	 * GICv4 support? We need to check on all CPUs in case of some
> +	 * extremely creative form of big-little brain damage...
> +	 */
>  	if (info->has_v4) {
> +		int cpu;
> +
> +		for_each_online_cpu(cpu) {
> +			bool enable;
> +
> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> +						 &enable, 1);
> +			gicv4_enable = gicv4_enable && enable;
> +		}

With maxcpus=N on the command line, CPUs can be brought online late, so we
might need this in a hotplug callback (and/or in the arm64 cpufeature
framework) to handle that case.

Thanks,
Mark.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-26 15:48     ` Mark Rutland
  (?)
@ 2017-10-27  6:57       ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  6:57 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> Hi,
>
> On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
>> cohabit with CPUs limited to GICv3 in the same system.
>> 
>> This is mad (the scheduler would have to be made aware of the v4
>> capability), and we're certainly not going to support this any
>> time soon. So let's check that all online CPUs are GICv4 capable,
>> and disable the functionnality if not.
>
> I just spotted this because of Christoffer's review; apologies for the late
> drive-by comment...
>
>> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>>  
>> -	/* GICv4 support? */
>> +	/*
>> +	 * GICv4 support? We need to check on all CPUs in case of some
>> +	 * extremely creative form of big-little brain damage...
>> +	 */
>>  	if (info->has_v4) {
>> +		int cpu;
>> +
>> +		for_each_online_cpu(cpu) {
>> +			bool enable;
>> +
>> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> +						 &enable, 1);
>> +			gicv4_enable = gicv4_enable && enable;
>> +		}
>
> With maxcpus=N on the command line, CPUs can be brought online late, so we
> might need this in a hotplug callback (and/or in the arm64 cpufeature
> framework) to handle that case.

I'm afraid that won't be enough. If the CPU is brought up once we've
already started a VM, we're screwed, as we cannot retroactively decide
to drop GICv4 on the floor and nuke the guest. Or did you have something
more radical in mind? Panic?

Maybe this approach is not the right one, in which case I'm happy to
drop this patch and implement something else.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  6:57       ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  6:57 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> Hi,
>
> On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
>> cohabit with CPUs limited to GICv3 in the same system.
>> 
>> This is mad (the scheduler would have to be made aware of the v4
>> capability), and we're certainly not going to support this any
>> time soon. So let's check that all online CPUs are GICv4 capable,
>> and disable the functionnality if not.
>
> I just spotted this because of Christoffer's review; apologies for the late
> drive-by comment...
>
>> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>>  
>> -	/* GICv4 support? */
>> +	/*
>> +	 * GICv4 support? We need to check on all CPUs in case of some
>> +	 * extremely creative form of big-little brain damage...
>> +	 */
>>  	if (info->has_v4) {
>> +		int cpu;
>> +
>> +		for_each_online_cpu(cpu) {
>> +			bool enable;
>> +
>> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> +						 &enable, 1);
>> +			gicv4_enable = gicv4_enable && enable;
>> +		}
>
> With maxcpus=N on the command line, CPUs can be brought online late, so we
> might need this in a hotplug callback (and/or in the arm64 cpufeature
> framework) to handle that case.

I'm afraid that won't be enough. If the CPU is brought up once we've
already started a VM, we're screwed, as we cannot retroactively decide
to drop GICv4 on the floor and nuke the guest. Or did you have something
more radical in mind? Panic?

Maybe this approach is not the right one, in which case I'm happy to
drop this patch and implement something else.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  6:57       ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  6:57 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> Hi,
>
> On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>> The GICv4 architecture doesn't prevent CPUs implementing GICv4 to
>> cohabit with CPUs limited to GICv3 in the same system.
>> 
>> This is mad (the scheduler would have to be made aware of the v4
>> capability), and we're certainly not going to support this any
>> time soon. So let's check that all online CPUs are GICv4 capable,
>> and disable the functionnality if not.
>
> I just spotted this because of Christoffer's review; apologies for the late
> drive-by comment...
>
>> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>>  
>> -	/* GICv4 support? */
>> +	/*
>> +	 * GICv4 support? We need to check on all CPUs in case of some
>> +	 * extremely creative form of big-little brain damage...
>> +	 */
>>  	if (info->has_v4) {
>> +		int cpu;
>> +
>> +		for_each_online_cpu(cpu) {
>> +			bool enable;
>> +
>> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> +						 &enable, 1);
>> +			gicv4_enable = gicv4_enable && enable;
>> +		}
>
> With maxcpus=N on the command line, CPUs can be brought online late, so we
> might need this in a hotplug callback (and/or in the arm64 cpufeature
> framework) to handle that case.

I'm afraid that won't be enough. If the CPU is brought up once we've
already started a VM, we're screwed, as we cannot retroactively decide
to drop GICv4 on the floor and nuke the guest. Or did you have something
more radical in mind? Panic?

Maybe this approach is not the right one, in which case I'm happy to
drop this patch and implement something else.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-27  6:57       ` Marc Zyngier
@ 2017-10-27  7:37         ` Mark Rutland
  -1 siblings, 0 replies; 117+ messages in thread
From: Mark Rutland @ 2017-10-27  7:37 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:

> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >>  
> >> -	/* GICv4 support? */
> >> +	/*
> >> +	 * GICv4 support? We need to check on all CPUs in case of some
> >> +	 * extremely creative form of big-little brain damage...
> >> +	 */
> >>  	if (info->has_v4) {
> >> +		int cpu;
> >> +
> >> +		for_each_online_cpu(cpu) {
> >> +			bool enable;
> >> +
> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> >> +						 &enable, 1);
> >> +			gicv4_enable = gicv4_enable && enable;
> >> +		}
> >
> > With maxcpus=N on the command line, CPUs can be brought online late, so we
> > might need this in a hotplug callback (and/or in the arm64 cpufeature
> > framework) to handle that case.
> 
> I'm afraid that won't be enough. If the CPU is brought up once we've
> already started a VM, we're screwed, as we cannot retroactively decide
> to drop GICv4 on the floor and nuke the guest. Or did you have something
> more radical in mind? Panic?

If you teach the arm64 cpufeature framework about this, it can abort bringing a
!GICv4 CPU online late.

It already handles onlining a !FP CPU if all boot CPUs had FP, for example.

See verify_local_cpu_features() in arch/arm64/kernel/cpufeature.c.

Thanks,
Mark.

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  7:37         ` Mark Rutland
  0 siblings, 0 replies; 117+ messages in thread
From: Mark Rutland @ 2017-10-27  7:37 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:

> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >>  
> >> -	/* GICv4 support? */
> >> +	/*
> >> +	 * GICv4 support? We need to check on all CPUs in case of some
> >> +	 * extremely creative form of big-little brain damage...
> >> +	 */
> >>  	if (info->has_v4) {
> >> +		int cpu;
> >> +
> >> +		for_each_online_cpu(cpu) {
> >> +			bool enable;
> >> +
> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> >> +						 &enable, 1);
> >> +			gicv4_enable = gicv4_enable && enable;
> >> +		}
> >
> > With maxcpus=N on the command line, CPUs can be brought online late, so we
> > might need this in a hotplug callback (and/or in the arm64 cpufeature
> > framework) to handle that case.
> 
> I'm afraid that won't be enough. If the CPU is brought up once we've
> already started a VM, we're screwed, as we cannot retroactively decide
> to drop GICv4 on the floor and nuke the guest. Or did you have something
> more radical in mind? Panic?

If you teach the arm64 cpufeature framework about this, it can abort bringing a
!GICv4 CPU online late.

It already handles onlining a !FP CPU if all boot CPUs had FP, for example.

See verify_local_cpu_features() in arch/arm64/kernel/cpufeature.c.

Thanks,
Mark.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-27  7:37         ` Mark Rutland
  (?)
@ 2017-10-27  7:59           ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  7:59 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
>> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>
>> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>> >>  
>> >> -	/* GICv4 support? */
>> >> +	/*
>> >> +	 * GICv4 support? We need to check on all CPUs in case of some
>> >> +	 * extremely creative form of big-little brain damage...
>> >> +	 */
>> >>  	if (info->has_v4) {
>> >> +		int cpu;
>> >> +
>> >> +		for_each_online_cpu(cpu) {
>> >> +			bool enable;
>> >> +
>> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> >> +						 &enable, 1);
>> >> +			gicv4_enable = gicv4_enable && enable;
>> >> +		}
>> >
>> > With maxcpus=N on the command line, CPUs can be brought online late, so we
>> > might need this in a hotplug callback (and/or in the arm64 cpufeature
>> > framework) to handle that case.
>> 
>> I'm afraid that won't be enough. If the CPU is brought up once we've
>> already started a VM, we're screwed, as we cannot retroactively decide
>> to drop GICv4 on the floor and nuke the guest. Or did you have something
>> more radical in mind? Panic?
>
> If you teach the arm64 cpufeature framework about this, it can abort bringing a
> !GICv4 CPU online late.

You wish.

There is all kind of difficulties with that. This requires checking an
EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
call facility). We could make it an additional hyp-stub feature, but
that feels pretty involved.

Effectively, GICv4 support having it supported on the redistributors,
the ITSs, and the CPUs. The cpufeature framework only addresses the
first one. So unless the solution encompasses all the elements in the
chain, any checking feels pretty pointless.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  7:59           ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  7:59 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
>> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>
>> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>> >>  
>> >> -	/* GICv4 support? */
>> >> +	/*
>> >> +	 * GICv4 support? We need to check on all CPUs in case of some
>> >> +	 * extremely creative form of big-little brain damage...
>> >> +	 */
>> >>  	if (info->has_v4) {
>> >> +		int cpu;
>> >> +
>> >> +		for_each_online_cpu(cpu) {
>> >> +			bool enable;
>> >> +
>> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> >> +						 &enable, 1);
>> >> +			gicv4_enable = gicv4_enable && enable;
>> >> +		}
>> >
>> > With maxcpus=N on the command line, CPUs can be brought online late, so we
>> > might need this in a hotplug callback (and/or in the arm64 cpufeature
>> > framework) to handle that case.
>> 
>> I'm afraid that won't be enough. If the CPU is brought up once we've
>> already started a VM, we're screwed, as we cannot retroactively decide
>> to drop GICv4 on the floor and nuke the guest. Or did you have something
>> more radical in mind? Panic?
>
> If you teach the arm64 cpufeature framework about this, it can abort bringing a
> !GICv4 CPU online late.

You wish.

There is all kind of difficulties with that. This requires checking an
EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
call facility). We could make it an additional hyp-stub feature, but
that feels pretty involved.

Effectively, GICv4 support having it supported on the redistributors,
the ITSs, and the CPUs. The cpufeature framework only addresses the
first one. So unless the solution encompasses all the elements in the
chain, any checking feels pretty pointless.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  7:59           ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  7:59 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
>> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>
>> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>> >>  
>> >> -	/* GICv4 support? */
>> >> +	/*
>> >> +	 * GICv4 support? We need to check on all CPUs in case of some
>> >> +	 * extremely creative form of big-little brain damage...
>> >> +	 */
>> >>  	if (info->has_v4) {
>> >> +		int cpu;
>> >> +
>> >> +		for_each_online_cpu(cpu) {
>> >> +			bool enable;
>> >> +
>> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> >> +						 &enable, 1);
>> >> +			gicv4_enable = gicv4_enable && enable;
>> >> +		}
>> >
>> > With maxcpus=N on the command line, CPUs can be brought online late, so we
>> > might need this in a hotplug callback (and/or in the arm64 cpufeature
>> > framework) to handle that case.
>> 
>> I'm afraid that won't be enough. If the CPU is brought up once we've
>> already started a VM, we're screwed, as we cannot retroactively decide
>> to drop GICv4 on the floor and nuke the guest. Or did you have something
>> more radical in mind? Panic?
>
> If you teach the arm64 cpufeature framework about this, it can abort bringing a
> !GICv4 CPU online late.

You wish.

There is all kind of difficulties with that. This requires checking an
EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
call facility). We could make it an additional hyp-stub feature, but
that feels pretty involved.

Effectively, GICv4 support having it supported on the redistributors,
the ITSs, and the CPUs. The cpufeature framework only addresses the
first one. So unless the solution encompasses all the elements in the
chain, any checking feels pretty pointless.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-27  7:59           ` Marc Zyngier
@ 2017-10-27  8:04             ` Mark Rutland
  -1 siblings, 0 replies; 117+ messages in thread
From: Mark Rutland @ 2017-10-27  8:04 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> >
> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >> >>  
> >> >> -	/* GICv4 support? */
> >> >> +	/*
> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
> >> >> +	 * extremely creative form of big-little brain damage...
> >> >> +	 */
> >> >>  	if (info->has_v4) {
> >> >> +		int cpu;
> >> >> +
> >> >> +		for_each_online_cpu(cpu) {
> >> >> +			bool enable;
> >> >> +
> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> >> >> +						 &enable, 1);
> >> >> +			gicv4_enable = gicv4_enable && enable;
> >> >> +		}
> >> >
> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
> >> > framework) to handle that case.
> >> 
> >> I'm afraid that won't be enough. If the CPU is brought up once we've
> >> already started a VM, we're screwed, as we cannot retroactively decide
> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
> >> more radical in mind? Panic?
> >
> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
> > !GICv4 CPU online late.
> 
> You wish.
> 
> There is all kind of difficulties with that. This requires checking an
> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
> call facility). We could make it an additional hyp-stub feature, but
> that feels pretty involved.

Aargh; I'd assumed we could probe this from EL1 somewhow.

> Effectively, GICv4 support having it supported on the redistributors,
> the ITSs, and the CPUs. The cpufeature framework only addresses the
> first one. So unless the solution encompasses all the elements in the
> chain, any checking feels pretty pointless.

Sure thing. :/

Thanks,
Mark.

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  8:04             ` Mark Rutland
  0 siblings, 0 replies; 117+ messages in thread
From: Mark Rutland @ 2017-10-27  8:04 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> >
> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >> >>  
> >> >> -	/* GICv4 support? */
> >> >> +	/*
> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
> >> >> +	 * extremely creative form of big-little brain damage...
> >> >> +	 */
> >> >>  	if (info->has_v4) {
> >> >> +		int cpu;
> >> >> +
> >> >> +		for_each_online_cpu(cpu) {
> >> >> +			bool enable;
> >> >> +
> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> >> >> +						 &enable, 1);
> >> >> +			gicv4_enable = gicv4_enable && enable;
> >> >> +		}
> >> >
> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
> >> > framework) to handle that case.
> >> 
> >> I'm afraid that won't be enough. If the CPU is brought up once we've
> >> already started a VM, we're screwed, as we cannot retroactively decide
> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
> >> more radical in mind? Panic?
> >
> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
> > !GICv4 CPU online late.
> 
> You wish.
> 
> There is all kind of difficulties with that. This requires checking an
> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
> call facility). We could make it an additional hyp-stub feature, but
> that feels pretty involved.

Aargh; I'd assumed we could probe this from EL1 somewhow.

> Effectively, GICv4 support having it supported on the redistributors,
> the ITSs, and the CPUs. The cpufeature framework only addresses the
> first one. So unless the solution encompasses all the elements in the
> chain, any checking feels pretty pointless.

Sure thing. :/

Thanks,
Mark.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-27  8:04             ` Mark Rutland
  (?)
@ 2017-10-27  8:31               ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  8:31 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Fri, Oct 27 2017 at  9:04:21 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
>> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
>> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>> >
>> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>> >> >>  
>> >> >> -	/* GICv4 support? */
>> >> >> +	/*
>> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
>> >> >> +	 * extremely creative form of big-little brain damage...
>> >> >> +	 */
>> >> >>  	if (info->has_v4) {
>> >> >> +		int cpu;
>> >> >> +
>> >> >> +		for_each_online_cpu(cpu) {
>> >> >> +			bool enable;
>> >> >> +
>> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> >> >> +						 &enable, 1);
>> >> >> +			gicv4_enable = gicv4_enable && enable;
>> >> >> +		}
>> >> >
>> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
>> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
>> >> > framework) to handle that case.
>> >> 
>> >> I'm afraid that won't be enough. If the CPU is brought up once we've
>> >> already started a VM, we're screwed, as we cannot retroactively decide
>> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
>> >> more radical in mind? Panic?
>> >
>> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
>> > !GICv4 CPU online late.
>> 
>> You wish.
>> 
>> There is all kind of difficulties with that. This requires checking an
>> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
>> call facility). We could make it an additional hyp-stub feature, but
>> that feels pretty involved.
>
> Aargh; I'd assumed we could probe this from EL1 somewhow.
>
>> Effectively, GICv4 support having it supported on the redistributors,
>> the ITSs, and the CPUs. The cpufeature framework only addresses the
>> first one. So unless the solution encompasses all the elements in the
>> chain, any checking feels pretty pointless.
>
> Sure thing. :/

How are we taking this further?

I can drop this altogether (after all, you will get what you deserve if
you design a broken system). The alternative would be to add a hotplug
notifier here, and spit out a warning if we're going to be in
trouble. We still run into the risk of messing with a VM that's already
been started before the non-v4 CPU.

Thoughts anyone?

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  8:31               ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  8:31 UTC (permalink / raw)
  To: Mark Rutland
  Cc: linux-arm-kernel, kvmarm, kvm, Christoffer Dall, Eric Auger,
	Shanker Donthineni, Shameerali Kolothum Thodi, Andre Przywara

On Fri, Oct 27 2017 at  9:04:21 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
>> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
>> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>> >
>> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>> >> >>  
>> >> >> -	/* GICv4 support? */
>> >> >> +	/*
>> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
>> >> >> +	 * extremely creative form of big-little brain damage...
>> >> >> +	 */
>> >> >>  	if (info->has_v4) {
>> >> >> +		int cpu;
>> >> >> +
>> >> >> +		for_each_online_cpu(cpu) {
>> >> >> +			bool enable;
>> >> >> +
>> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> >> >> +						 &enable, 1);
>> >> >> +			gicv4_enable = gicv4_enable && enable;
>> >> >> +		}
>> >> >
>> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
>> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
>> >> > framework) to handle that case.
>> >> 
>> >> I'm afraid that won't be enough. If the CPU is brought up once we've
>> >> already started a VM, we're screwed, as we cannot retroactively decide
>> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
>> >> more radical in mind? Panic?
>> >
>> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
>> > !GICv4 CPU online late.
>> 
>> You wish.
>> 
>> There is all kind of difficulties with that. This requires checking an
>> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
>> call facility). We could make it an additional hyp-stub feature, but
>> that feels pretty involved.
>
> Aargh; I'd assumed we could probe this from EL1 somewhow.
>
>> Effectively, GICv4 support having it supported on the redistributors,
>> the ITSs, and the CPUs. The cpufeature framework only addresses the
>> first one. So unless the solution encompasses all the elements in the
>> chain, any checking feels pretty pointless.
>
> Sure thing. :/

How are we taking this further?

I can drop this altogether (after all, you will get what you deserve if
you design a broken system). The alternative would be to add a hotplug
notifier here, and spit out a warning if we're going to be in
trouble. We still run into the risk of messing with a VM that's already
been started before the non-v4 CPU.

Thoughts anyone?

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-27  8:31               ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27  8:31 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 27 2017 at  9:04:21 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
>> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
>> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
>> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
>> >
>> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
>> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
>> >> >>  
>> >> >> -	/* GICv4 support? */
>> >> >> +	/*
>> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
>> >> >> +	 * extremely creative form of big-little brain damage...
>> >> >> +	 */
>> >> >>  	if (info->has_v4) {
>> >> >> +		int cpu;
>> >> >> +
>> >> >> +		for_each_online_cpu(cpu) {
>> >> >> +			bool enable;
>> >> >> +
>> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
>> >> >> +						 &enable, 1);
>> >> >> +			gicv4_enable = gicv4_enable && enable;
>> >> >> +		}
>> >> >
>> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
>> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
>> >> > framework) to handle that case.
>> >> 
>> >> I'm afraid that won't be enough. If the CPU is brought up once we've
>> >> already started a VM, we're screwed, as we cannot retroactively decide
>> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
>> >> more radical in mind? Panic?
>> >
>> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
>> > !GICv4 CPU online late.
>> 
>> You wish.
>> 
>> There is all kind of difficulties with that. This requires checking an
>> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
>> call facility). We could make it an additional hyp-stub feature, but
>> that feels pretty involved.
>
> Aargh; I'd assumed we could probe this from EL1 somewhow.
>
>> Effectively, GICv4 support having it supported on the redistributors,
>> the ITSs, and the CPUs. The cpufeature framework only addresses the
>> first one. So unless the solution encompasses all the elements in the
>> chain, any checking feels pretty pointless.
>
> Sure thing. :/

How are we taking this further?

I can drop this altogether (after all, you will get what you deserve if
you design a broken system). The alternative would be to add a hotplug
notifier here, and spit out a warning if we're going to be in
trouble. We still run into the risk of messing with a VM that's already
been started before the non-v4 CPU.

Thoughts anyone?

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
  2017-10-26 15:28     ` Christoffer Dall
@ 2017-10-27 13:56       ` Marc Zyngier
  -1 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27 13:56 UTC (permalink / raw)
  To: Christoffer Dall; +Cc: Andre Przywara, kvmarm, linux-arm-kernel, kvm

On Thu, Oct 26 2017 at  5:28:28 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> On Fri, Oct 06, 2017 at 04:33:58PM +0100, Marc Zyngier wrote:
>> The GICv4 architecture doesn't make it easy for save/restore to
>> work, as it doesn't give any guarantee that the pending state
>> is written into the pending table.
>> 
>> So let's not take any chance, and let's return an error if
>> we encounter any LPI that has the HW bit set.
>> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>> 
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index f434748439ee..01aa4d9d405e 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
>>  	list_for_each_entry(ite, &device->itt_head, ite_list) {
>>  		gpa_t gpa = base + ite->event_id * ite_esz;
>>  
>> +		/*
>> +		 * If an LPI carries the HW bit, this means that this
>> +		 * interrupt is controlled by GICv4, and we do not
>> +		 * have direct access to that state. Let's simply fail
>> +		 * the save operation...
>> +		 */
>> +		if (ite->irq->hw)
>> +			return -EINVAL;
>
> Will this conflict with other error messages, and will QEMU have a
> reasonable way to tell the user what's going on?
>
> Perhaps we shoul document the return code in the ITS device doc and
> choose something unique, like -EBUSY?

Yup. I've now switched to -EACCES, which is probably the least horrible
among the error codes we're not using yet. I've also amended the
documentation to that effect.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
@ 2017-10-27 13:56       ` Marc Zyngier
  0 siblings, 0 replies; 117+ messages in thread
From: Marc Zyngier @ 2017-10-27 13:56 UTC (permalink / raw)
  To: linux-arm-kernel

On Thu, Oct 26 2017 at  5:28:28 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> On Fri, Oct 06, 2017 at 04:33:58PM +0100, Marc Zyngier wrote:
>> The GICv4 architecture doesn't make it easy for save/restore to
>> work, as it doesn't give any guarantee that the pending state
>> is written into the pending table.
>> 
>> So let's not take any chance, and let's return an error if
>> we encounter any LPI that has the HW bit set.
>> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
>>  1 file changed, 9 insertions(+)
>> 
>> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
>> index f434748439ee..01aa4d9d405e 100644
>> --- a/virt/kvm/arm/vgic/vgic-its.c
>> +++ b/virt/kvm/arm/vgic/vgic-its.c
>> @@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
>>  	list_for_each_entry(ite, &device->itt_head, ite_list) {
>>  		gpa_t gpa = base + ite->event_id * ite_esz;
>>  
>> +		/*
>> +		 * If an LPI carries the HW bit, this means that this
>> +		 * interrupt is controlled by GICv4, and we do not
>> +		 * have direct access to that state. Let's simply fail
>> +		 * the save operation...
>> +		 */
>> +		if (ite->irq->hw)
>> +			return -EINVAL;
>
> Will this conflict with other error messages, and will QEMU have a
> reasonable way to tell the user what's going on?
>
> Perhaps we shoul document the return code in the ITS device doc and
> choose something unique, like -EBUSY?

Yup. I've now switched to -EACCES, which is probably the least horrible
among the error codes we're not using yet. I've also amended the
documentation to that effect.

Thanks,

	M.
-- 
Jazz is not dead. It just smells funny.

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

* Re: [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
  2017-10-27  8:31               ` Marc Zyngier
@ 2017-10-29  2:16                 ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-29  2:16 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: kvm, Andre Przywara, linux-arm-kernel, kvmarm

On Fri, Oct 27, 2017 at 09:31:12AM +0100, Marc Zyngier wrote:
> On Fri, Oct 27 2017 at  9:04:21 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
> >> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> >> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
> >> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> >> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> >> >
> >> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
> >> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >> >> >>  
> >> >> >> -	/* GICv4 support? */
> >> >> >> +	/*
> >> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
> >> >> >> +	 * extremely creative form of big-little brain damage...
> >> >> >> +	 */
> >> >> >>  	if (info->has_v4) {
> >> >> >> +		int cpu;
> >> >> >> +
> >> >> >> +		for_each_online_cpu(cpu) {
> >> >> >> +			bool enable;
> >> >> >> +
> >> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> >> >> >> +						 &enable, 1);
> >> >> >> +			gicv4_enable = gicv4_enable && enable;
> >> >> >> +		}
> >> >> >
> >> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
> >> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
> >> >> > framework) to handle that case.
> >> >> 
> >> >> I'm afraid that won't be enough. If the CPU is brought up once we've
> >> >> already started a VM, we're screwed, as we cannot retroactively decide
> >> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
> >> >> more radical in mind? Panic?
> >> >
> >> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
> >> > !GICv4 CPU online late.
> >> 
> >> You wish.
> >> 
> >> There is all kind of difficulties with that. This requires checking an
> >> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
> >> call facility). We could make it an additional hyp-stub feature, but
> >> that feels pretty involved.
> >
> > Aargh; I'd assumed we could probe this from EL1 somewhow.
> >
> >> Effectively, GICv4 support having it supported on the redistributors,
> >> the ITSs, and the CPUs. The cpufeature framework only addresses the
> >> first one. So unless the solution encompasses all the elements in the
> >> chain, any checking feels pretty pointless.
> >
> > Sure thing. :/
> 
> How are we taking this further?
> 
> I can drop this altogether (after all, you will get what you deserve if
> you design a broken system). The alternative would be to add a hotplug
> notifier here, and spit out a warning if we're going to be in
> trouble. We still run into the risk of messing with a VM that's already
> been started before the non-v4 CPU.
> 
> Thoughts anyone?
> 
I think it's fine to drop the check like you do in v5, and if platforms
that actually have this problem show up and we need to detect against
bringing certain CPUs online, we can have a look at building a massive
control-infrastructure then.

Thanks,
-Christoffer

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

* [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4
@ 2017-10-29  2:16                 ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-29  2:16 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 27, 2017 at 09:31:12AM +0100, Marc Zyngier wrote:
> On Fri, Oct 27 2017 at  9:04:21 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> > On Fri, Oct 27, 2017 at 08:59:23AM +0100, Marc Zyngier wrote:
> >> On Fri, Oct 27 2017 at  8:37:28 am BST, Mark Rutland <mark.rutland@arm.com> wrote:
> >> > On Fri, Oct 27, 2017 at 07:57:12AM +0100, Marc Zyngier wrote:
> >> >> On Thu, Oct 26 2017 at  4:48:39 pm BST, Mark Rutland <mark.rutland@arm.com> wrote:
> >> >> > On Fri, Oct 06, 2017 at 04:34:00PM +0100, Marc Zyngier wrote:
> >> >
> >> >> >> @@ -485,8 +495,21 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
> >> >> >>  	kvm_vgic_global_state.can_emulate_gicv2 = false;
> >> >> >>  	kvm_vgic_global_state.ich_vtr_el2 = ich_vtr_el2;
> >> >> >>  
> >> >> >> -	/* GICv4 support? */
> >> >> >> +	/*
> >> >> >> +	 * GICv4 support? We need to check on all CPUs in case of some
> >> >> >> +	 * extremely creative form of big-little brain damage...
> >> >> >> +	 */
> >> >> >>  	if (info->has_v4) {
> >> >> >> +		int cpu;
> >> >> >> +
> >> >> >> +		for_each_online_cpu(cpu) {
> >> >> >> +			bool enable;
> >> >> >> +
> >> >> >> +			smp_call_function_single(cpu, vgic_check_v4_cpuif,
> >> >> >> +						 &enable, 1);
> >> >> >> +			gicv4_enable = gicv4_enable && enable;
> >> >> >> +		}
> >> >> >
> >> >> > With maxcpus=N on the command line, CPUs can be brought online late, so we
> >> >> > might need this in a hotplug callback (and/or in the arm64 cpufeature
> >> >> > framework) to handle that case.
> >> >> 
> >> >> I'm afraid that won't be enough. If the CPU is brought up once we've
> >> >> already started a VM, we're screwed, as we cannot retroactively decide
> >> >> to drop GICv4 on the floor and nuke the guest. Or did you have something
> >> >> more radical in mind? Panic?
> >> >
> >> > If you teach the arm64 cpufeature framework about this, it can abort bringing a
> >> > !GICv4 CPU online late.
> >> 
> >> You wish.
> >> 
> >> There is all kind of difficulties with that. This requires checking an
> >> EL2 register (ICH_VTR_EL2) when we've not initialised KVM yet (so no HYP
> >> call facility). We could make it an additional hyp-stub feature, but
> >> that feels pretty involved.
> >
> > Aargh; I'd assumed we could probe this from EL1 somewhow.
> >
> >> Effectively, GICv4 support having it supported on the redistributors,
> >> the ITSs, and the CPUs. The cpufeature framework only addresses the
> >> first one. So unless the solution encompasses all the elements in the
> >> chain, any checking feels pretty pointless.
> >
> > Sure thing. :/
> 
> How are we taking this further?
> 
> I can drop this altogether (after all, you will get what you deserve if
> you design a broken system). The alternative would be to add a hotplug
> notifier here, and spit out a warning if we're going to be in
> trouble. We still run into the risk of messing with a VM that's already
> been started before the non-v4 CPU.
> 
> Thoughts anyone?
> 
I think it's fine to drop the check like you do in v5, and if platforms
that actually have this problem show up and we need to detect against
bringing certain CPUs online, we can have a look at building a massive
control-infrastructure then.

Thanks,
-Christoffer

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

* Re: [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
  2017-10-27 13:56       ` Marc Zyngier
@ 2017-10-30  6:48         ` Christoffer Dall
  -1 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-30  6:48 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: linux-arm-kernel, kvmarm, kvm, Andre Przywara

On Fri, Oct 27, 2017 at 02:56:10PM +0100, Marc Zyngier wrote:
> On Thu, Oct 26 2017 at  5:28:28 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> > On Fri, Oct 06, 2017 at 04:33:58PM +0100, Marc Zyngier wrote:
> >> The GICv4 architecture doesn't make it easy for save/restore to
> >> work, as it doesn't give any guarantee that the pending state
> >> is written into the pending table.
> >> 
> >> So let's not take any chance, and let's return an error if
> >> we encounter any LPI that has the HW bit set.
> >> 
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >>  virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
> >>  1 file changed, 9 insertions(+)
> >> 
> >> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> >> index f434748439ee..01aa4d9d405e 100644
> >> --- a/virt/kvm/arm/vgic/vgic-its.c
> >> +++ b/virt/kvm/arm/vgic/vgic-its.c
> >> @@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
> >>  	list_for_each_entry(ite, &device->itt_head, ite_list) {
> >>  		gpa_t gpa = base + ite->event_id * ite_esz;
> >>  
> >> +		/*
> >> +		 * If an LPI carries the HW bit, this means that this
> >> +		 * interrupt is controlled by GICv4, and we do not
> >> +		 * have direct access to that state. Let's simply fail
> >> +		 * the save operation...
> >> +		 */
> >> +		if (ite->irq->hw)
> >> +			return -EINVAL;
> >
> > Will this conflict with other error messages, and will QEMU have a
> > reasonable way to tell the user what's going on?
> >
> > Perhaps we shoul document the return code in the ITS device doc and
> > choose something unique, like -EBUSY?
> 
> Yup. I've now switched to -EACCES, which is probably the least horrible
> among the error codes we're not using yet. I've also amended the
> documentation to that effect.
> 

Sounds good.  -EJUSTANUMBER.

Thanks,
-Christoffer

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

* [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved
@ 2017-10-30  6:48         ` Christoffer Dall
  0 siblings, 0 replies; 117+ messages in thread
From: Christoffer Dall @ 2017-10-30  6:48 UTC (permalink / raw)
  To: linux-arm-kernel

On Fri, Oct 27, 2017 at 02:56:10PM +0100, Marc Zyngier wrote:
> On Thu, Oct 26 2017 at  5:28:28 pm BST, Christoffer Dall <cdall@linaro.org> wrote:
> > On Fri, Oct 06, 2017 at 04:33:58PM +0100, Marc Zyngier wrote:
> >> The GICv4 architecture doesn't make it easy for save/restore to
> >> work, as it doesn't give any guarantee that the pending state
> >> is written into the pending table.
> >> 
> >> So let's not take any chance, and let's return an error if
> >> we encounter any LPI that has the HW bit set.
> >> 
> >> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >> ---
> >>  virt/kvm/arm/vgic/vgic-its.c | 9 +++++++++
> >>  1 file changed, 9 insertions(+)
> >> 
> >> diff --git a/virt/kvm/arm/vgic/vgic-its.c b/virt/kvm/arm/vgic/vgic-its.c
> >> index f434748439ee..01aa4d9d405e 100644
> >> --- a/virt/kvm/arm/vgic/vgic-its.c
> >> +++ b/virt/kvm/arm/vgic/vgic-its.c
> >> @@ -1987,6 +1987,15 @@ static int vgic_its_save_itt(struct vgic_its *its, struct its_device *device)
> >>  	list_for_each_entry(ite, &device->itt_head, ite_list) {
> >>  		gpa_t gpa = base + ite->event_id * ite_esz;
> >>  
> >> +		/*
> >> +		 * If an LPI carries the HW bit, this means that this
> >> +		 * interrupt is controlled by GICv4, and we do not
> >> +		 * have direct access to that state. Let's simply fail
> >> +		 * the save operation...
> >> +		 */
> >> +		if (ite->irq->hw)
> >> +			return -EINVAL;
> >
> > Will this conflict with other error messages, and will QEMU have a
> > reasonable way to tell the user what's going on?
> >
> > Perhaps we shoul document the return code in the ITS device doc and
> > choose something unique, like -EBUSY?
> 
> Yup. I've now switched to -EACCES, which is probably the least horrible
> among the error codes we're not using yet. I've also amended the
> documentation to that effect.
> 

Sounds good.  -EJUSTANUMBER.

Thanks,
-Christoffer

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

end of thread, other threads:[~2017-10-30  6:48 UTC | newest]

Thread overview: 117+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-06 15:33 [PATCH v4 00/26] KVM/ARM: Add support for GICv4 Marc Zyngier
2017-10-06 15:33 ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 01/26] KVM: arm/arm64: register irq bypass consumer on ARM/ARM64 Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 02/26] KVM: arm/arm64: vgic: restructure kvm_vgic_(un)map_phys_irq Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 14:44   ` Christoffer Dall
2017-10-25 14:44     ` Christoffer Dall
2017-10-26 13:05     ` Marc Zyngier
2017-10-26 13:05       ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 03/26] KVM: arm: Select ARM_GIC_V3 and ARM_GIC_V3_ITS Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 04/26] KVM: arm/arm64: vgic: Move kvm_vgic_destroy call around Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 05/26] KVM: arm/arm64: vITS: Add MSI translation helpers Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 06/26] KVM: arm/arm64: vITS: Add a helper to update the affinity of an LPI Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 14:50   ` Christoffer Dall
2017-10-25 14:50     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 07/26] KVM: arm/arm64: GICv4: Add property field and per-VM predicate Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 14:54   ` Christoffer Dall
2017-10-25 14:54     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 08/26] KVM: arm/arm64: GICv4: Add init/teardown of the per-VM vPE irq domain Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 15:46   ` Christoffer Dall
2017-10-25 15:46     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 09/26] KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 15:58   ` Christoffer Dall
2017-10-25 15:58     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 10/26] KVM: arm/arm64: GICv4: Handle INT command applied to a VLPI Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 11/26] KVM: arm/arm64: GICv4: Unmap VLPI when freeing an LPI Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 12/26] KVM: arm/arm64: GICv4: Propagate affinity changes to the physical ITS Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 16:22   ` Christoffer Dall
2017-10-25 16:22     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 13/26] KVM: arm/arm64: GICv4: Handle CLEAR applied to a VLPI Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 14/26] KVM: arm/arm64: GICv4: Handle MOVALL applied to a vPE Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 16:27   ` Christoffer Dall
2017-10-25 16:27     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 15/26] KVM: arm/arm64: GICv4: Propagate property updates to VLPIs Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 16/26] KVM: arm/arm64: GICv4: Handle INVALL applied to a vPE Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 17/26] KVM: arm/arm64: GICv4: Propagate VLPI properties at map time Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-25 16:48   ` Christoffer Dall
2017-10-25 16:48     ` Christoffer Dall
2017-10-25 17:01     ` Marc Zyngier
2017-10-25 17:01       ` Marc Zyngier
2017-10-26  8:21       ` Marc Zyngier
2017-10-26  8:21         ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 18/26] KVM: arm/arm64: GICv4: Use pending_last as a scheduling hint Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 19/26] KVM: arm/arm64: GICv4: Add doorbell interrupt handling Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-26 14:28   ` Christoffer Dall
2017-10-26 14:28     ` Christoffer Dall
2017-10-26 15:25   ` Christoffer Dall
2017-10-26 15:25     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 20/26] KVM: arm/arm64: GICv4: Use the doorbell interrupt as an unblocking source Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 21/26] KVM: arm/arm64: GICv4: Hook vPE scheduling into vgic flush/sync Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-26 15:24   ` Christoffer Dall
2017-10-26 15:24     ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 22/26] KVM: arm/arm64: GICv4: Enable virtual cpuif if VLPIs can be delivered Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:33 ` [PATCH v4 23/26] KVM: arm/arm64: GICv4: Prevent a VM using GICv4 from being saved Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-26 15:28   ` Christoffer Dall
2017-10-26 15:28     ` Christoffer Dall
2017-10-27 13:56     ` Marc Zyngier
2017-10-27 13:56       ` Marc Zyngier
2017-10-30  6:48       ` Christoffer Dall
2017-10-30  6:48         ` Christoffer Dall
2017-10-06 15:33 ` [PATCH v4 24/26] KVM: arm/arm64: GICv4: Enable VLPI support Marc Zyngier
2017-10-06 15:33   ` Marc Zyngier
2017-10-06 15:34 ` [PATCH v4 25/26] KVM: arm/arm64: GICv4: Prevent heterogenous systems from using GICv4 Marc Zyngier
2017-10-06 15:34   ` Marc Zyngier
2017-10-26 15:31   ` Christoffer Dall
2017-10-26 15:31     ` Christoffer Dall
2017-10-26 15:48   ` Mark Rutland
2017-10-26 15:48     ` Mark Rutland
2017-10-27  6:57     ` Marc Zyngier
2017-10-27  6:57       ` Marc Zyngier
2017-10-27  6:57       ` Marc Zyngier
2017-10-27  7:37       ` Mark Rutland
2017-10-27  7:37         ` Mark Rutland
2017-10-27  7:59         ` Marc Zyngier
2017-10-27  7:59           ` Marc Zyngier
2017-10-27  7:59           ` Marc Zyngier
2017-10-27  8:04           ` Mark Rutland
2017-10-27  8:04             ` Mark Rutland
2017-10-27  8:31             ` Marc Zyngier
2017-10-27  8:31               ` Marc Zyngier
2017-10-27  8:31               ` Marc Zyngier
2017-10-29  2:16               ` Christoffer Dall
2017-10-29  2:16                 ` Christoffer Dall
2017-10-06 15:34 ` [PATCH v4 26/26] KVM: arm/arm64: GICv4: Theory of operations Marc Zyngier
2017-10-06 15:34   ` Marc Zyngier
2017-10-26 15:32   ` Christoffer Dall
2017-10-26 15:32     ` Christoffer Dall
2017-10-08 16:45 ` [PATCH v4 00/26] KVM/ARM: Add support for GICv4 Shanker Donthineni
2017-10-08 16:45   ` Shanker Donthineni
2017-10-09 17:52 ` Konrad Rzeszutek Wilk
2017-10-09 17:52   ` Konrad Rzeszutek Wilk
2017-10-09 18:02   ` Marc Zyngier
2017-10-09 18:02     ` Marc Zyngier
2017-10-19 15:48 ` [PATCH v4 27/26] KVM: arm/arm64: GICv4: Prevent userspace from changing doorbell affinity Marc Zyngier
2017-10-19 15:48   ` Marc Zyngier

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.