All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2
@ 2017-05-03 10:45 ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: David Daney, Catalin Marinas, Mark Rutland, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

[Apologies for posting this at the beginning of a merge window, but as
 this is a rather hot topic, I'd rather put it out as soon as possible]

Some systems have less than perfect GICv3 implementations, leading to
all kind of ugly issues (guest hanging, host dying). In order to allow
some level of diagnostic, and in some cases implement workarounds,
this series enables the trapping of both Group-0, Group-1 and Common
sysregs. Mediating the access at EL2 allows some form of sanity
checking that the HW is sometimes sorely lacking.

Instead of fully emulating a GICv3 CPU interface, we still use the
existing HW (list registers, AP registers, VMCR...), which allows the
code to be independent from the rest of the KVM code, and to cope with
partial trapping.

Of course, trapping has a cost, which is why this must be either
enabled on the command line, or selected by another cpu capability
(see Cavium erratum 30115). A quick test on an A57-based platform
shows a 25% hit when repeatedly banging on the trapped registers,
while normal workloads do not seem to suffer noticeably from such
trapping (hackbench variance is in the usual noise, despite being very
IPI happy).

This has been tested on a dual socket Thundex-X and a Freescale LS-2085a.

The first 6 patches are fixes, and only here for reference as they
have already been posted separately. The rest of the patches implement
Group-1, Group-0 and Common sysreg handlers, with the corresponding
command line options. I've also taken the liberty to rebase David
Daney's initial Cavium erratum 30115 workaround on top of this series,
and included it here as a typical use case.

David Daney (2):
  arm64: Add MIDR values for Cavium cn83XX SoCs
  arm64: Add workaround for Cavium Thunder erratum 30115

Marc Zyngier (29):
  arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses
  arm64: KVM: Do not use stack-protector to compile EL2 code
  arm: KVM: Do not use stack-protector to compile HYP code
  KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW
    interrupt
  KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW
    interrupt
  KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of
    ICH_APxRn_EL2 registers
  KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
  KVM: arm64: Make kvm_condition_valid32() accessible from EL2
  KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at
    EL2
  KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
  KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
  KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
  KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
  KVM: arm64: vgic-v3: Add misc Group-0 handlers
  KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
  KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
  KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
  KVM: arm64: Enable GICv3 common sysreg trapping via command-line
  KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped

 Documentation/arm64/silicon-errata.txt |   1 +
 arch/arm/kvm/hyp/Makefile              |   2 +
 arch/arm64/Kconfig                     |  11 +
 arch/arm64/include/asm/cpucaps.h       |   3 +-
 arch/arm64/include/asm/cputype.h       |   2 +
 arch/arm64/include/asm/esr.h           |  25 ++
 arch/arm64/include/asm/kvm_emulate.h   |   6 +
 arch/arm64/include/asm/kvm_hyp.h       |   1 +
 arch/arm64/include/asm/sysreg.h        |   9 +
 arch/arm64/kernel/cpu_errata.c         |  21 +
 arch/arm64/kvm/hyp/Makefile            |   2 +
 arch/arm64/kvm/hyp/switch.c            |  14 +
 arch/arm64/kvm/sys_regs.c              |   8 +-
 include/kvm/arm_vgic.h                 |   1 +
 include/linux/irqchip/arm-gic-v3.h     |   6 +
 virt/kvm/arm/aarch32.c                 |   2 +-
 virt/kvm/arm/hyp/vgic-v3-sr.c          | 792 +++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-v2.c            |   7 +
 virt/kvm/arm/vgic/vgic-v3.c            |  52 +++
 19 files changed, 934 insertions(+), 31 deletions(-)

-- 
2.11.0

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

* [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2
@ 2017-05-03 10:45 ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

[Apologies for posting this at the beginning of a merge window, but as
 this is a rather hot topic, I'd rather put it out as soon as possible]

Some systems have less than perfect GICv3 implementations, leading to
all kind of ugly issues (guest hanging, host dying). In order to allow
some level of diagnostic, and in some cases implement workarounds,
this series enables the trapping of both Group-0, Group-1 and Common
sysregs. Mediating the access at EL2 allows some form of sanity
checking that the HW is sometimes sorely lacking.

Instead of fully emulating a GICv3 CPU interface, we still use the
existing HW (list registers, AP registers, VMCR...), which allows the
code to be independent from the rest of the KVM code, and to cope with
partial trapping.

Of course, trapping has a cost, which is why this must be either
enabled on the command line, or selected by another cpu capability
(see Cavium erratum 30115). A quick test on an A57-based platform
shows a 25% hit when repeatedly banging on the trapped registers,
while normal workloads do not seem to suffer noticeably from such
trapping (hackbench variance is in the usual noise, despite being very
IPI happy).

This has been tested on a dual socket Thundex-X and a Freescale LS-2085a.

The first 6 patches are fixes, and only here for reference as they
have already been posted separately. The rest of the patches implement
Group-1, Group-0 and Common sysreg handlers, with the corresponding
command line options. I've also taken the liberty to rebase David
Daney's initial Cavium erratum 30115 workaround on top of this series,
and included it here as a typical use case.

David Daney (2):
  arm64: Add MIDR values for Cavium cn83XX SoCs
  arm64: Add workaround for Cavium Thunder erratum 30115

Marc Zyngier (29):
  arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses
  arm64: KVM: Do not use stack-protector to compile EL2 code
  arm: KVM: Do not use stack-protector to compile HYP code
  KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW
    interrupt
  KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW
    interrupt
  KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of
    ICH_APxRn_EL2 registers
  KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
  KVM: arm64: Make kvm_condition_valid32() accessible from EL2
  KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at
    EL2
  KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
  KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
  KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
  KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
  KVM: arm64: vgic-v3: Add misc Group-0 handlers
  KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
  KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
  KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
  KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
  KVM: arm64: Enable GICv3 common sysreg trapping via command-line
  KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped

 Documentation/arm64/silicon-errata.txt |   1 +
 arch/arm/kvm/hyp/Makefile              |   2 +
 arch/arm64/Kconfig                     |  11 +
 arch/arm64/include/asm/cpucaps.h       |   3 +-
 arch/arm64/include/asm/cputype.h       |   2 +
 arch/arm64/include/asm/esr.h           |  25 ++
 arch/arm64/include/asm/kvm_emulate.h   |   6 +
 arch/arm64/include/asm/kvm_hyp.h       |   1 +
 arch/arm64/include/asm/sysreg.h        |   9 +
 arch/arm64/kernel/cpu_errata.c         |  21 +
 arch/arm64/kvm/hyp/Makefile            |   2 +
 arch/arm64/kvm/hyp/switch.c            |  14 +
 arch/arm64/kvm/sys_regs.c              |   8 +-
 include/kvm/arm_vgic.h                 |   1 +
 include/linux/irqchip/arm-gic-v3.h     |   6 +
 virt/kvm/arm/aarch32.c                 |   2 +-
 virt/kvm/arm/hyp/vgic-v3-sr.c          | 792 +++++++++++++++++++++++++++++++--
 virt/kvm/arm/vgic/vgic-v2.c            |   7 +
 virt/kvm/arm/vgic/vgic-v3.c            |  52 +++
 19 files changed, 934 insertions(+), 31 deletions(-)

-- 
2.11.0

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

* [PATCH 01/31] arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Our 32bit CP14/15 handling inherited some of the ARMv7 code for handling
the trapped system registers, completely missing the fact that the
fields for Rt and Rt2 are now 5 bit wide, and not 4...

Let's fix it, and provide an accessor for the most common Rt case.

Cc: stable@vger.kernel.org
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_emulate.h | 6 ++++++
 arch/arm64/kvm/sys_regs.c            | 8 ++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index f5ea0ba70f07..fe39e6841326 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -240,6 +240,12 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
 	return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
+static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	return (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
+}
+
 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 {
 	return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index efbe9e8e7a78..0fe27024a2e1 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1529,8 +1529,8 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (hsr >> 5) & 0xf;
-	int Rt2 = (hsr >> 10) & 0xf;
+	int Rt = kvm_vcpu_sys_get_rt(vcpu);
+	int Rt2 = (hsr >> 10) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = false;
@@ -1586,7 +1586,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt  = (hsr >> 5) & 0xf;
+	int Rt  = kvm_vcpu_sys_get_rt(vcpu);
 
 	params.is_aarch32 = true;
 	params.is_32bit = true;
@@ -1688,7 +1688,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	struct sys_reg_params params;
 	unsigned long esr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (esr >> 5) & 0x1f;
+	int Rt = kvm_vcpu_sys_get_rt(vcpu);
 	int ret;
 
 	trace_kvm_handle_sys_reg(esr);
-- 
2.11.0

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

* [PATCH 01/31] arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Our 32bit CP14/15 handling inherited some of the ARMv7 code for handling
the trapped system registers, completely missing the fact that the
fields for Rt and Rt2 are now 5 bit wide, and not 4...

Let's fix it, and provide an accessor for the most common Rt case.

Cc: stable at vger.kernel.org
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_emulate.h | 6 ++++++
 arch/arm64/kvm/sys_regs.c            | 8 ++++----
 2 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index f5ea0ba70f07..fe39e6841326 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -240,6 +240,12 @@ static inline u8 kvm_vcpu_trap_get_fault_type(const struct kvm_vcpu *vcpu)
 	return kvm_vcpu_get_hsr(vcpu) & ESR_ELx_FSC_TYPE;
 }
 
+static inline int kvm_vcpu_sys_get_rt(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	return (esr & ESR_ELx_SYS64_ISS_RT_MASK) >> ESR_ELx_SYS64_ISS_RT_SHIFT;
+}
+
 static inline unsigned long kvm_vcpu_get_mpidr_aff(struct kvm_vcpu *vcpu)
 {
 	return vcpu_sys_reg(vcpu, MPIDR_EL1) & MPIDR_HWID_BITMASK;
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index efbe9e8e7a78..0fe27024a2e1 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -1529,8 +1529,8 @@ static int kvm_handle_cp_64(struct kvm_vcpu *vcpu,
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (hsr >> 5) & 0xf;
-	int Rt2 = (hsr >> 10) & 0xf;
+	int Rt = kvm_vcpu_sys_get_rt(vcpu);
+	int Rt2 = (hsr >> 10) & 0x1f;
 
 	params.is_aarch32 = true;
 	params.is_32bit = false;
@@ -1586,7 +1586,7 @@ static int kvm_handle_cp_32(struct kvm_vcpu *vcpu,
 {
 	struct sys_reg_params params;
 	u32 hsr = kvm_vcpu_get_hsr(vcpu);
-	int Rt  = (hsr >> 5) & 0xf;
+	int Rt  = kvm_vcpu_sys_get_rt(vcpu);
 
 	params.is_aarch32 = true;
 	params.is_32bit = true;
@@ -1688,7 +1688,7 @@ int kvm_handle_sys_reg(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
 	struct sys_reg_params params;
 	unsigned long esr = kvm_vcpu_get_hsr(vcpu);
-	int Rt = (esr >> 5) & 0x1f;
+	int Rt = kvm_vcpu_sys_get_rt(vcpu);
 	int ret;
 
 	trace_kvm_handle_sys_reg(esr);
-- 
2.11.0

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

* [PATCH 02/31] arm64: KVM: Do not use stack-protector to compile EL2 code
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: David Daney, Catalin Marinas, Mark Rutland, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

We like living dangerously. Nothing explicitely forbids stack-protector
to be used in the EL2 code, while distributions routinely compile their
kernel with it. We're just lucky that no code actually triggers the
instrumentation.

Let's not try our luck for much longer, and disable stack-protector
for code living at EL2.

Cc: stable@vger.kernel.org
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
index aaf42ae8d8c3..14c4e3b14bcb 100644
--- a/arch/arm64/kvm/hyp/Makefile
+++ b/arch/arm64/kvm/hyp/Makefile
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
-- 
2.11.0

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

* [PATCH 02/31] arm64: KVM: Do not use stack-protector to compile EL2 code
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

We like living dangerously. Nothing explicitely forbids stack-protector
to be used in the EL2 code, while distributions routinely compile their
kernel with it. We're just lucky that no code actually triggers the
instrumentation.

Let's not try our luck for much longer, and disable stack-protector
for code living at EL2.

Cc: stable at vger.kernel.org
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/kvm/hyp/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/kvm/hyp/Makefile b/arch/arm64/kvm/hyp/Makefile
index aaf42ae8d8c3..14c4e3b14bcb 100644
--- a/arch/arm64/kvm/hyp/Makefile
+++ b/arch/arm64/kvm/hyp/Makefile
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
-- 
2.11.0

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

* [PATCH 03/31] arm: KVM: Do not use stack-protector to compile HYP code
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

We like living dangerously. Nothing explicitely forbids stack-protector
to be used in the HYP code, while distributions routinely compile their
kernel with it. We're just lucky that no code actually triggers the
instrumentation.

Let's not try our luck for much longer, and disable stack-protector
for code living at HYP.

Cc: stable@vger.kernel.org
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/hyp/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile
index 3023bb530edf..8679405b0b2b 100644
--- a/arch/arm/kvm/hyp/Makefile
+++ b/arch/arm/kvm/hyp/Makefile
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
-- 
2.11.0

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

* [PATCH 03/31] arm: KVM: Do not use stack-protector to compile HYP code
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

We like living dangerously. Nothing explicitely forbids stack-protector
to be used in the HYP code, while distributions routinely compile their
kernel with it. We're just lucky that no code actually triggers the
instrumentation.

Let's not try our luck for much longer, and disable stack-protector
for code living at HYP.

Cc: stable at vger.kernel.org
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm/kvm/hyp/Makefile | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm/kvm/hyp/Makefile b/arch/arm/kvm/hyp/Makefile
index 3023bb530edf..8679405b0b2b 100644
--- a/arch/arm/kvm/hyp/Makefile
+++ b/arch/arm/kvm/hyp/Makefile
@@ -2,6 +2,8 @@
 # Makefile for Kernel-based Virtual Machine module, HYP part
 #
 
+ccflags-y += -fno-stack-protector
+
 KVM=../../../../virt/kvm
 
 obj-$(CONFIG_KVM_ARM_HOST) += $(KVM)/arm/hyp/vgic-v2-sr.o
-- 
2.11.0

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

* [PATCH 04/31] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: David Daney, Catalin Marinas, Mark Rutland, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

When an interrupt is injected with the HW bit set (indicating that
deactivation should be propagated to the physical distributor),
special care must be taken so that we never mark the corresponding
LR with the Active+Pending state (as the pending state is kept in
the physycal distributor).

Cc: stable@vger.kernel.org
Fixes: 140b086dd197 ("KVM: arm/arm64: vgic-new: Add GICv2 world switch backend")
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v2.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index a65757aab6d3..504b4bd0d651 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -149,6 +149,13 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
 	if (irq->hw) {
 		val |= GICH_LR_HW;
 		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+		/*
+		 * Never set pending+active on a HW interrupt, as the
+		 * pending state is kept at the physical distributor
+		 * level.
+		 */
+		if (irq->active && irq_is_pending(irq))
+			val &= ~GICH_LR_PENDING_BIT;
 	} else {
 		if (irq->config == VGIC_CONFIG_LEVEL)
 			val |= GICH_LR_EOI;
-- 
2.11.0

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

* [PATCH 04/31] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

When an interrupt is injected with the HW bit set (indicating that
deactivation should be propagated to the physical distributor),
special care must be taken so that we never mark the corresponding
LR with the Active+Pending state (as the pending state is kept in
the physycal distributor).

Cc: stable at vger.kernel.org
Fixes: 140b086dd197 ("KVM: arm/arm64: vgic-new: Add GICv2 world switch backend")
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v2.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index a65757aab6d3..504b4bd0d651 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -149,6 +149,13 @@ void vgic_v2_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
 	if (irq->hw) {
 		val |= GICH_LR_HW;
 		val |= irq->hwintid << GICH_LR_PHYSID_CPUID_SHIFT;
+		/*
+		 * Never set pending+active on a HW interrupt, as the
+		 * pending state is kept@the physical distributor
+		 * level.
+		 */
+		if (irq->active && irq_is_pending(irq))
+			val &= ~GICH_LR_PENDING_BIT;
 	} else {
 		if (irq->config == VGIC_CONFIG_LEVEL)
 			val |= GICH_LR_EOI;
-- 
2.11.0

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

* [PATCH 05/31] KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW interrupt
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: David Daney, Catalin Marinas, Mark Rutland, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

When an interrupt is injected with the HW bit set (indicating that
deactivation should be propagated to the physical distributor),
special care must be taken so that we never mark the corresponding
LR with the Active+Pending state (as the pending state is kept in
the physycal distributor).

Cc: stable@vger.kernel.org
Fixes: 59529f69f504 ("KVM: arm/arm64: vgic-new: Add GICv3 world switch backend")
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v3.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index df1503650300..393779ebe87c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -127,6 +127,13 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
 	if (irq->hw) {
 		val |= ICH_LR_HW;
 		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+		/*
+		 * Never set pending+active on a HW interrupt, as the
+		 * pending state is kept at the physical distributor
+		 * level.
+		 */
+		if (irq->active && irq_is_pending(irq))
+			val &= ~ICH_LR_PENDING_BIT;
 	} else {
 		if (irq->config == VGIC_CONFIG_LEVEL)
 			val |= ICH_LR_EOI;
-- 
2.11.0

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

* [PATCH 05/31] KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW interrupt
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

When an interrupt is injected with the HW bit set (indicating that
deactivation should be propagated to the physical distributor),
special care must be taken so that we never mark the corresponding
LR with the Active+Pending state (as the pending state is kept in
the physycal distributor).

Cc: stable at vger.kernel.org
Fixes: 59529f69f504 ("KVM: arm/arm64: vgic-new: Add GICv3 world switch backend")
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/vgic/vgic-v3.c | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index df1503650300..393779ebe87c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -127,6 +127,13 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
 	if (irq->hw) {
 		val |= ICH_LR_HW;
 		val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+		/*
+		 * Never set pending+active on a HW interrupt, as the
+		 * pending state is kept@the physical distributor
+		 * level.
+		 */
+		if (irq->active && irq_is_pending(irq))
+			val &= ~ICH_LR_PENDING_BIT;
 	} else {
 		if (irq->config == VGIC_CONFIG_LEVEL)
 			val |= ICH_LR_EOI;
-- 
2.11.0

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

* [PATCH 06/31] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

The GICv3 documentation is extremely confusing, as it talks about
the number of priorities represented by the ICH_APxRn_EL2 registers,
while it should really talk about the number of preemption levels.

This leads to a bug where we may access undefined ICH_APxRn_EL2
registers, since PREbits is allowed to be smaller than PRIbits.
Thankfully, nobody seem to have taken this path so far...

The fix is to use ICH_VTR_EL2.PREbits instead.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index bce6037cf01d..32c3295929b0 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -22,7 +22,7 @@
 #include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)		((v) & 0xf)
-#define vtr_to_nr_pri_bits(v)		(((u32)(v) >> 29) + 1)
+#define vtr_to_nr_pre_bits(v)		(((u32)(v) >> 26) + 1)
 
 static u64 __hyp_text __gic_v3_get_lr(unsigned int lr)
 {
@@ -135,13 +135,13 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
 	if (used_lrs) {
 		int i;
-		u32 nr_pri_bits;
+		u32 nr_pre_bits;
 
 		cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2);
 
 		write_gicreg(0, ICH_HCR_EL2);
 		val = read_gicreg(ICH_VTR_EL2);
-		nr_pri_bits = vtr_to_nr_pri_bits(val);
+		nr_pre_bits = vtr_to_nr_pre_bits(val);
 
 		for (i = 0; i < used_lrs; i++) {
 			if (cpu_if->vgic_elrsr & (1 << i))
@@ -152,7 +152,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			__gic_v3_set_lr(0, i);
 		}
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
 			cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
@@ -162,7 +162,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
 		}
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
 			cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
@@ -198,7 +198,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 	u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
 	u64 val;
-	u32 nr_pri_bits;
+	u32 nr_pre_bits;
 	int i;
 
 	/*
@@ -217,12 +217,12 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	}
 
 	val = read_gicreg(ICH_VTR_EL2);
-	nr_pri_bits = vtr_to_nr_pri_bits(val);
+	nr_pre_bits = vtr_to_nr_pre_bits(val);
 
 	if (used_lrs) {
 		write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
 			write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
@@ -232,7 +232,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 			write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
 		}
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
 			write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
-- 
2.11.0

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

* [PATCH 06/31] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

The GICv3 documentation is extremely confusing, as it talks about
the number of priorities represented by the ICH_APxRn_EL2 registers,
while it should really talk about the number of preemption levels.

This leads to a bug where we may access undefined ICH_APxRn_EL2
registers, since PREbits is allowed to be smaller than PRIbits.
Thankfully, nobody seem to have taken this path so far...

The fix is to use ICH_VTR_EL2.PREbits instead.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index bce6037cf01d..32c3295929b0 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -22,7 +22,7 @@
 #include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)		((v) & 0xf)
-#define vtr_to_nr_pri_bits(v)		(((u32)(v) >> 29) + 1)
+#define vtr_to_nr_pre_bits(v)		(((u32)(v) >> 26) + 1)
 
 static u64 __hyp_text __gic_v3_get_lr(unsigned int lr)
 {
@@ -135,13 +135,13 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
 	if (used_lrs) {
 		int i;
-		u32 nr_pri_bits;
+		u32 nr_pre_bits;
 
 		cpu_if->vgic_elrsr = read_gicreg(ICH_ELSR_EL2);
 
 		write_gicreg(0, ICH_HCR_EL2);
 		val = read_gicreg(ICH_VTR_EL2);
-		nr_pri_bits = vtr_to_nr_pri_bits(val);
+		nr_pre_bits = vtr_to_nr_pre_bits(val);
 
 		for (i = 0; i < used_lrs; i++) {
 			if (cpu_if->vgic_elrsr & (1 << i))
@@ -152,7 +152,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			__gic_v3_set_lr(0, i);
 		}
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
 			cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
@@ -162,7 +162,7 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 			cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
 		}
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
 			cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
@@ -198,7 +198,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
 	u64 used_lrs = vcpu->arch.vgic_cpu.used_lrs;
 	u64 val;
-	u32 nr_pri_bits;
+	u32 nr_pre_bits;
 	int i;
 
 	/*
@@ -217,12 +217,12 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 	}
 
 	val = read_gicreg(ICH_VTR_EL2);
-	nr_pri_bits = vtr_to_nr_pri_bits(val);
+	nr_pre_bits = vtr_to_nr_pre_bits(val);
 
 	if (used_lrs) {
 		write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
 			write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
@@ -232,7 +232,7 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 			write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
 		}
 
-		switch (nr_pri_bits) {
+		switch (nr_pre_bits) {
 		case 7:
 			write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
 			write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
-- 
2.11.0

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

As we're about to access the Active Priority registers a lot more,
let's define accessors that take the register number as a parameter.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 100 insertions(+), 16 deletions(-)

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 32c3295929b0..990d9d1e85d0 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
 	}
 }
 
+static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
+{
+	switch (n) {
+	case 0:
+		write_gicreg(val, ICH_AP0R0_EL2);
+		break;
+	case 1:
+		write_gicreg(val, ICH_AP0R1_EL2);
+		break;
+	case 2:
+		write_gicreg(val, ICH_AP0R2_EL2);
+		break;
+	case 3:
+		write_gicreg(val, ICH_AP0R3_EL2);
+		break;
+	}
+}
+
+static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
+{
+	switch (n) {
+	case 0:
+		write_gicreg(val, ICH_AP1R0_EL2);
+		break;
+	case 1:
+		write_gicreg(val, ICH_AP1R1_EL2);
+		break;
+	case 2:
+		write_gicreg(val, ICH_AP1R2_EL2);
+		break;
+	case 3:
+		write_gicreg(val, ICH_AP1R3_EL2);
+		break;
+	}
+}
+
+static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
+{
+	u32 val;
+
+	switch (n) {
+	case 0:
+		val = read_gicreg(ICH_AP0R0_EL2);
+		break;
+	case 1:
+		val = read_gicreg(ICH_AP0R1_EL2);
+		break;
+	case 2:
+		val = read_gicreg(ICH_AP0R2_EL2);
+		break;
+	case 3:
+		val = read_gicreg(ICH_AP0R3_EL2);
+		break;
+	default:
+		unreachable();
+	}
+
+	return val;
+}
+
+static u32 __hyp_text __vgic_v3_read_ap1rn(int n)
+{
+	u32 val;
+
+	switch (n) {
+	case 0:
+		val = read_gicreg(ICH_AP1R0_EL2);
+		break;
+	case 1:
+		val = read_gicreg(ICH_AP1R1_EL2);
+		break;
+	case 2:
+		val = read_gicreg(ICH_AP1R2_EL2);
+		break;
+	case 3:
+		val = read_gicreg(ICH_AP1R3_EL2);
+		break;
+	default:
+		unreachable();
+	}
+
+	return val;
+}
+
 void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 {
 	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -154,22 +238,22 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
 		switch (nr_pre_bits) {
 		case 7:
-			cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
-			cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
+			cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
+			cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
 		case 6:
-			cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2);
+			cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
 		default:
-			cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
+			cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
 		}
 
 		switch (nr_pre_bits) {
 		case 7:
-			cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
-			cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
+			cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
+			cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
 		case 6:
-			cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2);
+			cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
 		default:
-			cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2);
+			cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
 		}
 	} else {
 		cpu_if->vgic_elrsr = 0xffff;
@@ -224,22 +308,22 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 
 		switch (nr_pre_bits) {
 		case 7:
-			write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
-			write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
 		case 6:
-			write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
 		default:
-			write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
 		}
 
 		switch (nr_pre_bits) {
 		case 7:
-			write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
-			write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
 		case 6:
-			write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
 		default:
-			write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
 		}
 
 		for (i = 0; i < used_lrs; i++)
-- 
2.11.0

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

As we're about to access the Active Priority registers a lot more,
let's define accessors that take the register number as a parameter.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 100 insertions(+), 16 deletions(-)

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 32c3295929b0..990d9d1e85d0 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
 	}
 }
 
+static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
+{
+	switch (n) {
+	case 0:
+		write_gicreg(val, ICH_AP0R0_EL2);
+		break;
+	case 1:
+		write_gicreg(val, ICH_AP0R1_EL2);
+		break;
+	case 2:
+		write_gicreg(val, ICH_AP0R2_EL2);
+		break;
+	case 3:
+		write_gicreg(val, ICH_AP0R3_EL2);
+		break;
+	}
+}
+
+static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
+{
+	switch (n) {
+	case 0:
+		write_gicreg(val, ICH_AP1R0_EL2);
+		break;
+	case 1:
+		write_gicreg(val, ICH_AP1R1_EL2);
+		break;
+	case 2:
+		write_gicreg(val, ICH_AP1R2_EL2);
+		break;
+	case 3:
+		write_gicreg(val, ICH_AP1R3_EL2);
+		break;
+	}
+}
+
+static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
+{
+	u32 val;
+
+	switch (n) {
+	case 0:
+		val = read_gicreg(ICH_AP0R0_EL2);
+		break;
+	case 1:
+		val = read_gicreg(ICH_AP0R1_EL2);
+		break;
+	case 2:
+		val = read_gicreg(ICH_AP0R2_EL2);
+		break;
+	case 3:
+		val = read_gicreg(ICH_AP0R3_EL2);
+		break;
+	default:
+		unreachable();
+	}
+
+	return val;
+}
+
+static u32 __hyp_text __vgic_v3_read_ap1rn(int n)
+{
+	u32 val;
+
+	switch (n) {
+	case 0:
+		val = read_gicreg(ICH_AP1R0_EL2);
+		break;
+	case 1:
+		val = read_gicreg(ICH_AP1R1_EL2);
+		break;
+	case 2:
+		val = read_gicreg(ICH_AP1R2_EL2);
+		break;
+	case 3:
+		val = read_gicreg(ICH_AP1R3_EL2);
+		break;
+	default:
+		unreachable();
+	}
+
+	return val;
+}
+
 void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 {
 	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -154,22 +238,22 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
 
 		switch (nr_pre_bits) {
 		case 7:
-			cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
-			cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
+			cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
+			cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
 		case 6:
-			cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2);
+			cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
 		default:
-			cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
+			cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
 		}
 
 		switch (nr_pre_bits) {
 		case 7:
-			cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
-			cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
+			cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
+			cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
 		case 6:
-			cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2);
+			cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
 		default:
-			cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2);
+			cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
 		}
 	} else {
 		cpu_if->vgic_elrsr = 0xffff;
@@ -224,22 +308,22 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 
 		switch (nr_pre_bits) {
 		case 7:
-			write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
-			write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
 		case 6:
-			write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
 		default:
-			write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
+			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
 		}
 
 		switch (nr_pre_bits) {
 		case 7:
-			write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
-			write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
 		case 6:
-			write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
 		default:
-			write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
+			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
 		}
 
 		for (i = 0; i < used_lrs; i++)
-- 
2.11.0

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

* [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

It is often useful to compare an ESR syndrome reporting the trapping
of a system register with a value matching that system register.

Since encoding both the sysreg and the ESR version seem to be a bit
overkill, let's add a set of macros that convert an ESR value into
the corresponding sysreg encoding.

We handle both AArch32 and AArch64, taking advantage of identical
encodings between system registers and CP15 accessors.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index ad42e79a5d4d..db8f13137443 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -19,6 +19,7 @@
 #define __ASM_ESR_H
 
 #include <asm/memory.h>
+#include <asm/sysreg.h>
 
 #define ESR_ELx_EC_UNKNOWN	(0x00)
 #define ESR_ELx_EC_WFx		(0x01)
@@ -177,6 +178,30 @@
 
 #define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
 					 ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define esr_sys64_to_sysreg(e)					\
+	sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP0_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
+
+#define esr_cp15_to_sysreg(e)					\
+	sys_reg(3,						\
+		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
+
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 
-- 
2.11.0

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

* [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

It is often useful to compare an ESR syndrome reporting the trapping
of a system register with a value matching that system register.

Since encoding both the sysreg and the ESR version seem to be a bit
overkill, let's add a set of macros that convert an ESR value into
the corresponding sysreg encoding.

We handle both AArch32 and AArch64, taking advantage of identical
encodings between system registers and CP15 accessors.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
index ad42e79a5d4d..db8f13137443 100644
--- a/arch/arm64/include/asm/esr.h
+++ b/arch/arm64/include/asm/esr.h
@@ -19,6 +19,7 @@
 #define __ASM_ESR_H
 
 #include <asm/memory.h>
+#include <asm/sysreg.h>
 
 #define ESR_ELx_EC_UNKNOWN	(0x00)
 #define ESR_ELx_EC_WFx		(0x01)
@@ -177,6 +178,30 @@
 
 #define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
 					 ESR_ELx_SYS64_ISS_DIR_READ)
+
+#define esr_sys64_to_sysreg(e)					\
+	sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP0_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
+
+#define esr_cp15_to_sysreg(e)					\
+	sys_reg(3,						\
+		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
+		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
+		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
+
 #ifndef __ASSEMBLY__
 #include <asm/types.h>
 
-- 
2.11.0

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

* [PATCH 09/31] KVM: arm64: Make kvm_condition_valid32() accessible from EL2
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

As we're about to trap CP15 accesses and handle them at EL2, we
need to evaluate whether or not the condition flags are valid,
as an implementation is allowed to trap despite the condition
not being met.

Tagging the function as __hyp_text allows this.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/aarch32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/virt/kvm/arm/aarch32.c b/virt/kvm/arm/aarch32.c
index 528af4b2d09e..79c7c357804b 100644
--- a/virt/kvm/arm/aarch32.c
+++ b/virt/kvm/arm/aarch32.c
@@ -60,7 +60,7 @@ static const unsigned short cc_map[16] = {
 /*
  * Check if a trapped instruction should have been executed or not.
  */
-bool kvm_condition_valid32(const struct kvm_vcpu *vcpu)
+bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu)
 {
 	unsigned long cpsr;
 	u32 cpsr_cond;
-- 
2.11.0

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

* [PATCH 09/31] KVM: arm64: Make kvm_condition_valid32() accessible from EL2
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

As we're about to trap CP15 accesses and handle them at EL2, we
need to evaluate whether or not the condition flags are valid,
as an implementation is allowed to trap despite the condition
not being met.

Tagging the function as __hyp_text allows this.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/aarch32.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/virt/kvm/arm/aarch32.c b/virt/kvm/arm/aarch32.c
index 528af4b2d09e..79c7c357804b 100644
--- a/virt/kvm/arm/aarch32.c
+++ b/virt/kvm/arm/aarch32.c
@@ -60,7 +60,7 @@ static const unsigned short cc_map[16] = {
 /*
  * Check if a trapped instruction should have been executed or not.
  */
-bool kvm_condition_valid32(const struct kvm_vcpu *vcpu)
+bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu)
 {
 	unsigned long cpsr;
 	u32 cpsr_cond;
-- 
2.11.0

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

* [PATCH 10/31] KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at EL2
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: David Daney, Catalin Marinas, Mark Rutland, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

In order to start handling guest access to GICv3 system registers,
let's add a hook that will get called when we trap a system register
access. This is gated by a new static key (vgic_v3_cpuif_trap).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_hyp.h |  1 +
 arch/arm64/kvm/hyp/switch.c      | 14 ++++++++++++++
 include/kvm/arm_vgic.h           |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c    | 27 +++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c      |  2 ++
 5 files changed, 45 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index b18e852d27e8..4572a9b560fa 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -127,6 +127,7 @@ int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
 void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
+int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __timer_save_state(struct kvm_vcpu *vcpu);
 void __timer_restore_state(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index aede1658aeda..dfd8ca16601b 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -350,6 +350,20 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 		}
 	}
 
+	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
+	    exit_code == ARM_EXCEPTION_TRAP &&
+	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
+	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
+		int ret = __vgic_v3_perform_cpuif_access(vcpu);
+
+		if (ret == 1) {
+			__skip_instr(vcpu);
+			goto again;
+		}
+
+		/* 0 falls through to be handled out of EL2 */
+	}
+
 	fp_enabled = __fpsimd_enabled();
 
 	__sysreg_save_guest_state(guest_ctxt);
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 581a59ea7e34..ddfa11b713bf 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -280,6 +280,7 @@ struct vgic_cpu {
 };
 
 extern struct static_key_false vgic_v2_cpuif_trap;
+extern struct static_key_false vgic_v3_cpuif_trap;
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 void kvm_vgic_early_init(struct kvm *kvm);
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 990d9d1e85d0..435787a93c6c 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -19,6 +19,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm_host.h>
 
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)		((v) & 0xf)
@@ -371,3 +372,29 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
 {
 	write_gicreg(vmcr, ICH_VMCR_EL2);
 }
+
+#ifdef CONFIG_ARM64
+
+int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	u32 sysreg;
+
+	if (vcpu_mode_is_32bit(vcpu)) {
+		if (!kvm_condition_valid(vcpu))
+			return 1;
+
+		sysreg = esr_cp15_to_sysreg(esr);
+	} else {
+		sysreg = esr_sys64_to_sysreg(esr);
+	}
+
+	switch (sysreg) {
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+#endif
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 393779ebe87c..063526443781 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -318,6 +318,8 @@ int vgic_v3_map_resources(struct kvm *kvm)
 	return ret;
 }
 
+DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
-- 
2.11.0

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

* [PATCH 10/31] KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at EL2
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

In order to start handling guest access to GICv3 system registers,
let's add a hook that will get called when we trap a system register
access. This is gated by a new static key (vgic_v3_cpuif_trap).

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/kvm_hyp.h |  1 +
 arch/arm64/kvm/hyp/switch.c      | 14 ++++++++++++++
 include/kvm/arm_vgic.h           |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c    | 27 +++++++++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c      |  2 ++
 5 files changed, 45 insertions(+)

diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
index b18e852d27e8..4572a9b560fa 100644
--- a/arch/arm64/include/asm/kvm_hyp.h
+++ b/arch/arm64/include/asm/kvm_hyp.h
@@ -127,6 +127,7 @@ int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
 void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
+int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
 
 void __timer_save_state(struct kvm_vcpu *vcpu);
 void __timer_restore_state(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index aede1658aeda..dfd8ca16601b 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -350,6 +350,20 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
 		}
 	}
 
+	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
+	    exit_code == ARM_EXCEPTION_TRAP &&
+	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
+	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
+		int ret = __vgic_v3_perform_cpuif_access(vcpu);
+
+		if (ret == 1) {
+			__skip_instr(vcpu);
+			goto again;
+		}
+
+		/* 0 falls through to be handled out of EL2 */
+	}
+
 	fp_enabled = __fpsimd_enabled();
 
 	__sysreg_save_guest_state(guest_ctxt);
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 581a59ea7e34..ddfa11b713bf 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -280,6 +280,7 @@ struct vgic_cpu {
 };
 
 extern struct static_key_false vgic_v2_cpuif_trap;
+extern struct static_key_false vgic_v3_cpuif_trap;
 
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 void kvm_vgic_early_init(struct kvm *kvm);
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 990d9d1e85d0..435787a93c6c 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -19,6 +19,7 @@
 #include <linux/irqchip/arm-gic-v3.h>
 #include <linux/kvm_host.h>
 
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
 
 #define vtr_to_max_lr_idx(v)		((v) & 0xf)
@@ -371,3 +372,29 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
 {
 	write_gicreg(vmcr, ICH_VMCR_EL2);
 }
+
+#ifdef CONFIG_ARM64
+
+int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	u32 sysreg;
+
+	if (vcpu_mode_is_32bit(vcpu)) {
+		if (!kvm_condition_valid(vcpu))
+			return 1;
+
+		sysreg = esr_cp15_to_sysreg(esr);
+	} else {
+		sysreg = esr_sys64_to_sysreg(esr);
+	}
+
+	switch (sysreg) {
+	default:
+		return 0;
+	}
+
+	return 1;
+}
+
+#endif
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 393779ebe87c..063526443781 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -318,6 +318,8 @@ int vgic_v3_map_resources(struct kvm *kvm)
 	return ret;
 }
 
+DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
-- 
2.11.0

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

* [PATCH 11/31] KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_BPR1_EL1
register, which is located in the ICH_VMCR_EL2.BPR1 field.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/hyp/vgic-v3-sr.c | 61 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 435787a93c6c..f0f038c490a5 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -375,9 +375,57 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
 
 #ifdef CONFIG_ARM64
 
+static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
+{
+	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+}
+
+static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
+{
+	unsigned int bpr;
+
+	if (vmcr & ICH_VMCR_CBPR_MASK) {
+		bpr = __vgic_v3_get_bpr0(vmcr);
+		if (bpr < 7)
+			bpr++;
+	} else {
+		bpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	}
+
+	return bpr;
+}
+
+static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
+}
+
+static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+	u8 bpr_min = 8 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+
+	if (vmcr & ICH_VMCR_CBPR_MASK)
+		return;
+
+	/* Enforce BPR limiting */
+	if (val < bpr_min)
+		val = bpr_min;
+
+	val <<= ICH_VMCR_BPR1_SHIFT;
+	val &= ICH_VMCR_BPR1_MASK;
+	vmcr &= ~ICH_VMCR_BPR1_MASK;
+	vmcr |= val;
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
-	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	int rt = kvm_vcpu_sys_get_rt(vcpu);
+	u32 vmcr, esr = kvm_vcpu_get_hsr(vcpu);
+	void (*fn)(struct kvm_vcpu *, u32, int);
+	bool is_read;
 	u32 sysreg;
 
 	if (vcpu_mode_is_32bit(vcpu)) {
@@ -389,11 +437,22 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		sysreg = esr_sys64_to_sysreg(esr);
 	}
 
+	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
+
 	switch (sysreg) {
+	case SYS_ICC_BPR1_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_bpr1;
+		else
+			fn = __vgic_v3_write_bpr1;
+		break;
 	default:
 		return 0;
 	}
 
+	vmcr = __vgic_v3_read_vmcr();
+	fn(vcpu, vmcr, rt);
+
 	return 1;
 }
 
-- 
2.11.0

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

* [PATCH 11/31] KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_BPR1_EL1
register, which is located in the ICH_VMCR_EL2.BPR1 field.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 virt/kvm/arm/hyp/vgic-v3-sr.c | 61 ++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 60 insertions(+), 1 deletion(-)

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 435787a93c6c..f0f038c490a5 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -375,9 +375,57 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
 
 #ifdef CONFIG_ARM64
 
+static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
+{
+	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
+}
+
+static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
+{
+	unsigned int bpr;
+
+	if (vmcr & ICH_VMCR_CBPR_MASK) {
+		bpr = __vgic_v3_get_bpr0(vmcr);
+		if (bpr < 7)
+			bpr++;
+	} else {
+		bpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
+	}
+
+	return bpr;
+}
+
+static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
+}
+
+static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+	u8 bpr_min = 8 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+
+	if (vmcr & ICH_VMCR_CBPR_MASK)
+		return;
+
+	/* Enforce BPR limiting */
+	if (val < bpr_min)
+		val = bpr_min;
+
+	val <<= ICH_VMCR_BPR1_SHIFT;
+	val &= ICH_VMCR_BPR1_MASK;
+	vmcr &= ~ICH_VMCR_BPR1_MASK;
+	vmcr |= val;
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
-	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	int rt = kvm_vcpu_sys_get_rt(vcpu);
+	u32 vmcr, esr = kvm_vcpu_get_hsr(vcpu);
+	void (*fn)(struct kvm_vcpu *, u32, int);
+	bool is_read;
 	u32 sysreg;
 
 	if (vcpu_mode_is_32bit(vcpu)) {
@@ -389,11 +437,22 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		sysreg = esr_sys64_to_sysreg(esr);
 	}
 
+	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
+
 	switch (sysreg) {
+	case SYS_ICC_BPR1_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_bpr1;
+		else
+			fn = __vgic_v3_write_bpr1;
+		break;
 	default:
 		return 0;
 	}
 
+	vmcr = __vgic_v3_read_vmcr();
+	fn(vcpu, vmcr, rt);
+
 	return 1;
 }
 
-- 
2.11.0

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

* [PATCH 12/31] KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_IGRPEN1_EL1
register, which is located in the ICH_VMCR_EL2.VENG1 field.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index f0f038c490a5..473ef22508e6 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -395,6 +395,23 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
 	return bpr;
 }
 
+static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
+}
+
+static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+
+	if (val & 1)
+		vmcr |= ICH_VMCR_ENG1_MASK;
+	else
+		vmcr &= ~ICH_VMCR_ENG1_MASK;
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
@@ -440,6 +457,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
 
 	switch (sysreg) {
+	case SYS_ICC_GRPEN1_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_igrpen1;
+		else
+			fn = __vgic_v3_write_igrpen1;
+		break;
 	case SYS_ICC_BPR1_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_bpr1;
-- 
2.11.0

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

* [PATCH 12/31] KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_IGRPEN1_EL1
register, which is located in the ICH_VMCR_EL2.VENG1 field.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index f0f038c490a5..473ef22508e6 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -395,6 +395,23 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
 	return bpr;
 }
 
+static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
+}
+
+static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+
+	if (val & 1)
+		vmcr |= ICH_VMCR_ENG1_MASK;
+	else
+		vmcr &= ~ICH_VMCR_ENG1_MASK;
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
@@ -440,6 +457,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
 
 	switch (sysreg) {
+	case SYS_ICC_GRPEN1_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_igrpen1;
+		else
+			fn = __vgic_v3_write_igrpen1;
+		break;
 	case SYS_ICC_BPR1_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_bpr1;
-- 
2.11.0

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

* [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading the guest's view of the ICC_IAR1_EL1
register. This involves finding the highest priority Group-1
interrupt, checking against both PMR and the active group
priority, activating the interrupt and setting the group
priority as active.

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 97cbca19430d..7610ea4e8337 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -391,6 +391,7 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 #define ICH_LR_PRIORITY_SHIFT		48
+#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 473ef22508e6..49aad1de3ac8 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
 
 #ifdef CONFIG_ARM64
 
+static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
+
+	return crm != 8;
+}
+
+#define GICv3_IDLE_PRIORITY	0xff
+
+static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
+						    u32 vmcr,
+						    u64 *lr_val)
+{
+	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
+	u8 priority = GICv3_IDLE_PRIORITY;
+	int i, lr = -1;
+
+	for (i = 0; i < used_lrs; i++) {
+		u64 val = __gic_v3_get_lr(i);
+		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+
+		/* Not pending in the state? */
+		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
+			continue;
+
+		/* Group-0 interrupt, but Group-0 disabled? */
+		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
+			continue;
+
+		/* Group-1 interrupt, but Group-1 disabled? */
+		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
+			continue;
+
+		/* Not the highest priority? */
+		if (lr_prio >= priority)
+			continue;
+
+		/* This is a candidate */
+		priority = lr_prio;
+		*lr_val = val;
+		lr = i;
+	}
+
+	if (lr == -1)
+		*lr_val = ICC_IAR1_EL1_SPURIOUS;
+
+	return lr;
+}
+
+static int __hyp_text __vgic_v3_get_highest_active_priority(void)
+{
+	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+	u8 nr_aprs = 1 << (nr_pre_bits - 5);
+	u32 hap = 0;
+	int i;
+
+	for (i = 0; i < nr_aprs; i++) {
+		u32 val;
+
+		val  = __vgic_v3_read_ap0rn(i);
+		val |= __vgic_v3_read_ap1rn(i);
+		if (val)
+			return (hap + __ffs(val)) << (8 - nr_pre_bits);
+
+		hap += 32;
+	}
+
+	return GICv3_IDLE_PRIORITY;
+}
+
 static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
 {
 	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
@@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
 	return bpr;
 }
 
+static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
+{
+	unsigned int bpr;
+
+	if (!grp)
+		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
+	else
+		bpr = __vgic_v3_get_bpr1(vmcr);
+
+	return pri & (GENMASK(7, 0) << bpr);
+}
+
+static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
+{
+	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+	u8 hap = pre >> (8 - nr_pre_bits);
+	int apr = hap / 32;
+	u32 bit = BIT(hap % 32);
+	u32 val;
+
+	val = __vgic_v3_read_ap1rn(apr);
+	__vgic_v3_write_ap1rn(val | bit, apr);
+}
+
+static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 lr_val;
+	u8 lr_prio, pmr;
+	int lr, grp;
+
+	grp = __vgic_v3_get_group(vcpu);
+
+	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
+	if (lr < 0)
+		goto spurious;
+
+	if (grp != !!(lr_val & ICH_LR_GROUP))
+		goto spurious;
+
+	pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+	if (pmr <= lr_prio)
+		goto spurious;
+
+	if (__vgic_v3_get_highest_active_priority() <= lr_prio)
+		goto spurious;
+
+	lr_val &= ~ICH_LR_STATE;
+	/* No active state for LPIs */
+	if ((lr_val & ICH_LR_VIRTUAL_ID_MASK) <= VGIC_MAX_SPI)
+		lr_val |= ICH_LR_ACTIVE_BIT;
+	__gic_v3_set_lr(lr_val, lr);
+	__vgic_v3_set_active_priority(__vgic_v3_pri_to_pre(lr_prio, vmcr, grp));
+	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
+	return;
+
+spurious:
+	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
+}
+
 static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
@@ -457,6 +588,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
 
 	switch (sysreg) {
+	case SYS_ICC_IAR1_EL1:
+		fn = __vgic_v3_read_iar;
+		break;
 	case SYS_ICC_GRPEN1_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_igrpen1;
-- 
2.11.0

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

* [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading the guest's view of the ICC_IAR1_EL1
register. This involves finding the highest priority Group-1
interrupt, checking against both PMR and the active group
priority, activating the interrupt and setting the group
priority as active.

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 97cbca19430d..7610ea4e8337 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -391,6 +391,7 @@
 #define ICH_LR_PHYS_ID_SHIFT		32
 #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
 #define ICH_LR_PRIORITY_SHIFT		48
+#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
 
 /* These are for GICv2 emulation only */
 #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 473ef22508e6..49aad1de3ac8 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
 
 #ifdef CONFIG_ARM64
 
+static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
+{
+	u32 esr = kvm_vcpu_get_hsr(vcpu);
+	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
+
+	return crm != 8;
+}
+
+#define GICv3_IDLE_PRIORITY	0xff
+
+static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
+						    u32 vmcr,
+						    u64 *lr_val)
+{
+	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
+	u8 priority = GICv3_IDLE_PRIORITY;
+	int i, lr = -1;
+
+	for (i = 0; i < used_lrs; i++) {
+		u64 val = __gic_v3_get_lr(i);
+		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+
+		/* Not pending in the state? */
+		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
+			continue;
+
+		/* Group-0 interrupt, but Group-0 disabled? */
+		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
+			continue;
+
+		/* Group-1 interrupt, but Group-1 disabled? */
+		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
+			continue;
+
+		/* Not the highest priority? */
+		if (lr_prio >= priority)
+			continue;
+
+		/* This is a candidate */
+		priority = lr_prio;
+		*lr_val = val;
+		lr = i;
+	}
+
+	if (lr == -1)
+		*lr_val = ICC_IAR1_EL1_SPURIOUS;
+
+	return lr;
+}
+
+static int __hyp_text __vgic_v3_get_highest_active_priority(void)
+{
+	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+	u8 nr_aprs = 1 << (nr_pre_bits - 5);
+	u32 hap = 0;
+	int i;
+
+	for (i = 0; i < nr_aprs; i++) {
+		u32 val;
+
+		val  = __vgic_v3_read_ap0rn(i);
+		val |= __vgic_v3_read_ap1rn(i);
+		if (val)
+			return (hap + __ffs(val)) << (8 - nr_pre_bits);
+
+		hap += 32;
+	}
+
+	return GICv3_IDLE_PRIORITY;
+}
+
 static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
 {
 	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
@@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
 	return bpr;
 }
 
+static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
+{
+	unsigned int bpr;
+
+	if (!grp)
+		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
+	else
+		bpr = __vgic_v3_get_bpr1(vmcr);
+
+	return pri & (GENMASK(7, 0) << bpr);
+}
+
+static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
+{
+	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+	u8 hap = pre >> (8 - nr_pre_bits);
+	int apr = hap / 32;
+	u32 bit = BIT(hap % 32);
+	u32 val;
+
+	val = __vgic_v3_read_ap1rn(apr);
+	__vgic_v3_write_ap1rn(val | bit, apr);
+}
+
+static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 lr_val;
+	u8 lr_prio, pmr;
+	int lr, grp;
+
+	grp = __vgic_v3_get_group(vcpu);
+
+	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
+	if (lr < 0)
+		goto spurious;
+
+	if (grp != !!(lr_val & ICH_LR_GROUP))
+		goto spurious;
+
+	pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
+	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+	if (pmr <= lr_prio)
+		goto spurious;
+
+	if (__vgic_v3_get_highest_active_priority() <= lr_prio)
+		goto spurious;
+
+	lr_val &= ~ICH_LR_STATE;
+	/* No active state for LPIs */
+	if ((lr_val & ICH_LR_VIRTUAL_ID_MASK) <= VGIC_MAX_SPI)
+		lr_val |= ICH_LR_ACTIVE_BIT;
+	__gic_v3_set_lr(lr_val, lr);
+	__vgic_v3_set_active_priority(__vgic_v3_pri_to_pre(lr_prio, vmcr, grp));
+	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
+	return;
+
+spurious:
+	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
+}
+
 static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
@@ -457,6 +588,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
 
 	switch (sysreg) {
+	case SYS_ICC_IAR1_EL1:
+		fn = __vgic_v3_read_iar;
+		break;
 	case SYS_ICC_GRPEN1_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_igrpen1;
-- 
2.11.0

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for writing the guest's view of the ICC_EOIR1_EL1
register. This involves dropping the priority of the interrupt,
and deactivating it if required (EOImode == 0).

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 7610ea4e8337..c56d9bc2c904 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,8 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_EOIcount_SHIFT		27
+#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
 
 #define ICH_VMCR_CBPR_SHIFT		4
 #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 49aad1de3ac8..a76351b3ad66 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
 	return lr;
 }
 
+static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
+					       int intid, u64 *lr_val)
+{
+	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
+	int i;
+
+	for (i = 0; i < used_lrs; i++) {
+		u64 val = __gic_v3_get_lr(i);
+
+		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
+		    (val & ICH_LR_ACTIVE_BIT)) {
+			*lr_val = val;
+			return i;
+		}
+	}
+
+	*lr_val = ICC_IAR1_EL1_SPURIOUS;
+	return -1;
+}
+
 static int __hyp_text __vgic_v3_get_highest_active_priority(void)
 {
 	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
@@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
 	__vgic_v3_write_ap1rn(val | bit, apr);
 }
 
+static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
+{
+	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+	u8 nr_aprs = 1 << (nr_pre_bits - 5);
+	u32 hap = 0;
+	int i;
+
+	for (i = 0; i < nr_aprs; i++) {
+		u32 ap0, ap1;
+		int c0, c1;
+
+		ap0 = __vgic_v3_read_ap0rn(i);
+		ap1 = __vgic_v3_read_ap1rn(i);
+		if (!ap0 && !ap1) {
+			hap += 32;
+			continue;
+		}
+
+		c0 = ap0 ? __ffs(ap0) : 32;
+		c1 = ap1 ? __ffs(ap1) : 32;
+
+		/* Always clear the LSB, which is the highest priority */
+		if (c0 < c1) {
+			ap0 &= ap0 - 1;
+			__vgic_v3_write_ap0rn(ap0, i);
+			hap += c0;
+		} else {
+			ap1 &= ap1 - 1;
+			__vgic_v3_write_ap1rn(ap1, i);
+			hap += c1;
+		}
+
+		return hap << (8 - nr_pre_bits);
+	}
+
+	return GICv3_IDLE_PRIORITY;
+}
+
 static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u64 lr_val;
@@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
 	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
 }
 
+static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
+{
+	lr_val &= ~ICH_LR_ACTIVE_BIT;
+	if (lr_val & ICH_LR_HW) {
+		u32 pid;
+		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
+		gic_write_dir(pid);
+	}
+
+	__gic_v3_set_lr(lr_val, lr);
+}
+
+static void __hyp_text __vgic_v3_bump_eoicount(void)
+{
+	u32 hcr;
+
+	hcr = read_gicreg(ICH_HCR_EL2);
+	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
+	write_gicreg(hcr, ICH_HCR_EL2);
+}
+
+static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u32 vid = vcpu_get_reg(vcpu, rt);
+	u64 lr_val;
+	u8 lr_prio, act_prio;
+	int lr, grp;
+
+	grp = __vgic_v3_get_group(vcpu);
+
+	/* Drop priority in any case */
+	act_prio = __vgic_v3_clear_highest_active_priority();
+
+	/* If EOIing an LPI, no deactivate to be performed */
+	if (vid >= VGIC_MIN_LPI)
+		return;
+
+	/* EOImode == 1, nothing to be done here */
+	if (vmcr & ICH_VMCR_EOIM_MASK)
+		return;
+
+	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
+	if (lr == -1) {
+		__vgic_v3_bump_eoicount();
+		return;
+	}
+
+	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+
+	/* If priorities or group do not match, the guest has fscked-up. */
+	if (grp != !!(lr_val & ICH_LR_GROUP) ||
+	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
+		return;
+
+	/* Let's now perform the deactivation */
+	__vgic_v3_clear_active_lr(lr, lr_val);
+}
+
 static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
@@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_IAR1_EL1:
 		fn = __vgic_v3_read_iar;
 		break;
+	case SYS_ICC_EOIR1_EL1:
+		fn = __vgic_v3_write_eoir;
+		break;
 	case SYS_ICC_GRPEN1_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_igrpen1;
-- 
2.11.0

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for writing the guest's view of the ICC_EOIR1_EL1
register. This involves dropping the priority of the interrupt,
and deactivating it if required (EOImode == 0).

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 7610ea4e8337..c56d9bc2c904 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,8 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_EOIcount_SHIFT		27
+#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
 
 #define ICH_VMCR_CBPR_SHIFT		4
 #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 49aad1de3ac8..a76351b3ad66 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
 	return lr;
 }
 
+static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
+					       int intid, u64 *lr_val)
+{
+	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
+	int i;
+
+	for (i = 0; i < used_lrs; i++) {
+		u64 val = __gic_v3_get_lr(i);
+
+		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
+		    (val & ICH_LR_ACTIVE_BIT)) {
+			*lr_val = val;
+			return i;
+		}
+	}
+
+	*lr_val = ICC_IAR1_EL1_SPURIOUS;
+	return -1;
+}
+
 static int __hyp_text __vgic_v3_get_highest_active_priority(void)
 {
 	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
@@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
 	__vgic_v3_write_ap1rn(val | bit, apr);
 }
 
+static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
+{
+	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+	u8 nr_aprs = 1 << (nr_pre_bits - 5);
+	u32 hap = 0;
+	int i;
+
+	for (i = 0; i < nr_aprs; i++) {
+		u32 ap0, ap1;
+		int c0, c1;
+
+		ap0 = __vgic_v3_read_ap0rn(i);
+		ap1 = __vgic_v3_read_ap1rn(i);
+		if (!ap0 && !ap1) {
+			hap += 32;
+			continue;
+		}
+
+		c0 = ap0 ? __ffs(ap0) : 32;
+		c1 = ap1 ? __ffs(ap1) : 32;
+
+		/* Always clear the LSB, which is the highest priority */
+		if (c0 < c1) {
+			ap0 &= ap0 - 1;
+			__vgic_v3_write_ap0rn(ap0, i);
+			hap += c0;
+		} else {
+			ap1 &= ap1 - 1;
+			__vgic_v3_write_ap1rn(ap1, i);
+			hap += c1;
+		}
+
+		return hap << (8 - nr_pre_bits);
+	}
+
+	return GICv3_IDLE_PRIORITY;
+}
+
 static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u64 lr_val;
@@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
 	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
 }
 
+static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
+{
+	lr_val &= ~ICH_LR_ACTIVE_BIT;
+	if (lr_val & ICH_LR_HW) {
+		u32 pid;
+		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
+		gic_write_dir(pid);
+	}
+
+	__gic_v3_set_lr(lr_val, lr);
+}
+
+static void __hyp_text __vgic_v3_bump_eoicount(void)
+{
+	u32 hcr;
+
+	hcr = read_gicreg(ICH_HCR_EL2);
+	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
+	write_gicreg(hcr, ICH_HCR_EL2);
+}
+
+static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u32 vid = vcpu_get_reg(vcpu, rt);
+	u64 lr_val;
+	u8 lr_prio, act_prio;
+	int lr, grp;
+
+	grp = __vgic_v3_get_group(vcpu);
+
+	/* Drop priority in any case */
+	act_prio = __vgic_v3_clear_highest_active_priority();
+
+	/* If EOIing an LPI, no deactivate to be performed */
+	if (vid >= VGIC_MIN_LPI)
+		return;
+
+	/* EOImode == 1, nothing to be done here */
+	if (vmcr & ICH_VMCR_EOIM_MASK)
+		return;
+
+	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
+	if (lr == -1) {
+		__vgic_v3_bump_eoicount();
+		return;
+	}
+
+	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
+
+	/* If priorities or group do not match, the guest has fscked-up. */
+	if (grp != !!(lr_val & ICH_LR_GROUP) ||
+	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
+		return;
+
+	/* Let's now perform the deactivation */
+	__vgic_v3_clear_active_lr(lr, lr_val);
+}
+
 static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
@@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_IAR1_EL1:
 		fn = __vgic_v3_read_iar;
 		break;
+	case SYS_ICC_EOIR1_EL1:
+		fn = __vgic_v3_write_eoir;
+		break;
 	case SYS_ICC_GRPEN1_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_igrpen1;
-- 
2.11.0

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

* [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 15c142ce991c..aad46b8eea5e 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,6 +180,7 @@
 
 #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
 
+#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
 #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a76351b3ad66..b6803989da1f 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
 	__vgic_v3_write_vmcr(vmcr);
 }
 
+static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
+{
+	u32 val;
+
+	if (!__vgic_v3_get_group(vcpu))
+		val = __vgic_v3_read_ap0rn(n);
+	else
+		val = __vgic_v3_read_ap1rn(n);
+
+	vcpu_set_reg(vcpu, rt, val);
+}
+
+static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
+{
+	u32 val = vcpu_get_reg(vcpu, rt);
+
+	if (!__vgic_v3_get_group(vcpu))
+		__vgic_v3_write_ap0rn(val, n);
+	else
+		__vgic_v3_write_ap1rn(val, n);
+}
+
+static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 0);
+}
+
+static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 1);
+}
+
+static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 2);
+}
+
+static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 3);
+}
+
+static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 0);
+}
+
+static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 1);
+}
+
+static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 2);
+}
+
+static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 3);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_bpr1;
 		break;
+	case SYS_ICC_AP1Rn_EL1(0):
+		if (is_read)
+			fn = __vgic_v3_read_apxr0;
+		else
+			fn = __vgic_v3_write_apxr0;
+		break;
+	case SYS_ICC_AP1Rn_EL1(1):
+		if (is_read)
+			fn = __vgic_v3_read_apxr1;
+		else
+			fn = __vgic_v3_write_apxr1;
+		break;
+	case SYS_ICC_AP1Rn_EL1(2):
+		if (is_read)
+			fn = __vgic_v3_read_apxr2;
+		else
+			fn = __vgic_v3_write_apxr2;
+		break;
+	case SYS_ICC_AP1Rn_EL1(3):
+		if (is_read)
+			fn = __vgic_v3_read_apxr3;
+		else
+			fn = __vgic_v3_write_apxr3;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 95 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 15c142ce991c..aad46b8eea5e 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,6 +180,7 @@
 
 #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
 
+#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
 #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a76351b3ad66..b6803989da1f 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
 	__vgic_v3_write_vmcr(vmcr);
 }
 
+static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
+{
+	u32 val;
+
+	if (!__vgic_v3_get_group(vcpu))
+		val = __vgic_v3_read_ap0rn(n);
+	else
+		val = __vgic_v3_read_ap1rn(n);
+
+	vcpu_set_reg(vcpu, rt, val);
+}
+
+static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
+{
+	u32 val = vcpu_get_reg(vcpu, rt);
+
+	if (!__vgic_v3_get_group(vcpu))
+		__vgic_v3_write_ap0rn(val, n);
+	else
+		__vgic_v3_write_ap1rn(val, n);
+}
+
+static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 0);
+}
+
+static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 1);
+}
+
+static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 2);
+}
+
+static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	__vgic_v3_read_apxrn(vcpu, rt, 3);
+}
+
+static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 0);
+}
+
+static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 1);
+}
+
+static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 2);
+}
+
+static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
+					     u32 vmcr, int rt)
+{
+	__vgic_v3_write_apxrn(vcpu, rt, 3);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_bpr1;
 		break;
+	case SYS_ICC_AP1Rn_EL1(0):
+		if (is_read)
+			fn = __vgic_v3_read_apxr0;
+		else
+			fn = __vgic_v3_write_apxr0;
+		break;
+	case SYS_ICC_AP1Rn_EL1(1):
+		if (is_read)
+			fn = __vgic_v3_read_apxr1;
+		else
+			fn = __vgic_v3_write_apxr1;
+		break;
+	case SYS_ICC_AP1Rn_EL1(2):
+		if (is_read)
+			fn = __vgic_v3_read_apxr2;
+		else
+			fn = __vgic_v3_write_apxr2;
+		break;
+	case SYS_ICC_AP1Rn_EL1(3):
+		if (is_read)
+			fn = __vgic_v3_read_apxr3;
+		else
+			fn = __vgic_v3_write_apxr3;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 16/31] KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading the guest's view of the ICV_HPPIR1_EL1
register. This is a simple parsing of the available LRs, extracting the
highest available interrupt.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index aad46b8eea5e..bd000686194a 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -185,6 +185,7 @@
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
 #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
 #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
+#define SYS_ICC_HPPIR1_EL1		sys_reg(3, 0, 12, 12, 2)
 #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
 #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
 #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index b6803989da1f..a521e105ade1 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -754,6 +754,26 @@ static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
 	__vgic_v3_write_apxrn(vcpu, rt, 3);
 }
 
+static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	u64 lr_val;
+	int lr, lr_grp, grp;
+
+	grp = __vgic_v3_get_group(vcpu);
+
+	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
+	if (lr == -1)
+		goto spurious;
+
+	lr_grp = !!(lr_val & ICH_LR_GROUP);
+	if (lr_grp != grp)
+		lr_val = ICC_IAR1_EL1_SPURIOUS;
+
+spurious:
+	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -816,6 +836,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_apxr3;
 		break;
+	case SYS_ICC_HPPIR1_EL1:
+		fn = __vgic_v3_read_hppir;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 16/31] KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading the guest's view of the ICV_HPPIR1_EL1
register. This is a simple parsing of the available LRs, extracting the
highest available interrupt.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index aad46b8eea5e..bd000686194a 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -185,6 +185,7 @@
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
 #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
 #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
+#define SYS_ICC_HPPIR1_EL1		sys_reg(3, 0, 12, 12, 2)
 #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
 #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
 #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index b6803989da1f..a521e105ade1 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -754,6 +754,26 @@ static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
 	__vgic_v3_write_apxrn(vcpu, rt, 3);
 }
 
+static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	u64 lr_val;
+	int lr, lr_grp, grp;
+
+	grp = __vgic_v3_get_group(vcpu);
+
+	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
+	if (lr == -1)
+		goto spurious;
+
+	lr_grp = !!(lr_val & ICH_LR_GROUP);
+	if (lr_grp != grp)
+		lr_val = ICC_IAR1_EL1_SPURIOUS;
+
+spurious:
+	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -816,6 +836,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_apxr3;
 		break;
+	case SYS_ICC_HPPIR1_EL1:
+		fn = __vgic_v3_read_hppir;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

In order to be able to trap Group-1 GICv3 system registers, we need to
set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
done after having restored the guest's state, and cleared on exit.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
 virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c56d9bc2c904..a1739843343e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_TALL1			(1 << 12)
 #define ICH_HCR_EOIcount_SHIFT		27
 #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
 
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a521e105ade1..a27671b1e9af 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -257,6 +257,9 @@ 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))
+			write_gicreg(0, ICH_HCR_EL2);
+
 		cpu_if->vgic_elrsr = 0xffff;
 		cpu_if->vgic_ap0r[0] = 0;
 		cpu_if->vgic_ap0r[1] = 0;
@@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 
 		for (i = 0; i < used_lrs; i++)
 			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
+	} else {
+		/* Always write ICH_HCR_EL2 to enable trapping */
+		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 	}
 
 	/*
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 063526443781..547b8374fb64 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -21,6 +21,8 @@
 
 #include "vgic.h"
 
+static bool group1_trap;
+
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 
 	/* Get the show on the road... */
 	vgic_v3->vgic_hcr = ICH_HCR_EN;
+	if (group1_trap)
+		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
-- 
2.11.0

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

* [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

In order to be able to trap Group-1 GICv3 system registers, we need to
set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
done after having restored the guest's state, and cleared on exit.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 include/linux/irqchip/arm-gic-v3.h | 1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
 virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
 3 files changed, 12 insertions(+)

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index c56d9bc2c904..a1739843343e 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_TALL1			(1 << 12)
 #define ICH_HCR_EOIcount_SHIFT		27
 #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
 
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a521e105ade1..a27671b1e9af 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -257,6 +257,9 @@ 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))
+			write_gicreg(0, ICH_HCR_EL2);
+
 		cpu_if->vgic_elrsr = 0xffff;
 		cpu_if->vgic_ap0r[0] = 0;
 		cpu_if->vgic_ap0r[1] = 0;
@@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
 
 		for (i = 0; i < used_lrs; i++)
 			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
+	} else {
+		/* Always write ICH_HCR_EL2 to enable trapping */
+		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
+			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
 	}
 
 	/*
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 063526443781..547b8374fb64 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -21,6 +21,8 @@
 
 #include "vgic.h"
 
+static bool group1_trap;
+
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
 	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
@@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 
 	/* Get the show on the road... */
 	vgic_v3->vgic_hcr = ICH_HCR_EN;
+	if (group1_trap)
+		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
-- 
2.11.0

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

* [PATCH 18/31] KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Now that we're able to safely handle Group-1 sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.group1_trap).

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

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 547b8374fb64..71ecf448ca49 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -324,6 +324,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
 
 DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
 
+static int __init early_group1_trap_cfg(char *buf)
+{
+	return strtobool(buf, &group1_trap);
+}
+early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
@@ -375,6 +381,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
 
+	if (group1_trap) {
+		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
+		static_branch_enable(&vgic_v3_cpuif_trap);
+	}
+
 	kvm_vgic_global_state.vctrl_base = NULL;
 	kvm_vgic_global_state.type = VGIC_V3;
 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
-- 
2.11.0

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

* [PATCH 18/31] KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we're able to safely handle Group-1 sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.group1_trap).

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

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 547b8374fb64..71ecf448ca49 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -324,6 +324,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
 
 DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
 
+static int __init early_group1_trap_cfg(char *buf)
+{
+	return strtobool(buf, &group1_trap);
+}
+early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
@@ -375,6 +381,11 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
 
+	if (group1_trap) {
+		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
+		static_branch_enable(&vgic_v3_cpuif_trap);
+	}
+
 	kvm_vgic_global_state.vctrl_base = NULL;
 	kvm_vgic_global_state.type = VGIC_V3;
 	kvm_vgic_global_state.max_gic_vcpus = VGIC_V3_MAX_CPUS;
-- 
2.11.0

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

* [PATCH 19/31] KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_BPR0_EL1
register, which is located in the ICH_VMCR_EL2.BPR0 field.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index bd000686194a..d20be0b28ca4 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,6 +180,7 @@
 
 #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
 
+#define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
 #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a27671b1e9af..b21bb0c77ec2 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -666,11 +666,41 @@ static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr,
 	__vgic_v3_write_vmcr(vmcr);
 }
 
+static void __hyp_text __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr0(vmcr));
+}
+
 static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
 }
 
+static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+	u8 bpr_min = 7 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+
+	/* Enforce BPR limiting */
+	if (val < bpr_min)
+		val = bpr_min;
+
+	val <<= ICH_VMCR_BPR0_SHIFT;
+	val &= ICH_VMCR_BPR0_MASK;
+	vmcr &= ~ICH_VMCR_BPR0_MASK;
+	vmcr |= val;
+
+	if (vmcr & ICH_VMCR_CBPR_MASK) {
+		val = __vgic_v3_get_bpr1(vmcr);
+		val <<= ICH_VMCR_BPR1_SHIFT;
+		val &= ICH_VMCR_BPR1_MASK;
+		vmcr &= ~ICH_VMCR_BPR1_MASK;
+		vmcr |= val;
+	}
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u64 val = vcpu_get_reg(vcpu, rt);
@@ -846,6 +876,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_HPPIR1_EL1:
 		fn = __vgic_v3_read_hppir;
 		break;
+	case SYS_ICC_BPR0_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_bpr0;
+		else
+			fn = __vgic_v3_write_bpr0;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 19/31] KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_BPR0_EL1
register, which is located in the ICH_VMCR_EL2.BPR0 field.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 36 ++++++++++++++++++++++++++++++++++++
 2 files changed, 37 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index bd000686194a..d20be0b28ca4 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,6 +180,7 @@
 
 #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
 
+#define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
 #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index a27671b1e9af..b21bb0c77ec2 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -666,11 +666,41 @@ static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr,
 	__vgic_v3_write_vmcr(vmcr);
 }
 
+static void __hyp_text __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr0(vmcr));
+}
+
 static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
 }
 
+static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+	u8 bpr_min = 7 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
+
+	/* Enforce BPR limiting */
+	if (val < bpr_min)
+		val = bpr_min;
+
+	val <<= ICH_VMCR_BPR0_SHIFT;
+	val &= ICH_VMCR_BPR0_MASK;
+	vmcr &= ~ICH_VMCR_BPR0_MASK;
+	vmcr |= val;
+
+	if (vmcr & ICH_VMCR_CBPR_MASK) {
+		val = __vgic_v3_get_bpr1(vmcr);
+		val <<= ICH_VMCR_BPR1_SHIFT;
+		val &= ICH_VMCR_BPR1_MASK;
+		vmcr &= ~ICH_VMCR_BPR1_MASK;
+		vmcr |= val;
+	}
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u64 val = vcpu_get_reg(vcpu, rt);
@@ -846,6 +876,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_HPPIR1_EL1:
 		fn = __vgic_v3_read_hppir;
 		break;
+	case SYS_ICC_BPR0_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_bpr0;
+		else
+			fn = __vgic_v3_write_bpr0;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 20/31] KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_IGRPEN0_EL1
register, which is located in the ICH_VMCR_EL2.VENG0 field.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index d20be0b28ca4..ba93bc7ac8e4 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -190,6 +190,7 @@
 #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
 #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
 #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
+#define SYS_ICC_GRPEN0_EL1		sys_reg(3, 0, 12, 12, 6)
 #define SYS_ICC_GRPEN1_EL1		sys_reg(3, 0, 12, 12, 7)
 
 #define SYS_CONTEXTIDR_EL1		sys_reg(3, 0, 13, 0, 1)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index b21bb0c77ec2..77d5d12389ec 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -649,11 +649,28 @@ static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int
 	__vgic_v3_clear_active_lr(lr, lr_val);
 }
 
+static void __hyp_text __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK));
+}
+
 static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
 }
 
+static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+
+	if (val & 1)
+		vmcr |= ICH_VMCR_ENG0_MASK;
+	else
+		vmcr &= ~ICH_VMCR_ENG0_MASK;
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u64 val = vcpu_get_reg(vcpu, rt);
@@ -876,6 +893,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_HPPIR1_EL1:
 		fn = __vgic_v3_read_hppir;
 		break;
+	case SYS_ICC_GRPEN0_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_igrpen0;
+		else
+			fn = __vgic_v3_write_igrpen0;
+		break;
 	case SYS_ICC_BPR0_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_bpr0;
-- 
2.11.0

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

* [PATCH 20/31] KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_IGRPEN0_EL1
register, which is located in the ICH_VMCR_EL2.VENG0 field.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
 2 files changed, 24 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index d20be0b28ca4..ba93bc7ac8e4 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -190,6 +190,7 @@
 #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
 #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
 #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
+#define SYS_ICC_GRPEN0_EL1		sys_reg(3, 0, 12, 12, 6)
 #define SYS_ICC_GRPEN1_EL1		sys_reg(3, 0, 12, 12, 7)
 
 #define SYS_CONTEXTIDR_EL1		sys_reg(3, 0, 13, 0, 1)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index b21bb0c77ec2..77d5d12389ec 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -649,11 +649,28 @@ static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int
 	__vgic_v3_clear_active_lr(lr, lr_val);
 }
 
+static void __hyp_text __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK));
+}
+
 static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
 }
 
+static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
+{
+	u64 val = vcpu_get_reg(vcpu, rt);
+
+	if (val & 1)
+		vmcr |= ICH_VMCR_ENG0_MASK;
+	else
+		vmcr &= ~ICH_VMCR_ENG0_MASK;
+
+	__vgic_v3_write_vmcr(vmcr);
+}
+
 static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u64 val = vcpu_get_reg(vcpu, rt);
@@ -876,6 +893,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_HPPIR1_EL1:
 		fn = __vgic_v3_read_hppir;
 		break;
+	case SYS_ICC_GRPEN0_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_igrpen0;
+		else
+			fn = __vgic_v3_write_igrpen0;
+		break;
 	case SYS_ICC_BPR0_EL1:
 		if (is_read)
 			fn = __vgic_v3_read_bpr0;
-- 
2.11.0

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

* [PATCH 21/31] KVM: arm64: vgic-v3: Add misc Group-0 handlers
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

A number of Group-0 registers can be handled by the same accessors
as that of Group-1, so let's add the required system register encodings
and catch them in the dispatching function.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h | 4 ++++
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index ba93bc7ac8e4..9971c5c435a7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,7 +180,11 @@
 
 #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
 
+#define SYS_ICC_IAR0_EL1		sys_reg(3, 0, 12, 8, 0)
+#define SYS_ICC_EOIR0_EL1		sys_reg(3, 0, 12, 8, 1)
+#define SYS_ICC_HPPIR0_EL1		sys_reg(3, 0, 12, 8, 2)
 #define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
+#define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
 #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 77d5d12389ec..9c639f57268b 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,9 +848,11 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
 
 	switch (sysreg) {
+	case SYS_ICC_IAR0_EL1:
 	case SYS_ICC_IAR1_EL1:
 		fn = __vgic_v3_read_iar;
 		break;
+	case SYS_ICC_EOIR0_EL1:
 	case SYS_ICC_EOIR1_EL1:
 		fn = __vgic_v3_write_eoir;
 		break;
@@ -866,30 +868,35 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_bpr1;
 		break;
+	case SYS_ICC_AP0Rn_EL1(0):
 	case SYS_ICC_AP1Rn_EL1(0):
 		if (is_read)
 			fn = __vgic_v3_read_apxr0;
 		else
 			fn = __vgic_v3_write_apxr0;
 		break;
+	case SYS_ICC_AP0Rn_EL1(1):
 	case SYS_ICC_AP1Rn_EL1(1):
 		if (is_read)
 			fn = __vgic_v3_read_apxr1;
 		else
 			fn = __vgic_v3_write_apxr1;
 		break;
+	case SYS_ICC_AP0Rn_EL1(2):
 	case SYS_ICC_AP1Rn_EL1(2):
 		if (is_read)
 			fn = __vgic_v3_read_apxr2;
 		else
 			fn = __vgic_v3_write_apxr2;
 		break;
+	case SYS_ICC_AP0Rn_EL1(3):
 	case SYS_ICC_AP1Rn_EL1(3):
 		if (is_read)
 			fn = __vgic_v3_read_apxr3;
 		else
 			fn = __vgic_v3_write_apxr3;
 		break;
+	case SYS_ICC_HPPIR0_EL1:
 	case SYS_ICC_HPPIR1_EL1:
 		fn = __vgic_v3_read_hppir;
 		break;
-- 
2.11.0

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

* [PATCH 21/31] KVM: arm64: vgic-v3: Add misc Group-0 handlers
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

A number of Group-0 registers can be handled by the same accessors
as that of Group-1, so let's add the required system register encodings
and catch them in the dispatching function.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h | 4 ++++
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 7 +++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index ba93bc7ac8e4..9971c5c435a7 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -180,7 +180,11 @@
 
 #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
 
+#define SYS_ICC_IAR0_EL1		sys_reg(3, 0, 12, 8, 0)
+#define SYS_ICC_EOIR0_EL1		sys_reg(3, 0, 12, 8, 1)
+#define SYS_ICC_HPPIR0_EL1		sys_reg(3, 0, 12, 8, 2)
 #define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
+#define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
 #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 77d5d12389ec..9c639f57268b 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,9 +848,11 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
 
 	switch (sysreg) {
+	case SYS_ICC_IAR0_EL1:
 	case SYS_ICC_IAR1_EL1:
 		fn = __vgic_v3_read_iar;
 		break;
+	case SYS_ICC_EOIR0_EL1:
 	case SYS_ICC_EOIR1_EL1:
 		fn = __vgic_v3_write_eoir;
 		break;
@@ -866,30 +868,35 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_bpr1;
 		break;
+	case SYS_ICC_AP0Rn_EL1(0):
 	case SYS_ICC_AP1Rn_EL1(0):
 		if (is_read)
 			fn = __vgic_v3_read_apxr0;
 		else
 			fn = __vgic_v3_write_apxr0;
 		break;
+	case SYS_ICC_AP0Rn_EL1(1):
 	case SYS_ICC_AP1Rn_EL1(1):
 		if (is_read)
 			fn = __vgic_v3_read_apxr1;
 		else
 			fn = __vgic_v3_write_apxr1;
 		break;
+	case SYS_ICC_AP0Rn_EL1(2):
 	case SYS_ICC_AP1Rn_EL1(2):
 		if (is_read)
 			fn = __vgic_v3_read_apxr2;
 		else
 			fn = __vgic_v3_write_apxr2;
 		break;
+	case SYS_ICC_AP0Rn_EL1(3):
 	case SYS_ICC_AP1Rn_EL1(3):
 		if (is_read)
 			fn = __vgic_v3_read_apxr3;
 		else
 			fn = __vgic_v3_write_apxr3;
 		break;
+	case SYS_ICC_HPPIR0_EL1:
 	case SYS_ICC_HPPIR1_EL1:
 		fn = __vgic_v3_read_hppir;
 		break;
-- 
2.11.0

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

* [PATCH 22/31] KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

In order to be able to trap Group-0 GICv3 system registers, we need to
set ICH_HCR_EL2.TALL0 begore entering the guest. This is conditionnaly
done after having restored the guest's state, and cleared on exit.

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index a1739843343e..7fef09bcf7b1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_TALL0			(1 << 11)
 #define ICH_HCR_TALL1			(1 << 12)
 #define ICH_HCR_EOIcount_SHIFT		27
 #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 71ecf448ca49..812f179a6931 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -21,6 +21,7 @@
 
 #include "vgic.h"
 
+static bool group0_trap;
 static bool group1_trap;
 
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
@@ -241,6 +242,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 
 	/* Get the show on the road... */
 	vgic_v3->vgic_hcr = ICH_HCR_EN;
+	if (group0_trap)
+		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
 	if (group1_trap)
 		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
 }
@@ -381,7 +384,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
 
-	if (group1_trap) {
+	if (group0_trap || group1_trap) {
 		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
 		static_branch_enable(&vgic_v3_cpuif_trap);
 	}
-- 
2.11.0

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

* [PATCH 22/31] KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

In order to be able to trap Group-0 GICv3 system registers, we need to
set ICH_HCR_EL2.TALL0 begore entering the guest. This is conditionnaly
done after having restored the guest's state, and cleared on exit.

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index a1739843343e..7fef09bcf7b1 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_TALL0			(1 << 11)
 #define ICH_HCR_TALL1			(1 << 12)
 #define ICH_HCR_EOIcount_SHIFT		27
 #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 71ecf448ca49..812f179a6931 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -21,6 +21,7 @@
 
 #include "vgic.h"
 
+static bool group0_trap;
 static bool group1_trap;
 
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
@@ -241,6 +242,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 
 	/* Get the show on the road... */
 	vgic_v3->vgic_hcr = ICH_HCR_EN;
+	if (group0_trap)
+		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
 	if (group1_trap)
 		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
 }
@@ -381,7 +384,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
 
-	if (group1_trap) {
+	if (group0_trap || group1_trap) {
 		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
 		static_branch_enable(&vgic_v3_cpuif_trap);
 	}
-- 
2.11.0

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

* [PATCH 23/31] KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Now that we're able to safely handle Group-0 sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.group0_trap).

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

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 812f179a6931..7c82c586d44a 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -327,6 +327,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
 
 DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
 
+static int __init early_group0_trap_cfg(char *buf)
+{
+	return strtobool(buf, &group0_trap);
+}
+early_param("vgic_v3.group0_trap", early_group0_trap_cfg);
+
 static int __init early_group1_trap_cfg(char *buf)
 {
 	return strtobool(buf, &group1_trap);
-- 
2.11.0

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

* [PATCH 23/31] KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we're able to safely handle Group-0 sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.group0_trap).

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

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 812f179a6931..7c82c586d44a 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -327,6 +327,12 @@ int vgic_v3_map_resources(struct kvm *kvm)
 
 DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
 
+static int __init early_group0_trap_cfg(char *buf)
+{
+	return strtobool(buf, &group0_trap);
+}
+early_param("vgic_v3.group0_trap", early_group0_trap_cfg);
+
 static int __init early_group1_trap_cfg(char *buf)
 {
 	return strtobool(buf, &group1_trap);
-- 
2.11.0

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

* [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:45   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

From: David Daney <david.daney@cavium.com>

Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/cputype.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 0984d1b3a8f2..235e77d98261 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -86,6 +86,7 @@
 
 #define CAVIUM_CPU_PART_THUNDERX	0x0A1
 #define CAVIUM_CPU_PART_THUNDERX_81XX	0x0A2
+#define CAVIUM_CPU_PART_THUNDERX_83XX	0x0A3
 
 #define BRCM_CPU_PART_VULCAN		0x516
 
@@ -96,6 +97,7 @@
 #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
+#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
 #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
 
 #ifndef __ASSEMBLY__
-- 
2.11.0

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

* [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
@ 2017-05-03 10:45   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:45 UTC (permalink / raw)
  To: linux-arm-kernel

From: David Daney <david.daney@cavium.com>

Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/cputype.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
index 0984d1b3a8f2..235e77d98261 100644
--- a/arch/arm64/include/asm/cputype.h
+++ b/arch/arm64/include/asm/cputype.h
@@ -86,6 +86,7 @@
 
 #define CAVIUM_CPU_PART_THUNDERX	0x0A1
 #define CAVIUM_CPU_PART_THUNDERX_81XX	0x0A2
+#define CAVIUM_CPU_PART_THUNDERX_83XX	0x0A3
 
 #define BRCM_CPU_PART_VULCAN		0x516
 
@@ -96,6 +97,7 @@
 #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
 #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
 #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
+#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
 #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
 
 #ifndef __ASSEMBLY__
-- 
2.11.0

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

* [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

From: David Daney <david.daney@cavium.com>

Some Cavium Thunder CPUs suffer a problem where a KVM guest may
inadvertently cause the host kernel to quit receiving interrupts.

Use the Group-0/1 trapping in order to deal with it.

[maz]: Adapted patch to the Group-0/1 trapping, reworked commit log

Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/arm64/silicon-errata.txt |  1 +
 arch/arm64/Kconfig                     | 11 +++++++++++
 arch/arm64/include/asm/cpucaps.h       |  3 ++-
 arch/arm64/kernel/cpu_errata.c         | 21 +++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c            |  7 +++++++
 5 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 10f2dddbf449..f5f93dca54b7 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -62,6 +62,7 @@ stable kernels.
 | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154        |
 | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456        |
 | Cavium         | ThunderX SMMUv2 | #27704          | N/A                         |
+| Cavium         | ThunderX Core   | #30115          | CAVIUM_ERRATUM_30115        |
 |                |                 |                 |                             |
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
 |                |                 |                 |                             |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3dcd7ec69bca..0950b21e4d17 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -480,6 +480,17 @@ config CAVIUM_ERRATUM_27456
 
 	  If unsure, say Y.
 
+config CAVIUM_ERRATUM_30115
+	bool "Cavium erratum 30115: Guest may disable interrupts in host"
+	default y
+	help
+	  On ThunderX T88 pass 1.x through 2.2, T81 pass 1.0 through
+	  1.2, and T83 Pass 1.0, KVM guest execution may disable
+	  interrupts in host. Trapping GICv3 group-1 accesses sidesteps
+	  the issue.
+
+	  If unsure, say Y.
+
 config QCOM_FALKOR_ERRATUM_1003
 	bool "Falkor E1003: Incorrect translation due to ASID change"
 	default y
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index b3aab8a17868..8d2272c6822c 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -38,7 +38,8 @@
 #define ARM64_WORKAROUND_REPEAT_TLBI		17
 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003	18
 #define ARM64_WORKAROUND_858921			19
+#define ARM64_WORKAROUND_CAVIUM_30115		20
 
-#define ARM64_NCAPS				20
+#define ARM64_NCAPS				21
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 2ed2a7657711..0e27f86ee709 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -133,6 +133,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
 	},
 #endif
+#ifdef CONFIG_CAVIUM_ERRATUM_30115
+	{
+	/* Cavium ThunderX, T88 pass 1.x - 2.2 */
+		.desc = "Cavium erratum 30115",
+		.capability = ARM64_WORKAROUND_CAVIUM_30115,
+		MIDR_RANGE(MIDR_THUNDERX, 0x00,
+			   (1 << MIDR_VARIANT_SHIFT) | 2),
+	},
+	{
+	/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
+		.desc = "Cavium erratum 30115",
+		.capability = ARM64_WORKAROUND_CAVIUM_30115,
+		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
+	},
+	{
+	/* Cavium ThunderX, T83 pass 1.0 */
+		.desc = "Cavium erratum 30115",
+		.capability = ARM64_WORKAROUND_CAVIUM_30115,
+		MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
+	},
+#endif
 	{
 		.desc = "Mismatched cache line size",
 		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 7c82c586d44a..445e86c8b00c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -390,6 +390,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
 
+#ifdef CONFIG_ARM64
+	if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
+		group0_trap = true;
+		group1_trap = true;
+	}
+#endif
+
 	if (group0_trap || group1_trap) {
 		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
 		static_branch_enable(&vgic_v3_cpuif_trap);
-- 
2.11.0

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

* [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

From: David Daney <david.daney@cavium.com>

Some Cavium Thunder CPUs suffer a problem where a KVM guest may
inadvertently cause the host kernel to quit receiving interrupts.

Use the Group-0/1 trapping in order to deal with it.

[maz]: Adapted patch to the Group-0/1 trapping, reworked commit log

Signed-off-by: David Daney <david.daney@cavium.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 Documentation/arm64/silicon-errata.txt |  1 +
 arch/arm64/Kconfig                     | 11 +++++++++++
 arch/arm64/include/asm/cpucaps.h       |  3 ++-
 arch/arm64/kernel/cpu_errata.c         | 21 +++++++++++++++++++++
 virt/kvm/arm/vgic/vgic-v3.c            |  7 +++++++
 5 files changed, 42 insertions(+), 1 deletion(-)

diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
index 10f2dddbf449..f5f93dca54b7 100644
--- a/Documentation/arm64/silicon-errata.txt
+++ b/Documentation/arm64/silicon-errata.txt
@@ -62,6 +62,7 @@ stable kernels.
 | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154        |
 | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456        |
 | Cavium         | ThunderX SMMUv2 | #27704          | N/A                         |
+| Cavium         | ThunderX Core   | #30115          | CAVIUM_ERRATUM_30115        |
 |                |                 |                 |                             |
 | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
 |                |                 |                 |                             |
diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
index 3dcd7ec69bca..0950b21e4d17 100644
--- a/arch/arm64/Kconfig
+++ b/arch/arm64/Kconfig
@@ -480,6 +480,17 @@ config CAVIUM_ERRATUM_27456
 
 	  If unsure, say Y.
 
+config CAVIUM_ERRATUM_30115
+	bool "Cavium erratum 30115: Guest may disable interrupts in host"
+	default y
+	help
+	  On ThunderX T88 pass 1.x through 2.2, T81 pass 1.0 through
+	  1.2, and T83 Pass 1.0, KVM guest execution may disable
+	  interrupts in host. Trapping GICv3 group-1 accesses sidesteps
+	  the issue.
+
+	  If unsure, say Y.
+
 config QCOM_FALKOR_ERRATUM_1003
 	bool "Falkor E1003: Incorrect translation due to ASID change"
 	default y
diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
index b3aab8a17868..8d2272c6822c 100644
--- a/arch/arm64/include/asm/cpucaps.h
+++ b/arch/arm64/include/asm/cpucaps.h
@@ -38,7 +38,8 @@
 #define ARM64_WORKAROUND_REPEAT_TLBI		17
 #define ARM64_WORKAROUND_QCOM_FALKOR_E1003	18
 #define ARM64_WORKAROUND_858921			19
+#define ARM64_WORKAROUND_CAVIUM_30115		20
 
-#define ARM64_NCAPS				20
+#define ARM64_NCAPS				21
 
 #endif /* __ASM_CPUCAPS_H */
diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
index 2ed2a7657711..0e27f86ee709 100644
--- a/arch/arm64/kernel/cpu_errata.c
+++ b/arch/arm64/kernel/cpu_errata.c
@@ -133,6 +133,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
 		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
 	},
 #endif
+#ifdef CONFIG_CAVIUM_ERRATUM_30115
+	{
+	/* Cavium ThunderX, T88 pass 1.x - 2.2 */
+		.desc = "Cavium erratum 30115",
+		.capability = ARM64_WORKAROUND_CAVIUM_30115,
+		MIDR_RANGE(MIDR_THUNDERX, 0x00,
+			   (1 << MIDR_VARIANT_SHIFT) | 2),
+	},
+	{
+	/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
+		.desc = "Cavium erratum 30115",
+		.capability = ARM64_WORKAROUND_CAVIUM_30115,
+		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
+	},
+	{
+	/* Cavium ThunderX, T83 pass 1.0 */
+		.desc = "Cavium erratum 30115",
+		.capability = ARM64_WORKAROUND_CAVIUM_30115,
+		MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
+	},
+#endif
 	{
 		.desc = "Mismatched cache line size",
 		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 7c82c586d44a..445e86c8b00c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -390,6 +390,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	if (kvm_vgic_global_state.vcpu_base == 0)
 		kvm_info("disabling GICv2 emulation\n");
 
+#ifdef CONFIG_ARM64
+	if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
+		group0_trap = true;
+		group1_trap = true;
+	}
+#endif
+
 	if (group0_trap || group1_trap) {
 		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
 		static_branch_enable(&vgic_v3_cpuif_trap);
-- 
2.11.0

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

* [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for writing the guest's view of the ICC_DIR_EL1
register, performing the deactivation of an interrupt if EOImode
is set ot 1.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 9c639f57268b..563dd2d16c59 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
 	write_gicreg(hcr, ICH_HCR_EL2);
 }
 
+static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
+					   u32 vmcr, int rt)
+{
+	u32 vid = vcpu_get_reg(vcpu, rt);
+	u64 lr_val;
+	int lr;
+
+	/* No deactivate to be performed on an LPI */
+	if (vid >= VGIC_MIN_LPI)
+		return;
+
+	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
+	if (lr == -1) {
+		__vgic_v3_bump_eoicount();
+		return;
+	}
+
+	__vgic_v3_clear_active_lr(lr, lr_val);
+}
+
 static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u32 vid = vcpu_get_reg(vcpu, rt);
@@ -912,6 +932,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_bpr0;
 		break;
+	case SYS_ICC_DIR_EL1:
+		fn = __vgic_v3_write_dir;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for writing the guest's view of the ICC_DIR_EL1
register, performing the deactivation of an interrupt if EOImode
is set ot 1.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 9c639f57268b..563dd2d16c59 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
 	write_gicreg(hcr, ICH_HCR_EL2);
 }
 
+static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
+					   u32 vmcr, int rt)
+{
+	u32 vid = vcpu_get_reg(vcpu, rt);
+	u64 lr_val;
+	int lr;
+
+	/* No deactivate to be performed on an LPI */
+	if (vid >= VGIC_MIN_LPI)
+		return;
+
+	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
+	if (lr == -1) {
+		__vgic_v3_bump_eoicount();
+		return;
+	}
+
+	__vgic_v3_clear_active_lr(lr, lr_val);
+}
+
 static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
 {
 	u32 vid = vcpu_get_reg(vcpu, rt);
@@ -912,6 +932,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_bpr0;
 		break;
+	case SYS_ICC_DIR_EL1:
+		fn = __vgic_v3_write_dir;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 27/31] KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading the guest's view of the ICV_RPR_EL1
register, returning the highest active priority.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 9971c5c435a7..c4d48e403629 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -187,6 +187,7 @@
 #define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
 #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
+#define SYS_ICC_RPR_EL1			sys_reg(3, 0, 12, 11, 3)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
 #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
 #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 563dd2d16c59..3a5f54f445b9 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,6 +848,13 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
 	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
 }
 
+static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
+					  u32 vmcr, int rt)
+{
+	u32 val = __vgic_v3_get_highest_active_priority();
+	vcpu_set_reg(vcpu, rt, val);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -935,6 +942,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_DIR_EL1:
 		fn = __vgic_v3_write_dir;
 		break;
+	case SYS_ICC_RPR_EL1:
+		fn = __vgic_v3_read_rpr;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 27/31] KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading the guest's view of the ICV_RPR_EL1
register, returning the highest active priority.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
 arch/arm64/include/asm/sysreg.h |  1 +
 virt/kvm/arm/hyp/vgic-v3-sr.c   | 10 ++++++++++
 2 files changed, 11 insertions(+)

diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
index 9971c5c435a7..c4d48e403629 100644
--- a/arch/arm64/include/asm/sysreg.h
+++ b/arch/arm64/include/asm/sysreg.h
@@ -187,6 +187,7 @@
 #define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
 #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
 #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
+#define SYS_ICC_RPR_EL1			sys_reg(3, 0, 12, 11, 3)
 #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
 #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
 #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 563dd2d16c59..3a5f54f445b9 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,6 +848,13 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
 	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
 }
 
+static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
+					  u32 vmcr, int rt)
+{
+	u32 val = __vgic_v3_get_highest_active_priority();
+	vcpu_set_reg(vcpu, rt, val);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -935,6 +942,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_DIR_EL1:
 		fn = __vgic_v3_write_dir;
 		break;
+	case SYS_ICC_RPR_EL1:
+		fn = __vgic_v3_read_rpr;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 28/31] KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICV_CTLR_EL1
register. only EOIMode and CBPR are of interest here, as all the other
bits directly come from ICH_VTR_EL2 and are Read-Only.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 3a5f54f445b9..981201bf7a5e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -855,6 +855,46 @@ static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
 	vcpu_set_reg(vcpu, rt, val);
 }
 
+static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu,
+					   u32 vmcr, int rt)
+{
+	u32 vtr, val;
+
+	vtr = read_gicreg(ICH_VTR_EL2);
+	/* PRIbits */
+	val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
+	/* IDbits */
+	val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
+	/* SEIS */
+	val |= ((vtr >> 22) & 1) << ICC_CTLR_EL1_SEIS_SHIFT;
+	/* A3V */
+	val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
+	/* EOImode */
+	val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
+	/* CBPR */
+	val |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+
+	vcpu_set_reg(vcpu, rt, val);
+}
+
+static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	u32 val = vcpu_get_reg(vcpu, rt);
+
+	if (val & ICC_CTLR_EL1_CBPR_MASK)
+		vmcr |= ICH_VMCR_CBPR_MASK;
+	else
+		vmcr &= ~ICH_VMCR_CBPR_MASK;
+
+	if (val & ICC_CTLR_EL1_EOImode_MASK)
+		vmcr |= ICH_VMCR_EOIM_MASK;
+	else
+		vmcr &= ~ICH_VMCR_EOIM_MASK;
+
+	write_gicreg(vmcr, ICH_VMCR_EL2);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -945,6 +985,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_RPR_EL1:
 		fn = __vgic_v3_read_rpr;
 		break;
+	case SYS_ICC_CTLR_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_ctlr;
+		else
+			fn = __vgic_v3_write_ctlr;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 28/31] KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICV_CTLR_EL1
register. only EOIMode and CBPR are of interest here, as all the other
bits directly come from ICH_VTR_EL2 and are Read-Only.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 3a5f54f445b9..981201bf7a5e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -855,6 +855,46 @@ static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
 	vcpu_set_reg(vcpu, rt, val);
 }
 
+static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu,
+					   u32 vmcr, int rt)
+{
+	u32 vtr, val;
+
+	vtr = read_gicreg(ICH_VTR_EL2);
+	/* PRIbits */
+	val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
+	/* IDbits */
+	val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
+	/* SEIS */
+	val |= ((vtr >> 22) & 1) << ICC_CTLR_EL1_SEIS_SHIFT;
+	/* A3V */
+	val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
+	/* EOImode */
+	val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
+	/* CBPR */
+	val |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
+
+	vcpu_set_reg(vcpu, rt, val);
+}
+
+static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu,
+					    u32 vmcr, int rt)
+{
+	u32 val = vcpu_get_reg(vcpu, rt);
+
+	if (val & ICC_CTLR_EL1_CBPR_MASK)
+		vmcr |= ICH_VMCR_CBPR_MASK;
+	else
+		vmcr &= ~ICH_VMCR_CBPR_MASK;
+
+	if (val & ICC_CTLR_EL1_EOImode_MASK)
+		vmcr |= ICH_VMCR_EOIM_MASK;
+	else
+		vmcr &= ~ICH_VMCR_EOIM_MASK;
+
+	write_gicreg(vmcr, ICH_VMCR_EL2);
+}
+
 int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 {
 	int rt = kvm_vcpu_sys_get_rt(vcpu);
@@ -945,6 +985,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 	case SYS_ICC_RPR_EL1:
 		fn = __vgic_v3_read_rpr;
 		break;
+	case SYS_ICC_CTLR_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_ctlr;
+		else
+			fn = __vgic_v3_write_ctlr;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 29/31] KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_PMR_EL1
register, which is located in the ICH_VMCR_EL2.VPMR field.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 981201bf7a5e..4fbeeb54704e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,6 +848,27 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
 	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
 }
 
+static void __hyp_text __vgic_v3_read_pmr(struct kvm_vcpu *vcpu,
+					  u32 vmcr, int rt)
+{
+	vmcr &= ICH_VMCR_PMR_MASK;
+	vmcr >>= ICH_VMCR_PMR_SHIFT;
+	vcpu_set_reg(vcpu, rt, vmcr);
+}
+
+static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu,
+					   u32 vmcr, int rt)
+{
+	u32 val = vcpu_get_reg(vcpu, rt);
+
+	val <<= ICH_VMCR_PMR_SHIFT;
+	val &= ICH_VMCR_PMR_MASK;
+	vmcr &= ~ICH_VMCR_PMR_MASK;
+	vmcr |= val;
+
+	write_gicreg(vmcr, ICH_VMCR_EL2);
+}
+
 static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
 					  u32 vmcr, int rt)
 {
@@ -991,6 +1012,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_ctlr;
 		break;
+	case SYS_ICC_PMR_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_pmr;
+		else
+			fn = __vgic_v3_write_pmr;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 29/31] KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Add a handler for reading/writing the guest's view of the ICC_PMR_EL1
register, which is located in the ICH_VMCR_EL2.VPMR field.

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

diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
index 981201bf7a5e..4fbeeb54704e 100644
--- a/virt/kvm/arm/hyp/vgic-v3-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
@@ -848,6 +848,27 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
 	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
 }
 
+static void __hyp_text __vgic_v3_read_pmr(struct kvm_vcpu *vcpu,
+					  u32 vmcr, int rt)
+{
+	vmcr &= ICH_VMCR_PMR_MASK;
+	vmcr >>= ICH_VMCR_PMR_SHIFT;
+	vcpu_set_reg(vcpu, rt, vmcr);
+}
+
+static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu,
+					   u32 vmcr, int rt)
+{
+	u32 val = vcpu_get_reg(vcpu, rt);
+
+	val <<= ICH_VMCR_PMR_SHIFT;
+	val &= ICH_VMCR_PMR_MASK;
+	vmcr &= ~ICH_VMCR_PMR_MASK;
+	vmcr |= val;
+
+	write_gicreg(vmcr, ICH_VMCR_EL2);
+}
+
 static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
 					  u32 vmcr, int rt)
 {
@@ -991,6 +1012,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
 		else
 			fn = __vgic_v3_write_ctlr;
 		break;
+	case SYS_ICC_PMR_EL1:
+		if (is_read)
+			fn = __vgic_v3_read_pmr;
+		else
+			fn = __vgic_v3_write_pmr;
+		break;
 	default:
 		return 0;
 	}
-- 
2.11.0

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

* [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Now that we're able to safely handle common sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.common_trap).

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 7fef09bcf7b1..2692217ac667 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_TC			(1 << 10)
 #define ICH_HCR_TALL0			(1 << 11)
 #define ICH_HCR_TALL1			(1 << 12)
 #define ICH_HCR_EOIcount_SHIFT		27
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 445e86c8b00c..717219ab58a2 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -23,6 +23,7 @@
 
 static bool group0_trap;
 static bool group1_trap;
+static bool common_trap;
 
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
@@ -246,6 +247,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
 	if (group1_trap)
 		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
+	if (common_trap)
+		vgic_v3->vgic_hcr |= ICH_HCR_TC;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
@@ -339,6 +342,12 @@ static int __init early_group1_trap_cfg(char *buf)
 }
 early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
 
+static int __init early_common_trap_cfg(char *buf)
+{
+	return strtobool(buf, &common_trap);
+}
+early_param("vgic_v3.common_trap", early_common_trap_cfg);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
@@ -397,7 +406,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	}
 #endif
 
-	if (group0_trap || group1_trap) {
+	if (group0_trap || group1_trap || common_trap) {
 		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
 		static_branch_enable(&vgic_v3_cpuif_trap);
 	}
-- 
2.11.0

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

* [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

Now that we're able to safely handle common sysreg access, let's
give the user the opportunity to enable it by passing a specific
command-line option (vgic_v3.common_trap).

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

diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
index 7fef09bcf7b1..2692217ac667 100644
--- a/include/linux/irqchip/arm-gic-v3.h
+++ b/include/linux/irqchip/arm-gic-v3.h
@@ -403,6 +403,7 @@
 
 #define ICH_HCR_EN			(1 << 0)
 #define ICH_HCR_UIE			(1 << 1)
+#define ICH_HCR_TC			(1 << 10)
 #define ICH_HCR_TALL0			(1 << 11)
 #define ICH_HCR_TALL1			(1 << 12)
 #define ICH_HCR_EOIcount_SHIFT		27
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 445e86c8b00c..717219ab58a2 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -23,6 +23,7 @@
 
 static bool group0_trap;
 static bool group1_trap;
+static bool common_trap;
 
 void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
 {
@@ -246,6 +247,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
 		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
 	if (group1_trap)
 		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
+	if (common_trap)
+		vgic_v3->vgic_hcr |= ICH_HCR_TC;
 }
 
 /* check for overlapping regions and for regions crossing the end of memory */
@@ -339,6 +342,12 @@ static int __init early_group1_trap_cfg(char *buf)
 }
 early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
 
+static int __init early_common_trap_cfg(char *buf)
+{
+	return strtobool(buf, &common_trap);
+}
+early_param("vgic_v3.common_trap", early_common_trap_cfg);
+
 /**
  * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
  * @node:	pointer to the DT node
@@ -397,7 +406,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 	}
 #endif
 
-	if (group0_trap || group1_trap) {
+	if (group0_trap || group1_trap || common_trap) {
 		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
 		static_branch_enable(&vgic_v3_cpuif_trap);
 	}
-- 
2.11.0

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

* [PATCH 31/31] KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-03 10:46   ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

In order to facilitate debug, let's log which class of GICv3 system
registers are trapped.

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

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 717219ab58a2..9110657b502c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -407,7 +407,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 #endif
 
 	if (group0_trap || group1_trap || common_trap) {
-		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
+		kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
+			 group0_trap ? "G0" : "",
+			 group1_trap ? "G1" : "",
+			 common_trap ? "C"  : "");
 		static_branch_enable(&vgic_v3_cpuif_trap);
 	}
 
-- 
2.11.0

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

* [PATCH 31/31] KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
@ 2017-05-03 10:46   ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 10:46 UTC (permalink / raw)
  To: linux-arm-kernel

In order to facilitate debug, let's log which class of GICv3 system
registers are trapped.

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

diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 717219ab58a2..9110657b502c 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -407,7 +407,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
 #endif
 
 	if (group0_trap || group1_trap || common_trap) {
-		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
+		kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
+			 group0_trap ? "G0" : "",
+			 group1_trap ? "G1" : "",
+			 common_trap ? "C"  : "");
 		static_branch_enable(&vgic_v3_cpuif_trap);
 	}
 
-- 
2.11.0

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-03 15:32     ` Mark Rutland
  -1 siblings, 0 replies; 162+ messages in thread
From: Mark Rutland @ 2017-05-03 15:32 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Christoffer Dall, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
> As we're about to access the Active Priority registers a lot more,
> let's define accessors that take the register number as a parameter.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>  1 file changed, 100 insertions(+), 16 deletions(-)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 32c3295929b0..990d9d1e85d0 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>  	}
>  }
>  
> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
> +{
> +	switch (n) {
> +	case 0:
> +		write_gicreg(val, ICH_AP0R0_EL2);
> +		break;
> +	case 1:
> +		write_gicreg(val, ICH_AP0R1_EL2);
> +		break;
> +	case 2:
> +		write_gicreg(val, ICH_AP0R2_EL2);
> +		break;
> +	case 3:
> +		write_gicreg(val, ICH_AP0R3_EL2);
> +		break;
> +	}

Is there any way we can get a build or runtime failure for an
out-of-bounds n value?

> +}

Given this is used with a constant n, you could make this:

#define __vgic_v3_write_ap0rn(v, n) \
	write_gicreg(v, ICH_AP0R##n##_EL2)

... which should also give you a warning for an out-of-bounds n.

Similar could apply for the other helpers here.

That would require some function -> macro conversion in later patches
though, so I can understand if you're not keen on that.

Thanks,
Mark.

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-03 15:32     ` Mark Rutland
  0 siblings, 0 replies; 162+ messages in thread
From: Mark Rutland @ 2017-05-03 15:32 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
> As we're about to access the Active Priority registers a lot more,
> let's define accessors that take the register number as a parameter.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>  1 file changed, 100 insertions(+), 16 deletions(-)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 32c3295929b0..990d9d1e85d0 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>  	}
>  }
>  
> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
> +{
> +	switch (n) {
> +	case 0:
> +		write_gicreg(val, ICH_AP0R0_EL2);
> +		break;
> +	case 1:
> +		write_gicreg(val, ICH_AP0R1_EL2);
> +		break;
> +	case 2:
> +		write_gicreg(val, ICH_AP0R2_EL2);
> +		break;
> +	case 3:
> +		write_gicreg(val, ICH_AP0R3_EL2);
> +		break;
> +	}

Is there any way we can get a build or runtime failure for an
out-of-bounds n value?

> +}

Given this is used with a constant n, you could make this:

#define __vgic_v3_write_ap0rn(v, n) \
	write_gicreg(v, ICH_AP0R##n##_EL2)

... which should also give you a warning for an out-of-bounds n.

Similar could apply for the other helpers here.

That would require some function -> macro conversion in later patches
though, so I can understand if you're not keen on that.

Thanks,
Mark.

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

* Re: [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-03 15:35     ` Mark Rutland
  -1 siblings, 0 replies; 162+ messages in thread
From: Mark Rutland @ 2017-05-03 15:35 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

On Wed, May 03, 2017 at 11:45:43AM +0100, Marc Zyngier wrote:
> It is often useful to compare an ESR syndrome reporting the trapping
> of a system register with a value matching that system register.
> 
> Since encoding both the sysreg and the ESR version seem to be a bit
> overkill, let's add a set of macros that convert an ESR value into
> the corresponding sysreg encoding.
> 
> We handle both AArch32 and AArch64, taking advantage of identical
> encodings between system registers and CP15 accessors.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Nice!

Acked-by: Mark Rutland <mark.rutland@arm.com>

Mark.

> ---
>  arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index ad42e79a5d4d..db8f13137443 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -19,6 +19,7 @@
>  #define __ASM_ESR_H
>  
>  #include <asm/memory.h>
> +#include <asm/sysreg.h>
>  
>  #define ESR_ELx_EC_UNKNOWN	(0x00)
>  #define ESR_ELx_EC_WFx		(0x01)
> @@ -177,6 +178,30 @@
>  
>  #define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
>  					 ESR_ELx_SYS64_ISS_DIR_READ)
> +
> +#define esr_sys64_to_sysreg(e)					\
> +	sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP0_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
> +#define esr_cp15_to_sysreg(e)					\
> +	sys_reg(3,						\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
>  #ifndef __ASSEMBLY__
>  #include <asm/types.h>
>  
> -- 
> 2.11.0
> 

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

* [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
@ 2017-05-03 15:35     ` Mark Rutland
  0 siblings, 0 replies; 162+ messages in thread
From: Mark Rutland @ 2017-05-03 15:35 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 03, 2017 at 11:45:43AM +0100, Marc Zyngier wrote:
> It is often useful to compare an ESR syndrome reporting the trapping
> of a system register with a value matching that system register.
> 
> Since encoding both the sysreg and the ESR version seem to be a bit
> overkill, let's add a set of macros that convert an ESR value into
> the corresponding sysreg encoding.
> 
> We handle both AArch32 and AArch64, taking advantage of identical
> encodings between system registers and CP15 accessors.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Nice!

Acked-by: Mark Rutland <mark.rutland@arm.com>

Mark.

> ---
>  arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index ad42e79a5d4d..db8f13137443 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -19,6 +19,7 @@
>  #define __ASM_ESR_H
>  
>  #include <asm/memory.h>
> +#include <asm/sysreg.h>
>  
>  #define ESR_ELx_EC_UNKNOWN	(0x00)
>  #define ESR_ELx_EC_WFx		(0x01)
> @@ -177,6 +178,30 @@
>  
>  #define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
>  					 ESR_ELx_SYS64_ISS_DIR_READ)
> +
> +#define esr_sys64_to_sysreg(e)					\
> +	sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP0_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
> +#define esr_cp15_to_sysreg(e)					\
> +	sys_reg(3,						\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
>  #ifndef __ASSEMBLY__
>  #include <asm/types.h>
>  
> -- 
> 2.11.0
> 

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-03 15:32     ` Mark Rutland
@ 2017-05-03 15:58       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 15:58 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Christoffer Dall, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

On 03/05/17 16:32, Mark Rutland wrote:
> On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
>> As we're about to access the Active Priority registers a lot more,
>> let's define accessors that take the register number as a parameter.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 100 insertions(+), 16 deletions(-)
>>
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 32c3295929b0..990d9d1e85d0 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>  	}
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP0R3_EL2);
>> +		break;
>> +	}
> 
> Is there any way we can get a build or runtime failure for an
> out-of-bounds n value?

I'd rather avoid runtime failure on this path, because that's pretty
terminal. Build-time is a possibility, to some extent.

> 
>> +}
> 
> Given this is used with a constant n, you could make this:
> 
> #define __vgic_v3_write_ap0rn(v, n) \
> 	write_gicreg(v, ICH_AP0R##n##_EL2)
> 
> ... which should also give you a warning for an out-of-bounds n.
> 
> Similar could apply for the other helpers here.
> 
> That would require some function -> macro conversion in later patches
> though, so I can understand if you're not keen on that.

I don't mind reworking this if that makes it safer. But the real problem
is that the register number and the group are not necessarily constants
(see how this is used in __vgic_v3_get_highest_active_priority).

I'll have a look at how I can make that look a bit better.

Thanks,

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

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-03 15:58       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-03 15:58 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/05/17 16:32, Mark Rutland wrote:
> On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
>> As we're about to access the Active Priority registers a lot more,
>> let's define accessors that take the register number as a parameter.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 100 insertions(+), 16 deletions(-)
>>
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 32c3295929b0..990d9d1e85d0 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>  	}
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP0R3_EL2);
>> +		break;
>> +	}
> 
> Is there any way we can get a build or runtime failure for an
> out-of-bounds n value?

I'd rather avoid runtime failure on this path, because that's pretty
terminal. Build-time is a possibility, to some extent.

> 
>> +}
> 
> Given this is used with a constant n, you could make this:
> 
> #define __vgic_v3_write_ap0rn(v, n) \
> 	write_gicreg(v, ICH_AP0R##n##_EL2)
> 
> ... which should also give you a warning for an out-of-bounds n.
> 
> Similar could apply for the other helpers here.
> 
> That would require some function -> macro conversion in later patches
> though, so I can understand if you're not keen on that.

I don't mind reworking this if that makes it safer. But the real problem
is that the register number and the group are not necessarily constants
(see how this is used in __vgic_v3_get_highest_active_priority).

I'll have a look at how I can make that look a bit better.

Thanks,

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

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

* Re: [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2
  2017-05-03 10:45 ` Marc Zyngier
@ 2017-05-09  0:05   ` David Daney
  -1 siblings, 0 replies; 162+ messages in thread
From: David Daney @ 2017-05-09  0:05 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: David Daney, Catalin Marinas, Mark Rutland, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

On 05/03/2017 03:45 AM, Marc Zyngier wrote:
> [Apologies for posting this at the beginning of a merge window, but as
>   this is a rather hot topic, I'd rather put it out as soon as possible]
> 
> Some systems have less than perfect GICv3 implementations, leading to
> all kind of ugly issues (guest hanging, host dying). In order to allow
> some level of diagnostic, and in some cases implement workarounds,
> this series enables the trapping of both Group-0, Group-1 and Common
> sysregs. Mediating the access at EL2 allows some form of sanity
> checking that the HW is sometimes sorely lacking.
> 
> Instead of fully emulating a GICv3 CPU interface, we still use the
> existing HW (list registers, AP registers, VMCR...), which allows the
> code to be independent from the rest of the KVM code, and to cope with
> partial trapping.
> 
> Of course, trapping has a cost, which is why this must be either
> enabled on the command line, or selected by another cpu capability
> (see Cavium erratum 30115). A quick test on an A57-based platform
> shows a 25% hit when repeatedly banging on the trapped registers,
> while normal workloads do not seem to suffer noticeably from such
> trapping (hackbench variance is in the usual noise, despite being very
> IPI happy).
> 
> This has been tested on a dual socket Thundex-X and a Freescale LS-2085a.
> 
> The first 6 patches are fixes, and only here for reference as they
> have already been posted separately. The rest of the patches implement
> Group-1, Group-0 and Common sysreg handlers, with the corresponding
> command line options. I've also taken the liberty to rebase David
> Daney's initial Cavium erratum 30115 workaround on top of this series,
> and included it here as a typical use case.
> 


Thanks Marc for working on this.

I tested this series based on your git branch:
https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/gicv3-cpuif-mediated-access

This does indeed fix the problems we were seeing, so feel free to add:

Tested-by: David Daney <david.daney@cavium.com>

to the entire series.

I would note that with these patches we see an occasional:

[ 3868.311491] Unexpected interrupt 4 on vcpu ffff801f57a6a020
[ 4262.063419] Unexpected interrupt 4 on vcpu ffff801f5b3dc040
[ 4262.063422] Unexpected interrupt 4 on vcpu ffff801f50972020

This is better than locking up the system, but I wonder if it indicates 
that improvement to the code is still possible.

David Daney



> David Daney (2):
>    arm64: Add MIDR values for Cavium cn83XX SoCs
>    arm64: Add workaround for Cavium Thunder erratum 30115
> 
> Marc Zyngier (29):
>    arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses
>    arm64: KVM: Do not use stack-protector to compile EL2 code
>    arm: KVM: Do not use stack-protector to compile HYP code
>    KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW
>      interrupt
>    KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW
>      interrupt
>    KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of
>      ICH_APxRn_EL2 registers
>    KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
>    arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
>    KVM: arm64: Make kvm_condition_valid32() accessible from EL2
>    KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at
>      EL2
>    KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
>    KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
>    KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
>    KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
>    KVM: arm64: vgic-v3: Add misc Group-0 handlers
>    KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
>    KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
>    KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
>    KVM: arm64: Enable GICv3 common sysreg trapping via command-line
>    KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
> 
>   Documentation/arm64/silicon-errata.txt |   1 +
>   arch/arm/kvm/hyp/Makefile              |   2 +
>   arch/arm64/Kconfig                     |  11 +
>   arch/arm64/include/asm/cpucaps.h       |   3 +-
>   arch/arm64/include/asm/cputype.h       |   2 +
>   arch/arm64/include/asm/esr.h           |  25 ++
>   arch/arm64/include/asm/kvm_emulate.h   |   6 +
>   arch/arm64/include/asm/kvm_hyp.h       |   1 +
>   arch/arm64/include/asm/sysreg.h        |   9 +
>   arch/arm64/kernel/cpu_errata.c         |  21 +
>   arch/arm64/kvm/hyp/Makefile            |   2 +
>   arch/arm64/kvm/hyp/switch.c            |  14 +
>   arch/arm64/kvm/sys_regs.c              |   8 +-
>   include/kvm/arm_vgic.h                 |   1 +
>   include/linux/irqchip/arm-gic-v3.h     |   6 +
>   virt/kvm/arm/aarch32.c                 |   2 +-
>   virt/kvm/arm/hyp/vgic-v3-sr.c          | 792 +++++++++++++++++++++++++++++++--
>   virt/kvm/arm/vgic/vgic-v2.c            |   7 +
>   virt/kvm/arm/vgic/vgic-v3.c            |  52 +++
>   19 files changed, 934 insertions(+), 31 deletions(-)
> 

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

* [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2
@ 2017-05-09  0:05   ` David Daney
  0 siblings, 0 replies; 162+ messages in thread
From: David Daney @ 2017-05-09  0:05 UTC (permalink / raw)
  To: linux-arm-kernel

On 05/03/2017 03:45 AM, Marc Zyngier wrote:
> [Apologies for posting this at the beginning of a merge window, but as
>   this is a rather hot topic, I'd rather put it out as soon as possible]
> 
> Some systems have less than perfect GICv3 implementations, leading to
> all kind of ugly issues (guest hanging, host dying). In order to allow
> some level of diagnostic, and in some cases implement workarounds,
> this series enables the trapping of both Group-0, Group-1 and Common
> sysregs. Mediating the access at EL2 allows some form of sanity
> checking that the HW is sometimes sorely lacking.
> 
> Instead of fully emulating a GICv3 CPU interface, we still use the
> existing HW (list registers, AP registers, VMCR...), which allows the
> code to be independent from the rest of the KVM code, and to cope with
> partial trapping.
> 
> Of course, trapping has a cost, which is why this must be either
> enabled on the command line, or selected by another cpu capability
> (see Cavium erratum 30115). A quick test on an A57-based platform
> shows a 25% hit when repeatedly banging on the trapped registers,
> while normal workloads do not seem to suffer noticeably from such
> trapping (hackbench variance is in the usual noise, despite being very
> IPI happy).
> 
> This has been tested on a dual socket Thundex-X and a Freescale LS-2085a.
> 
> The first 6 patches are fixes, and only here for reference as they
> have already been posted separately. The rest of the patches implement
> Group-1, Group-0 and Common sysreg handlers, with the corresponding
> command line options. I've also taken the liberty to rebase David
> Daney's initial Cavium erratum 30115 workaround on top of this series,
> and included it here as a typical use case.
> 


Thanks Marc for working on this.

I tested this series based on your git branch:
https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/gicv3-cpuif-mediated-access

This does indeed fix the problems we were seeing, so feel free to add:

Tested-by: David Daney <david.daney@cavium.com>

to the entire series.

I would note that with these patches we see an occasional:

[ 3868.311491] Unexpected interrupt 4 on vcpu ffff801f57a6a020
[ 4262.063419] Unexpected interrupt 4 on vcpu ffff801f5b3dc040
[ 4262.063422] Unexpected interrupt 4 on vcpu ffff801f50972020

This is better than locking up the system, but I wonder if it indicates 
that improvement to the code is still possible.

David Daney



> David Daney (2):
>    arm64: Add MIDR values for Cavium cn83XX SoCs
>    arm64: Add workaround for Cavium Thunder erratum 30115
> 
> Marc Zyngier (29):
>    arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses
>    arm64: KVM: Do not use stack-protector to compile EL2 code
>    arm: KVM: Do not use stack-protector to compile HYP code
>    KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW
>      interrupt
>    KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW
>      interrupt
>    KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of
>      ICH_APxRn_EL2 registers
>    KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
>    arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
>    KVM: arm64: Make kvm_condition_valid32() accessible from EL2
>    KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at
>      EL2
>    KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
>    KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
>    KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line
>    KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
>    KVM: arm64: vgic-v3: Add misc Group-0 handlers
>    KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
>    KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line
>    KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
>    KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
>    KVM: arm64: Enable GICv3 common sysreg trapping via command-line
>    KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
> 
>   Documentation/arm64/silicon-errata.txt |   1 +
>   arch/arm/kvm/hyp/Makefile              |   2 +
>   arch/arm64/Kconfig                     |  11 +
>   arch/arm64/include/asm/cpucaps.h       |   3 +-
>   arch/arm64/include/asm/cputype.h       |   2 +
>   arch/arm64/include/asm/esr.h           |  25 ++
>   arch/arm64/include/asm/kvm_emulate.h   |   6 +
>   arch/arm64/include/asm/kvm_hyp.h       |   1 +
>   arch/arm64/include/asm/sysreg.h        |   9 +
>   arch/arm64/kernel/cpu_errata.c         |  21 +
>   arch/arm64/kvm/hyp/Makefile            |   2 +
>   arch/arm64/kvm/hyp/switch.c            |  14 +
>   arch/arm64/kvm/sys_regs.c              |   8 +-
>   include/kvm/arm_vgic.h                 |   1 +
>   include/linux/irqchip/arm-gic-v3.h     |   6 +
>   virt/kvm/arm/aarch32.c                 |   2 +-
>   virt/kvm/arm/hyp/vgic-v3-sr.c          | 792 +++++++++++++++++++++++++++++++--
>   virt/kvm/arm/vgic/vgic-v2.c            |   7 +
>   virt/kvm/arm/vgic/vgic-v3.c            |  52 +++
>   19 files changed, 934 insertions(+), 31 deletions(-)
> 

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

* Re: [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2
  2017-05-09  0:05   ` David Daney
@ 2017-05-09 17:39     ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-09 17:39 UTC (permalink / raw)
  To: David Daney, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

On 09/05/17 01:05, David Daney wrote:
> On 05/03/2017 03:45 AM, Marc Zyngier wrote:
>> [Apologies for posting this at the beginning of a merge window, but as
>>   this is a rather hot topic, I'd rather put it out as soon as possible]
>>
>> Some systems have less than perfect GICv3 implementations, leading to
>> all kind of ugly issues (guest hanging, host dying). In order to allow
>> some level of diagnostic, and in some cases implement workarounds,
>> this series enables the trapping of both Group-0, Group-1 and Common
>> sysregs. Mediating the access at EL2 allows some form of sanity
>> checking that the HW is sometimes sorely lacking.
>>
>> Instead of fully emulating a GICv3 CPU interface, we still use the
>> existing HW (list registers, AP registers, VMCR...), which allows the
>> code to be independent from the rest of the KVM code, and to cope with
>> partial trapping.
>>
>> Of course, trapping has a cost, which is why this must be either
>> enabled on the command line, or selected by another cpu capability
>> (see Cavium erratum 30115). A quick test on an A57-based platform
>> shows a 25% hit when repeatedly banging on the trapped registers,
>> while normal workloads do not seem to suffer noticeably from such
>> trapping (hackbench variance is in the usual noise, despite being very
>> IPI happy).
>>
>> This has been tested on a dual socket Thundex-X and a Freescale LS-2085a.
>>
>> The first 6 patches are fixes, and only here for reference as they
>> have already been posted separately. The rest of the patches implement
>> Group-1, Group-0 and Common sysreg handlers, with the corresponding
>> command line options. I've also taken the liberty to rebase David
>> Daney's initial Cavium erratum 30115 workaround on top of this series,
>> and included it here as a typical use case.
>>
> 
> 
> Thanks Marc for working on this.
> 
> I tested this series based on your git branch:
> https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/gicv3-cpuif-mediated-access
> 
> This does indeed fix the problems we were seeing, so feel free to add:
> 
> Tested-by: David Daney <david.daney@cavium.com>
> 
> to the entire series.

Thanks for having given it a go.

> 
> I would note that with these patches we see an occasional:
> 
> [ 3868.311491] Unexpected interrupt 4 on vcpu ffff801f57a6a020
> [ 4262.063419] Unexpected interrupt 4 on vcpu ffff801f5b3dc040
> [ 4262.063422] Unexpected interrupt 4 on vcpu ffff801f50972020
> 
> This is better than locking up the system, but I wonder if it indicates 
> that improvement to the code is still possible.

This warning occasionally shows up on the same platform even without
these patches (it is just harder to trigger). This is an artefact of the
way KVM treats the virtual timer, disabling it on exit and expecting it
to immediately retired from the CPU interface. This works just fine on
all systems, except for this platform where it seems to take a bit more
time.

Trapping things at EL2 introduces just enough additional latency that we
end-up exiting with a pending interrupt more often than without the
trapping, trigger this warning.

The good news is twofold: this is completely harmless (we just get an
extra interrupt on the host), and Christoffer is working on patches that
will change the way we handle this so that we actually make use of that
interrupt.

Thanks,

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

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

* [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2
@ 2017-05-09 17:39     ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-09 17:39 UTC (permalink / raw)
  To: linux-arm-kernel

On 09/05/17 01:05, David Daney wrote:
> On 05/03/2017 03:45 AM, Marc Zyngier wrote:
>> [Apologies for posting this at the beginning of a merge window, but as
>>   this is a rather hot topic, I'd rather put it out as soon as possible]
>>
>> Some systems have less than perfect GICv3 implementations, leading to
>> all kind of ugly issues (guest hanging, host dying). In order to allow
>> some level of diagnostic, and in some cases implement workarounds,
>> this series enables the trapping of both Group-0, Group-1 and Common
>> sysregs. Mediating the access at EL2 allows some form of sanity
>> checking that the HW is sometimes sorely lacking.
>>
>> Instead of fully emulating a GICv3 CPU interface, we still use the
>> existing HW (list registers, AP registers, VMCR...), which allows the
>> code to be independent from the rest of the KVM code, and to cope with
>> partial trapping.
>>
>> Of course, trapping has a cost, which is why this must be either
>> enabled on the command line, or selected by another cpu capability
>> (see Cavium erratum 30115). A quick test on an A57-based platform
>> shows a 25% hit when repeatedly banging on the trapped registers,
>> while normal workloads do not seem to suffer noticeably from such
>> trapping (hackbench variance is in the usual noise, despite being very
>> IPI happy).
>>
>> This has been tested on a dual socket Thundex-X and a Freescale LS-2085a.
>>
>> The first 6 patches are fixes, and only here for reference as they
>> have already been posted separately. The rest of the patches implement
>> Group-1, Group-0 and Common sysreg handlers, with the corresponding
>> command line options. I've also taken the liberty to rebase David
>> Daney's initial Cavium erratum 30115 workaround on top of this series,
>> and included it here as a typical use case.
>>
> 
> 
> Thanks Marc for working on this.
> 
> I tested this series based on your git branch:
> https://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git/log/?h=kvm-arm64/gicv3-cpuif-mediated-access
> 
> This does indeed fix the problems we were seeing, so feel free to add:
> 
> Tested-by: David Daney <david.daney@cavium.com>
> 
> to the entire series.

Thanks for having given it a go.

> 
> I would note that with these patches we see an occasional:
> 
> [ 3868.311491] Unexpected interrupt 4 on vcpu ffff801f57a6a020
> [ 4262.063419] Unexpected interrupt 4 on vcpu ffff801f5b3dc040
> [ 4262.063422] Unexpected interrupt 4 on vcpu ffff801f50972020
> 
> This is better than locking up the system, but I wonder if it indicates 
> that improvement to the code is still possible.

This warning occasionally shows up on the same platform even without
these patches (it is just harder to trigger). This is an artefact of the
way KVM treats the virtual timer, disabling it on exit and expecting it
to immediately retired from the CPU interface. This works just fine on
all systems, except for this platform where it seems to take a bit more
time.

Trapping things at EL2 introduces just enough additional latency that we
end-up exiting with a pending interrupt more often than without the
trapping, trigger this warning.

The good news is twofold: this is completely harmless (we just get an
extra interrupt on the host), and Christoffer is working on patches that
will change the way we handle this so that we actually make use of that
interrupt.

Thanks,

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

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

* Re: [PATCH 10/31] KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at EL2
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-17  9:54     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi Marc,
On 03/05/2017 12:45, Marc Zyngier wrote:
> In order to start handling guest access to GICv3 system registers,
> let's add a hook that will get called when we trap a system register
> access. This is gated by a new static key (vgic_v3_cpuif_trap).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

> ---
>  arch/arm64/include/asm/kvm_hyp.h |  1 +
>  arch/arm64/kvm/hyp/switch.c      | 14 ++++++++++++++
>  include/kvm/arm_vgic.h           |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c    | 27 +++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c      |  2 ++
>  5 files changed, 45 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
> index b18e852d27e8..4572a9b560fa 100644
> --- a/arch/arm64/include/asm/kvm_hyp.h
> +++ b/arch/arm64/include/asm/kvm_hyp.h
> @@ -127,6 +127,7 @@ int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
>  
>  void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
>  void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
> +int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
>  
>  void __timer_save_state(struct kvm_vcpu *vcpu);
>  void __timer_restore_state(struct kvm_vcpu *vcpu);
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index aede1658aeda..dfd8ca16601b 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -350,6 +350,20 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
>  		}
>  	}
>  
> +	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
> +	    exit_code == ARM_EXCEPTION_TRAP &&
> +	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
> +	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
> +		int ret = __vgic_v3_perform_cpuif_access(vcpu);
> +
> +		if (ret == 1) {
> +			__skip_instr(vcpu);
> +			goto again;
> +		}
> +
> +		/* 0 falls through to be handled out of EL2 */
> +	}
> +
>  	fp_enabled = __fpsimd_enabled();
>  
>  	__sysreg_save_guest_state(guest_ctxt);
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 581a59ea7e34..ddfa11b713bf 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -280,6 +280,7 @@ struct vgic_cpu {
>  };
>  
>  extern struct static_key_false vgic_v2_cpuif_trap;
> +extern struct static_key_false vgic_v3_cpuif_trap;
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
>  void kvm_vgic_early_init(struct kvm *kvm);
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 990d9d1e85d0..435787a93c6c 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -19,6 +19,7 @@
>  #include <linux/irqchip/arm-gic-v3.h>
>  #include <linux/kvm_host.h>
>  
> +#include <asm/kvm_emulate.h>
>  #include <asm/kvm_hyp.h>
>  
>  #define vtr_to_max_lr_idx(v)		((v) & 0xf)
> @@ -371,3 +372,29 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>  {
>  	write_gicreg(vmcr, ICH_VMCR_EL2);
>  }
> +
> +#ifdef CONFIG_ARM64
> +
> +int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
> +{
> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
> +	u32 sysreg;
> +
> +	if (vcpu_mode_is_32bit(vcpu)) {
> +		if (!kvm_condition_valid(vcpu))
> +			return 1;
> +
> +		sysreg = esr_cp15_to_sysreg(esr);
> +	} else {
> +		sysreg = esr_sys64_to_sysreg(esr);
> +	}
> +
> +	switch (sysreg) {
> +	default:
> +		return 0;
> +	}
> +
> +	return 1;
> +}
> +
> +#endif
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 393779ebe87c..063526443781 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -318,6 +318,8 @@ int vgic_v3_map_resources(struct kvm *kvm)
>  	return ret;
>  }
>  
> +DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> 

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

* [PATCH 10/31] KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at EL2
@ 2017-05-17  9:54     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,
On 03/05/2017 12:45, Marc Zyngier wrote:
> In order to start handling guest access to GICv3 system registers,
> let's add a hook that will get called when we trap a system register
> access. This is gated by a new static key (vgic_v3_cpuif_trap).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

> ---
>  arch/arm64/include/asm/kvm_hyp.h |  1 +
>  arch/arm64/kvm/hyp/switch.c      | 14 ++++++++++++++
>  include/kvm/arm_vgic.h           |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c    | 27 +++++++++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c      |  2 ++
>  5 files changed, 45 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/kvm_hyp.h b/arch/arm64/include/asm/kvm_hyp.h
> index b18e852d27e8..4572a9b560fa 100644
> --- a/arch/arm64/include/asm/kvm_hyp.h
> +++ b/arch/arm64/include/asm/kvm_hyp.h
> @@ -127,6 +127,7 @@ int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
>  
>  void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
>  void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
> +int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
>  
>  void __timer_save_state(struct kvm_vcpu *vcpu);
>  void __timer_restore_state(struct kvm_vcpu *vcpu);
> diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
> index aede1658aeda..dfd8ca16601b 100644
> --- a/arch/arm64/kvm/hyp/switch.c
> +++ b/arch/arm64/kvm/hyp/switch.c
> @@ -350,6 +350,20 @@ int __hyp_text __kvm_vcpu_run(struct kvm_vcpu *vcpu)
>  		}
>  	}
>  
> +	if (static_branch_unlikely(&vgic_v3_cpuif_trap) &&
> +	    exit_code == ARM_EXCEPTION_TRAP &&
> +	    (kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_SYS64 ||
> +	     kvm_vcpu_trap_get_class(vcpu) == ESR_ELx_EC_CP15_32)) {
> +		int ret = __vgic_v3_perform_cpuif_access(vcpu);
> +
> +		if (ret == 1) {
> +			__skip_instr(vcpu);
> +			goto again;
> +		}
> +
> +		/* 0 falls through to be handled out of EL2 */
> +	}
> +
>  	fp_enabled = __fpsimd_enabled();
>  
>  	__sysreg_save_guest_state(guest_ctxt);
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 581a59ea7e34..ddfa11b713bf 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -280,6 +280,7 @@ struct vgic_cpu {
>  };
>  
>  extern struct static_key_false vgic_v2_cpuif_trap;
> +extern struct static_key_false vgic_v3_cpuif_trap;
>  
>  int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
>  void kvm_vgic_early_init(struct kvm *kvm);
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 990d9d1e85d0..435787a93c6c 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -19,6 +19,7 @@
>  #include <linux/irqchip/arm-gic-v3.h>
>  #include <linux/kvm_host.h>
>  
> +#include <asm/kvm_emulate.h>
>  #include <asm/kvm_hyp.h>
>  
>  #define vtr_to_max_lr_idx(v)		((v) & 0xf)
> @@ -371,3 +372,29 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>  {
>  	write_gicreg(vmcr, ICH_VMCR_EL2);
>  }
> +
> +#ifdef CONFIG_ARM64
> +
> +int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
> +{
> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
> +	u32 sysreg;
> +
> +	if (vcpu_mode_is_32bit(vcpu)) {
> +		if (!kvm_condition_valid(vcpu))
> +			return 1;
> +
> +		sysreg = esr_cp15_to_sysreg(esr);
> +	} else {
> +		sysreg = esr_sys64_to_sysreg(esr);
> +	}
> +
> +	switch (sysreg) {
> +	default:
> +		return 0;
> +	}
> +
> +	return 1;
> +}
> +
> +#endif
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 393779ebe87c..063526443781 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -318,6 +318,8 @@ int vgic_v3_map_resources(struct kvm *kvm)
>  	return ret;
>  }
>  
> +DEFINE_STATIC_KEY_FALSE(vgic_v3_cpuif_trap);
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> 

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

* Re: [PATCH 09/31] KVM: arm64: Make kvm_condition_valid32() accessible from EL2
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-17  9:54     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,
On 03/05/2017 12:45, Marc Zyngier wrote:
> As we're about to trap CP15 accesses and handle them at EL2, we
> need to evaluate whether or not the condition flags are valid,
> as an implementation is allowed to trap despite the condition
> not being met.
> 
> Tagging the function as __hyp_text allows this.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

> ---
>  virt/kvm/arm/aarch32.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/aarch32.c b/virt/kvm/arm/aarch32.c
> index 528af4b2d09e..79c7c357804b 100644
> --- a/virt/kvm/arm/aarch32.c
> +++ b/virt/kvm/arm/aarch32.c
> @@ -60,7 +60,7 @@ static const unsigned short cc_map[16] = {
>  /*
>   * Check if a trapped instruction should have been executed or not.
>   */
> -bool kvm_condition_valid32(const struct kvm_vcpu *vcpu)
> +bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu)
>  {
>  	unsigned long cpsr;
>  	u32 cpsr_cond;
> 

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

* [PATCH 09/31] KVM: arm64: Make kvm_condition_valid32() accessible from EL2
@ 2017-05-17  9:54     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,
On 03/05/2017 12:45, Marc Zyngier wrote:
> As we're about to trap CP15 accesses and handle them at EL2, we
> need to evaluate whether or not the condition flags are valid,
> as an implementation is allowed to trap despite the condition
> not being met.
> 
> Tagging the function as __hyp_text allows this.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

> ---
>  virt/kvm/arm/aarch32.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/aarch32.c b/virt/kvm/arm/aarch32.c
> index 528af4b2d09e..79c7c357804b 100644
> --- a/virt/kvm/arm/aarch32.c
> +++ b/virt/kvm/arm/aarch32.c
> @@ -60,7 +60,7 @@ static const unsigned short cc_map[16] = {
>  /*
>   * Check if a trapped instruction should have been executed or not.
>   */
> -bool kvm_condition_valid32(const struct kvm_vcpu *vcpu)
> +bool __hyp_text kvm_condition_valid32(const struct kvm_vcpu *vcpu)
>  {
>  	unsigned long cpsr;
>  	u32 cpsr_cond;
> 

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-17  9:54     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> As we're about to access the Active Priority registers a lot more,
> let's define accessors that take the register number as a parameter.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>  1 file changed, 100 insertions(+), 16 deletions(-)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 32c3295929b0..990d9d1e85d0 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>  	}
>  }
>  
> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
> +{
> +	switch (n) {
> +	case 0:
> +		write_gicreg(val, ICH_AP0R0_EL2);
> +		break;
> +	case 1:
> +		write_gicreg(val, ICH_AP0R1_EL2);
> +		break;
> +	case 2:
> +		write_gicreg(val, ICH_AP0R2_EL2);
> +		break;
> +	case 3:
> +		write_gicreg(val, ICH_AP0R3_EL2);
> +		break;
> +	}
> +}
> +
> +static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
> +{
> +	switch (n) {
> +	case 0:
> +		write_gicreg(val, ICH_AP1R0_EL2);
> +		break;
> +	case 1:
> +		write_gicreg(val, ICH_AP1R1_EL2);
> +		break;
> +	case 2:
> +		write_gicreg(val, ICH_AP1R2_EL2);
> +		break;
> +	case 3:
> +		write_gicreg(val, ICH_AP1R3_EL2);
> +		break;
> +	}
> +}
> +
> +static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
> +{
> +	u32 val;
> +
> +	switch (n) {
> +	case 0:
> +		val = read_gicreg(ICH_AP0R0_EL2);
> +		break;
> +	case 1:
> +		val = read_gicreg(ICH_AP0R1_EL2);
> +		break;
> +	case 2:
> +		val = read_gicreg(ICH_AP0R2_EL2);
> +		break;
> +	case 3:
> +		val = read_gicreg(ICH_AP0R3_EL2);
> +		break;
> +	default:
> +		unreachable();
I am not familiar with that macro. For my curiosity why is it used here
and not in write functions.

Besides Mark's comment,

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> +	}
> +
> +	return val;
> +}
> +
> +static u32 __hyp_text __vgic_v3_read_ap1rn(int n)
> +{
> +	u32 val;
> +
> +	switch (n) {
> +	case 0:
> +		val = read_gicreg(ICH_AP1R0_EL2);
> +		break;
> +	case 1:
> +		val = read_gicreg(ICH_AP1R1_EL2);
> +		break;
> +	case 2:
> +		val = read_gicreg(ICH_AP1R2_EL2);
> +		break;
> +	case 3:
> +		val = read_gicreg(ICH_AP1R3_EL2);
> +		break;
> +	default:
> +		unreachable();
> +	}
> +
> +	return val;
> +}
> +
>  void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
> @@ -154,22 +238,22 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
> -			cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
> +			cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
> +			cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
>  		case 6:
> -			cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2);
> +			cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
>  		default:
> -			cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
> +			cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
>  		}
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
> -			cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
> +			cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
> +			cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
>  		case 6:
> -			cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2);
> +			cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
>  		default:
> -			cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2);
> +			cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
>  		}
>  	} else {
>  		cpu_if->vgic_elrsr = 0xffff;
> @@ -224,22 +308,22 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
> -			write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
>  		case 6:
> -			write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
>  		default:
> -			write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
>  		}
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
> -			write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
>  		case 6:
> -			write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
>  		default:
> -			write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
>  		}
>  
>  		for (i = 0; i < used_lrs; i++)
> 

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-17  9:54     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> As we're about to access the Active Priority registers a lot more,
> let's define accessors that take the register number as a parameter.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>  1 file changed, 100 insertions(+), 16 deletions(-)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 32c3295929b0..990d9d1e85d0 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>  	}
>  }
>  
> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
> +{
> +	switch (n) {
> +	case 0:
> +		write_gicreg(val, ICH_AP0R0_EL2);
> +		break;
> +	case 1:
> +		write_gicreg(val, ICH_AP0R1_EL2);
> +		break;
> +	case 2:
> +		write_gicreg(val, ICH_AP0R2_EL2);
> +		break;
> +	case 3:
> +		write_gicreg(val, ICH_AP0R3_EL2);
> +		break;
> +	}
> +}
> +
> +static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
> +{
> +	switch (n) {
> +	case 0:
> +		write_gicreg(val, ICH_AP1R0_EL2);
> +		break;
> +	case 1:
> +		write_gicreg(val, ICH_AP1R1_EL2);
> +		break;
> +	case 2:
> +		write_gicreg(val, ICH_AP1R2_EL2);
> +		break;
> +	case 3:
> +		write_gicreg(val, ICH_AP1R3_EL2);
> +		break;
> +	}
> +}
> +
> +static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
> +{
> +	u32 val;
> +
> +	switch (n) {
> +	case 0:
> +		val = read_gicreg(ICH_AP0R0_EL2);
> +		break;
> +	case 1:
> +		val = read_gicreg(ICH_AP0R1_EL2);
> +		break;
> +	case 2:
> +		val = read_gicreg(ICH_AP0R2_EL2);
> +		break;
> +	case 3:
> +		val = read_gicreg(ICH_AP0R3_EL2);
> +		break;
> +	default:
> +		unreachable();
I am not familiar with that macro. For my curiosity why is it used here
and not in write functions.

Besides Mark's comment,

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> +	}
> +
> +	return val;
> +}
> +
> +static u32 __hyp_text __vgic_v3_read_ap1rn(int n)
> +{
> +	u32 val;
> +
> +	switch (n) {
> +	case 0:
> +		val = read_gicreg(ICH_AP1R0_EL2);
> +		break;
> +	case 1:
> +		val = read_gicreg(ICH_AP1R1_EL2);
> +		break;
> +	case 2:
> +		val = read_gicreg(ICH_AP1R2_EL2);
> +		break;
> +	case 3:
> +		val = read_gicreg(ICH_AP1R3_EL2);
> +		break;
> +	default:
> +		unreachable();
> +	}
> +
> +	return val;
> +}
> +
>  void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_v3_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v3;
> @@ -154,22 +238,22 @@ void __hyp_text __vgic_v3_save_state(struct kvm_vcpu *vcpu)
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			cpu_if->vgic_ap0r[3] = read_gicreg(ICH_AP0R3_EL2);
> -			cpu_if->vgic_ap0r[2] = read_gicreg(ICH_AP0R2_EL2);
> +			cpu_if->vgic_ap0r[3] = __vgic_v3_read_ap0rn(3);
> +			cpu_if->vgic_ap0r[2] = __vgic_v3_read_ap0rn(2);
>  		case 6:
> -			cpu_if->vgic_ap0r[1] = read_gicreg(ICH_AP0R1_EL2);
> +			cpu_if->vgic_ap0r[1] = __vgic_v3_read_ap0rn(1);
>  		default:
> -			cpu_if->vgic_ap0r[0] = read_gicreg(ICH_AP0R0_EL2);
> +			cpu_if->vgic_ap0r[0] = __vgic_v3_read_ap0rn(0);
>  		}
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			cpu_if->vgic_ap1r[3] = read_gicreg(ICH_AP1R3_EL2);
> -			cpu_if->vgic_ap1r[2] = read_gicreg(ICH_AP1R2_EL2);
> +			cpu_if->vgic_ap1r[3] = __vgic_v3_read_ap1rn(3);
> +			cpu_if->vgic_ap1r[2] = __vgic_v3_read_ap1rn(2);
>  		case 6:
> -			cpu_if->vgic_ap1r[1] = read_gicreg(ICH_AP1R1_EL2);
> +			cpu_if->vgic_ap1r[1] = __vgic_v3_read_ap1rn(1);
>  		default:
> -			cpu_if->vgic_ap1r[0] = read_gicreg(ICH_AP1R0_EL2);
> +			cpu_if->vgic_ap1r[0] = __vgic_v3_read_ap1rn(0);
>  		}
>  	} else {
>  		cpu_if->vgic_elrsr = 0xffff;
> @@ -224,22 +308,22 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			write_gicreg(cpu_if->vgic_ap0r[3], ICH_AP0R3_EL2);
> -			write_gicreg(cpu_if->vgic_ap0r[2], ICH_AP0R2_EL2);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[3], 3);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[2], 2);
>  		case 6:
> -			write_gicreg(cpu_if->vgic_ap0r[1], ICH_AP0R1_EL2);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[1], 1);
>  		default:
> -			write_gicreg(cpu_if->vgic_ap0r[0], ICH_AP0R0_EL2);
> +			__vgic_v3_write_ap0rn(cpu_if->vgic_ap0r[0], 0);
>  		}
>  
>  		switch (nr_pre_bits) {
>  		case 7:
> -			write_gicreg(cpu_if->vgic_ap1r[3], ICH_AP1R3_EL2);
> -			write_gicreg(cpu_if->vgic_ap1r[2], ICH_AP1R2_EL2);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[3], 3);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[2], 2);
>  		case 6:
> -			write_gicreg(cpu_if->vgic_ap1r[1], ICH_AP1R1_EL2);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[1], 1);
>  		default:
> -			write_gicreg(cpu_if->vgic_ap1r[0], ICH_AP1R0_EL2);
> +			__vgic_v3_write_ap1rn(cpu_if->vgic_ap1r[0], 0);
>  		}
>  
>  		for (i = 0; i < used_lrs; i++)
> 

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

* Re: [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-17  9:54     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> It is often useful to compare an ESR syndrome reporting the trapping
> of a system register with a value matching that system register.
> 
> Since encoding both the sysreg and the ESR version seem to be a bit
> overkill, let's add a set of macros that convert an ESR value into
> the corresponding sysreg encoding.
> 
> We handle both AArch32 and AArch64, taking advantage of identical
> encodings between system registers and CP15 accessors.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index ad42e79a5d4d..db8f13137443 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -19,6 +19,7 @@
>  #define __ASM_ESR_H
>  
>  #include <asm/memory.h>
> +#include <asm/sysreg.h>
>  
>  #define ESR_ELx_EC_UNKNOWN	(0x00)
>  #define ESR_ELx_EC_WFx		(0x01)
> @@ -177,6 +178,30 @@
>  
>  #define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
>  					 ESR_ELx_SYS64_ISS_DIR_READ)
> +
> +#define esr_sys64_to_sysreg(e)					\
> +	sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP0_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
> +#define esr_cp15_to_sysreg(e)					\
> +	sys_reg(3,						\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
>  #ifndef __ASSEMBLY__
>  #include <asm/types.h>

Needs a rebase on top
9842119  arm64: Add CNTFRQ_EL0 trap handler

Otherwise
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

>  
> 

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

* [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
@ 2017-05-17  9:54     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17  9:54 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> It is often useful to compare an ESR syndrome reporting the trapping
> of a system register with a value matching that system register.
> 
> Since encoding both the sysreg and the ESR version seem to be a bit
> overkill, let's add a set of macros that convert an ESR value into
> the corresponding sysreg encoding.
> 
> We handle both AArch32 and AArch64, taking advantage of identical
> encodings between system registers and CP15 accessors.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm64/include/asm/esr.h | 25 +++++++++++++++++++++++++
>  1 file changed, 25 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/esr.h b/arch/arm64/include/asm/esr.h
> index ad42e79a5d4d..db8f13137443 100644
> --- a/arch/arm64/include/asm/esr.h
> +++ b/arch/arm64/include/asm/esr.h
> @@ -19,6 +19,7 @@
>  #define __ASM_ESR_H
>  
>  #include <asm/memory.h>
> +#include <asm/sysreg.h>
>  
>  #define ESR_ELx_EC_UNKNOWN	(0x00)
>  #define ESR_ELx_EC_WFx		(0x01)
> @@ -177,6 +178,30 @@
>  
>  #define ESR_ELx_SYS64_ISS_SYS_CNTVCT	(ESR_ELx_SYS64_ISS_SYS_VAL(3, 3, 2, 14, 0) | \
>  					 ESR_ELx_SYS64_ISS_DIR_READ)
> +
> +#define esr_sys64_to_sysreg(e)					\
> +	sys_reg((((e) & ESR_ELx_SYS64_ISS_OP0_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP0_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
> +#define esr_cp15_to_sysreg(e)					\
> +	sys_reg(3,						\
> +		(((e) & ESR_ELx_SYS64_ISS_OP1_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP1_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRN_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRN_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_CRM_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_CRM_SHIFT),			\
> +		(((e) & ESR_ELx_SYS64_ISS_OP2_MASK) >>		\
> +		 ESR_ELx_SYS64_ISS_OP2_SHIFT))
> +
>  #ifndef __ASSEMBLY__
>  #include <asm/types.h>

Needs a rebase on top
9842119  arm64: Add CNTFRQ_EL0 trap handler

Otherwise
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric

>  
> 

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

* Re: [PATCH 12/31] KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-17 15:39     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17 15:39 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_IGRPEN1_EL1
> register, which is located in the ICH_VMCR_EL2.VENG1 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index f0f038c490a5..473ef22508e6 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -395,6 +395,23 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>  	return bpr;
>  }
>  
> +static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
> +}
> +
> +static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (val & 1)
> +		vmcr |= ICH_VMCR_ENG1_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_ENG1_MASK;
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
> @@ -440,6 +457,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
>  
>  	switch (sysreg) {
> +	case SYS_ICC_GRPEN1_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_igrpen1;
> +		else
> +			fn = __vgic_v3_write_igrpen1;
> +		break;
>  	case SYS_ICC_BPR1_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_bpr1;
> 

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

* [PATCH 12/31] KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler
@ 2017-05-17 15:39     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17 15:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_IGRPEN1_EL1
> register, which is located in the ICH_VMCR_EL2.VENG1 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index f0f038c490a5..473ef22508e6 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -395,6 +395,23 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>  	return bpr;
>  }
>  
> +static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
> +}
> +
> +static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (val & 1)
> +		vmcr |= ICH_VMCR_ENG1_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_ENG1_MASK;
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
> @@ -440,6 +457,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
>  
>  	switch (sysreg) {
> +	case SYS_ICC_GRPEN1_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_igrpen1;
> +		else
> +			fn = __vgic_v3_write_igrpen1;
> +		break;
>  	case SYS_ICC_BPR1_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_bpr1;
> 

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

* Re: [PATCH 11/31] KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-17 15:39     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17 15:39 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_BPR1_EL1
> register, which is located in the ICH_VMCR_EL2.BPR1 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 61 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 435787a93c6c..f0f038c490a5 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -375,9 +375,57 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>  
>  #ifdef CONFIG_ARM64
>  
> +static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
> +{
> +	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> +}
> +
> +static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
> +{
> +	unsigned int bpr;
> +
> +	if (vmcr & ICH_VMCR_CBPR_MASK) {
> +		bpr = __vgic_v3_get_bpr0(vmcr);
> +		if (bpr < 7)
> +			bpr++;
> +	} else {
> +		bpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
> +	}
> +
> +	return bpr;
> +}
> +
> +static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
> +}
> +
> +static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +	u8 bpr_min = 8 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +
> +	if (vmcr & ICH_VMCR_CBPR_MASK)
> +		return;
> +
> +	/* Enforce BPR limiting */
> +	if (val < bpr_min)
> +		val = bpr_min;
> +
> +	val <<= ICH_VMCR_BPR1_SHIFT;
> +	val &= ICH_VMCR_BPR1_MASK;
> +	vmcr &= ~ICH_VMCR_BPR1_MASK;
> +	vmcr |= val;
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
> -	u32 esr = kvm_vcpu_get_hsr(vcpu);
> +	int rt = kvm_vcpu_sys_get_rt(vcpu);
nit: could be done later when setting is_read.

> +	u32 vmcr, esr = kvm_vcpu_get_hsr(vcpu);
Christoffer does not like this ;-)

Besides looks good to me

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric


> +	void (*fn)(struct kvm_vcpu *, u32, int);
> +	bool is_read;
>  	u32 sysreg;
>  
>  	if (vcpu_mode_is_32bit(vcpu)) {
> @@ -389,11 +437,22 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		sysreg = esr_sys64_to_sysreg(esr);
>  	}
>  
> +	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
> +
>  	switch (sysreg) {
> +	case SYS_ICC_BPR1_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_bpr1;
> +		else
> +			fn = __vgic_v3_write_bpr1;
> +		break;
>  	default:
>  		return 0;
>  	}
>  
> +	vmcr = __vgic_v3_read_vmcr();
> +	fn(vcpu, vmcr, rt);
> +
>  	return 1;
>  }
>  
> 

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

* [PATCH 11/31] KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler
@ 2017-05-17 15:39     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-17 15:39 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_BPR1_EL1
> register, which is located in the ICH_VMCR_EL2.BPR1 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 61 ++++++++++++++++++++++++++++++++++++++++++-
>  1 file changed, 60 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 435787a93c6c..f0f038c490a5 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -375,9 +375,57 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>  
>  #ifdef CONFIG_ARM64
>  
> +static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
> +{
> +	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> +}
> +
> +static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
> +{
> +	unsigned int bpr;
> +
> +	if (vmcr & ICH_VMCR_CBPR_MASK) {
> +		bpr = __vgic_v3_get_bpr0(vmcr);
> +		if (bpr < 7)
> +			bpr++;
> +	} else {
> +		bpr = (vmcr & ICH_VMCR_BPR1_MASK) >> ICH_VMCR_BPR1_SHIFT;
> +	}
> +
> +	return bpr;
> +}
> +
> +static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
> +}
> +
> +static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +	u8 bpr_min = 8 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +
> +	if (vmcr & ICH_VMCR_CBPR_MASK)
> +		return;
> +
> +	/* Enforce BPR limiting */
> +	if (val < bpr_min)
> +		val = bpr_min;
> +
> +	val <<= ICH_VMCR_BPR1_SHIFT;
> +	val &= ICH_VMCR_BPR1_MASK;
> +	vmcr &= ~ICH_VMCR_BPR1_MASK;
> +	vmcr |= val;
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
> -	u32 esr = kvm_vcpu_get_hsr(vcpu);
> +	int rt = kvm_vcpu_sys_get_rt(vcpu);
nit: could be done later when setting is_read.

> +	u32 vmcr, esr = kvm_vcpu_get_hsr(vcpu);
Christoffer does not like this ;-)

Besides looks good to me

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric


> +	void (*fn)(struct kvm_vcpu *, u32, int);
> +	bool is_read;
>  	u32 sysreg;
>  
>  	if (vcpu_mode_is_32bit(vcpu)) {
> @@ -389,11 +437,22 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		sysreg = esr_sys64_to_sysreg(esr);
>  	}
>  
> +	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
> +
>  	switch (sysreg) {
> +	case SYS_ICC_BPR1_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_bpr1;
> +		else
> +			fn = __vgic_v3_write_bpr1;
> +		break;
>  	default:
>  		return 0;
>  	}
>  
> +	vmcr = __vgic_v3_read_vmcr();
> +	fn(vcpu, vmcr, rt);
> +
>  	return 1;
>  }
>  
> 

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

* Re: [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-18  7:41     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-18  7:41 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading the guest's view of the ICC_IAR1_EL1
> register. This involves finding the highest priority Group-1
> interrupt, checking against both PMR and the active group
> priority, activating the interrupt and setting the group
> priority as active.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |   1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 135 insertions(+)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 97cbca19430d..7610ea4e8337 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -391,6 +391,7 @@
>  #define ICH_LR_PHYS_ID_SHIFT		32
>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>  #define ICH_LR_PRIORITY_SHIFT		48
> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>  
>  /* These are for GICv2 emulation only */
>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 473ef22508e6..49aad1de3ac8 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>  
>  #ifdef CONFIG_ARM64
>  
> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
> +{
> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
> +
> +	return crm != 8;
> +}
> +
> +#define GICv3_IDLE_PRIORITY	0xff
> +
> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
> +						    u32 vmcr,
> +						    u64 *lr_val)
> +{
> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> +	u8 priority = GICv3_IDLE_PRIORITY;
> +	int i, lr = -1;
> +
> +	for (i = 0; i < used_lrs; i++) {
> +		u64 val = __gic_v3_get_lr(i);
> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
> +
> +		/* Not pending in the state? */
> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
> +			continue;
> +
> +		/* Group-0 interrupt, but Group-0 disabled? */
> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
> +			continue;
> +
> +		/* Group-1 interrupt, but Group-1 disabled? */
> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
> +			continue;
> +
> +		/* Not the highest priority? */
> +		if (lr_prio >= priority)
> +			continue;
> +
> +		/* This is a candidate */
> +		priority = lr_prio;
> +		*lr_val = val;
> +		lr = i;
> +	}
> +
> +	if (lr == -1)
> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
> +
> +	return lr;
> +}
> +
> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
> +{
> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
s/nr_aprs/nr_apr_regs ?

> +	u32 hap = 0;
> +	int i;
> +
> +	for (i = 0; i < nr_aprs; i++) {
> +		u32 val;
> +
> +		val  = __vgic_v3_read_ap0rn(i);
> +		val |= __vgic_v3_read_ap1rn(i);
> +		if (val)
> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
here don't we need to shift by the actual number of subpriority bits?
isn't nr_pre_bits the max implemented preemption bits but not
necessarily the actual chosen number set by bpr?
> +
> +		hap += 32;
> +	}
> +
> +	return GICv3_IDLE_PRIORITY;
> +}
> +
>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>  {
>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>  	return bpr;
>  }
>  
Would be nice to have a short doc comment.
I understand this zeros the subpriority field in the priority value, is
it correct? pseudocode PriorityGroup()?
> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
> +{
> +	unsigned int bpr;
> +
> +	if (!grp)
> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
> +	else
> +		bpr = __vgic_v3_get_bpr1(vmcr);
> +
> +	return pri & (GENMASK(7, 0) << bpr);
 & GENMASK(7, bpr)?
> +}
> +
> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
> +{
> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +	u8 hap = pre >> (8 - nr_pre_bits);
Could you add a comment about what is hap. I tend to think it is the
group priority but then I don't get why we don't shift by 8 -bpr

Thanks

Eric
> +	int apr = hap / 32;
> +	u32 bit = BIT(hap % 32);
> +	u32 val;
> +
> +	val = __vgic_v3_read_ap1rn(apr);
> +	__vgic_v3_write_ap1rn(val | bit, apr);
> +}
> +
> +static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 lr_val;
> +	u8 lr_prio, pmr;
> +	int lr, grp;
> +
> +	grp = __vgic_v3_get_group(vcpu);
> +
> +	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
> +	if (lr < 0)
> +		goto spurious;
> +
> +	if (grp != !!(lr_val & ICH_LR_GROUP))
> +		goto spurious;
> +
> +	pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
> +	if (pmr <= lr_prio)
> +		goto spurious;
> +
> +	if (__vgic_v3_get_highest_active_priority() <= lr_prio)
> +		goto spurious;
> +
> +	lr_val &= ~ICH_LR_STATE;
> +	/* No active state for LPIs */
> +	if ((lr_val & ICH_LR_VIRTUAL_ID_MASK) <= VGIC_MAX_SPI)
> +		lr_val |= ICH_LR_ACTIVE_BIT;
> +	__gic_v3_set_lr(lr_val, lr);
> +	__vgic_v3_set_active_priority(__vgic_v3_pri_to_pre(lr_prio, vmcr, grp));
> +	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
> +	return;
> +
> +spurious:
> +	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
> +}
> +
>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
> @@ -457,6 +588,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
>  
>  	switch (sysreg) {
> +	case SYS_ICC_IAR1_EL1:
> +		fn = __vgic_v3_read_iar;
> +		break;
>  	case SYS_ICC_GRPEN1_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_igrpen1;
> 

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

* [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
@ 2017-05-18  7:41     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-18  7:41 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading the guest's view of the ICC_IAR1_EL1
> register. This involves finding the highest priority Group-1
> interrupt, checking against both PMR and the active group
> priority, activating the interrupt and setting the group
> priority as active.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |   1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 135 insertions(+)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 97cbca19430d..7610ea4e8337 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -391,6 +391,7 @@
>  #define ICH_LR_PHYS_ID_SHIFT		32
>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>  #define ICH_LR_PRIORITY_SHIFT		48
> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>  
>  /* These are for GICv2 emulation only */
>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 473ef22508e6..49aad1de3ac8 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>  
>  #ifdef CONFIG_ARM64
>  
> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
> +{
> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
> +
> +	return crm != 8;
> +}
> +
> +#define GICv3_IDLE_PRIORITY	0xff
> +
> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
> +						    u32 vmcr,
> +						    u64 *lr_val)
> +{
> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> +	u8 priority = GICv3_IDLE_PRIORITY;
> +	int i, lr = -1;
> +
> +	for (i = 0; i < used_lrs; i++) {
> +		u64 val = __gic_v3_get_lr(i);
> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
> +
> +		/* Not pending in the state? */
> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
> +			continue;
> +
> +		/* Group-0 interrupt, but Group-0 disabled? */
> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
> +			continue;
> +
> +		/* Group-1 interrupt, but Group-1 disabled? */
> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
> +			continue;
> +
> +		/* Not the highest priority? */
> +		if (lr_prio >= priority)
> +			continue;
> +
> +		/* This is a candidate */
> +		priority = lr_prio;
> +		*lr_val = val;
> +		lr = i;
> +	}
> +
> +	if (lr == -1)
> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
> +
> +	return lr;
> +}
> +
> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
> +{
> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
s/nr_aprs/nr_apr_regs ?

> +	u32 hap = 0;
> +	int i;
> +
> +	for (i = 0; i < nr_aprs; i++) {
> +		u32 val;
> +
> +		val  = __vgic_v3_read_ap0rn(i);
> +		val |= __vgic_v3_read_ap1rn(i);
> +		if (val)
> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
here don't we need to shift by the actual number of subpriority bits?
isn't nr_pre_bits the max implemented preemption bits but not
necessarily the actual chosen number set by bpr?
> +
> +		hap += 32;
> +	}
> +
> +	return GICv3_IDLE_PRIORITY;
> +}
> +
>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>  {
>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>  	return bpr;
>  }
>  
Would be nice to have a short doc comment.
I understand this zeros the subpriority field in the priority value, is
it correct? pseudocode PriorityGroup()?
> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
> +{
> +	unsigned int bpr;
> +
> +	if (!grp)
> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
> +	else
> +		bpr = __vgic_v3_get_bpr1(vmcr);
> +
> +	return pri & (GENMASK(7, 0) << bpr);
 & GENMASK(7, bpr)?
> +}
> +
> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
> +{
> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +	u8 hap = pre >> (8 - nr_pre_bits);
Could you add a comment about what is hap. I tend to think it is the
group priority but then I don't get why we don't shift by 8 -bpr

Thanks

Eric
> +	int apr = hap / 32;
> +	u32 bit = BIT(hap % 32);
> +	u32 val;
> +
> +	val = __vgic_v3_read_ap1rn(apr);
> +	__vgic_v3_write_ap1rn(val | bit, apr);
> +}
> +
> +static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 lr_val;
> +	u8 lr_prio, pmr;
> +	int lr, grp;
> +
> +	grp = __vgic_v3_get_group(vcpu);
> +
> +	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
> +	if (lr < 0)
> +		goto spurious;
> +
> +	if (grp != !!(lr_val & ICH_LR_GROUP))
> +		goto spurious;
> +
> +	pmr = (vmcr & ICH_VMCR_PMR_MASK) >> ICH_VMCR_PMR_SHIFT;
> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
> +	if (pmr <= lr_prio)
> +		goto spurious;
> +
> +	if (__vgic_v3_get_highest_active_priority() <= lr_prio)
> +		goto spurious;
> +
> +	lr_val &= ~ICH_LR_STATE;
> +	/* No active state for LPIs */
> +	if ((lr_val & ICH_LR_VIRTUAL_ID_MASK) <= VGIC_MAX_SPI)
> +		lr_val |= ICH_LR_ACTIVE_BIT;
> +	__gic_v3_set_lr(lr_val, lr);
> +	__vgic_v3_set_active_priority(__vgic_v3_pri_to_pre(lr_prio, vmcr, grp));
> +	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
> +	return;
> +
> +spurious:
> +	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
> +}
> +
>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
> @@ -457,6 +588,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
>  
>  	switch (sysreg) {
> +	case SYS_ICC_IAR1_EL1:
> +		fn = __vgic_v3_read_iar;
> +		break;
>  	case SYS_ICC_GRPEN1_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_igrpen1;
> 

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

* Re: [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  2017-05-18  7:41     ` Auger Eric
@ 2017-05-22 17:52       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-22 17:52 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Eric,

On 18/05/17 08:41, Auger Eric wrote:
> Hi Marc,
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> Add a handler for reading the guest's view of the ICC_IAR1_EL1
>> register. This involves finding the highest priority Group-1
>> interrupt, checking against both PMR and the active group
>> priority, activating the interrupt and setting the group
>> priority as active.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 135 insertions(+)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index 97cbca19430d..7610ea4e8337 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -391,6 +391,7 @@
>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>  #define ICH_LR_PRIORITY_SHIFT		48
>> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>>  
>>  /* These are for GICv2 emulation only */
>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 473ef22508e6..49aad1de3ac8 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>>  
>>  #ifdef CONFIG_ARM64
>>  
>> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
>> +{
>> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
>> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>> +
>> +	return crm != 8;
>> +}
>> +
>> +#define GICv3_IDLE_PRIORITY	0xff
>> +
>> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>> +						    u32 vmcr,
>> +						    u64 *lr_val)
>> +{
>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>> +	u8 priority = GICv3_IDLE_PRIORITY;
>> +	int i, lr = -1;
>> +
>> +	for (i = 0; i < used_lrs; i++) {
>> +		u64 val = __gic_v3_get_lr(i);
>> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>> +
>> +		/* Not pending in the state? */
>> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
>> +			continue;
>> +
>> +		/* Group-0 interrupt, but Group-0 disabled? */
>> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
>> +			continue;
>> +
>> +		/* Group-1 interrupt, but Group-1 disabled? */
>> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
>> +			continue;
>> +
>> +		/* Not the highest priority? */
>> +		if (lr_prio >= priority)
>> +			continue;
>> +
>> +		/* This is a candidate */
>> +		priority = lr_prio;
>> +		*lr_val = val;
>> +		lr = i;
>> +	}
>> +
>> +	if (lr == -1)
>> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
>> +
>> +	return lr;
>> +}
>> +
>> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>> +{
>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
> s/nr_aprs/nr_apr_regs ?

Sure, I can do that if that helps.

>> +	u32 hap = 0;
>> +	int i;
>> +
>> +	for (i = 0; i < nr_aprs; i++) {
>> +		u32 val;
>> +
>> +		val  = __vgic_v3_read_ap0rn(i);
>> +		val |= __vgic_v3_read_ap1rn(i);
>> +		if (val)
>> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
> here don't we need to shift by the actual number of subpriority bits?
> isn't nr_pre_bits the max implemented preemption bits but not
> necessarily the actual chosen number set by bpr?

Hmmm. I don't think that works. If you did that, you could end-up in a
bizarre situation where you can completely miss the current active
priority. Try for example:

	nr_pre_bits=5
	set BPR1=3 (5 preemption bits)
	read IAR, interrupt priority = 0x10, set bit 2 in AP1R0
	set BPR=4 (4 preemption bits)

With this setting, you've changed the active priority from being 0x10
(with BPR1=3) to being 8. This is wrong, as this should be an invariant.

The only way to avoid this unfortunate state of affair is to always
normalize the active priority to always be stored as if BPR had its
smallest possible value (which happens to be nr_pre_bits).

>> +
>> +		hap += 32;
>> +	}
>> +
>> +	return GICv3_IDLE_PRIORITY;
>> +}
>> +
>>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>>  {
>>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>>  	return bpr;
>>  }
>>  
> Would be nice to have a short doc comment.
> I understand this zeros the subpriority field in the priority value, is
> it correct? pseudocode PriorityGroup()?

Yes, I should probably add some references to the pseudocode.

>> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
>> +{
>> +	unsigned int bpr;
>> +
>> +	if (!grp)
>> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
>> +	else
>> +		bpr = __vgic_v3_get_bpr1(vmcr);
>> +
>> +	return pri & (GENMASK(7, 0) << bpr);
>  & GENMASK(7, bpr)?

Not sure about that. If grp==0, bpr can range from 1 to 8. If it is 8,
what is the meaning of GENMASK(7,8)?

>> +}
>> +
>> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>> +{
>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> +	u8 hap = pre >> (8 - nr_pre_bits);
> Could you add a comment about what is hap. I tend to think it is the
> group priority but then I don't get why we don't shift by 8 -bpr

"hap" stands for Highest Active Priority. And for the reasons describer
above, we need to normalize it, irrespective of the BPR.

Does it make sense?

Thanks,

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

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

* [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
@ 2017-05-22 17:52       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-22 17:52 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

On 18/05/17 08:41, Auger Eric wrote:
> Hi Marc,
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> Add a handler for reading the guest's view of the ICC_IAR1_EL1
>> register. This involves finding the highest priority Group-1
>> interrupt, checking against both PMR and the active group
>> priority, activating the interrupt and setting the group
>> priority as active.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 135 insertions(+)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index 97cbca19430d..7610ea4e8337 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -391,6 +391,7 @@
>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>  #define ICH_LR_PRIORITY_SHIFT		48
>> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>>  
>>  /* These are for GICv2 emulation only */
>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 473ef22508e6..49aad1de3ac8 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>>  
>>  #ifdef CONFIG_ARM64
>>  
>> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
>> +{
>> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
>> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>> +
>> +	return crm != 8;
>> +}
>> +
>> +#define GICv3_IDLE_PRIORITY	0xff
>> +
>> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>> +						    u32 vmcr,
>> +						    u64 *lr_val)
>> +{
>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>> +	u8 priority = GICv3_IDLE_PRIORITY;
>> +	int i, lr = -1;
>> +
>> +	for (i = 0; i < used_lrs; i++) {
>> +		u64 val = __gic_v3_get_lr(i);
>> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>> +
>> +		/* Not pending in the state? */
>> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
>> +			continue;
>> +
>> +		/* Group-0 interrupt, but Group-0 disabled? */
>> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
>> +			continue;
>> +
>> +		/* Group-1 interrupt, but Group-1 disabled? */
>> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
>> +			continue;
>> +
>> +		/* Not the highest priority? */
>> +		if (lr_prio >= priority)
>> +			continue;
>> +
>> +		/* This is a candidate */
>> +		priority = lr_prio;
>> +		*lr_val = val;
>> +		lr = i;
>> +	}
>> +
>> +	if (lr == -1)
>> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
>> +
>> +	return lr;
>> +}
>> +
>> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>> +{
>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
> s/nr_aprs/nr_apr_regs ?

Sure, I can do that if that helps.

>> +	u32 hap = 0;
>> +	int i;
>> +
>> +	for (i = 0; i < nr_aprs; i++) {
>> +		u32 val;
>> +
>> +		val  = __vgic_v3_read_ap0rn(i);
>> +		val |= __vgic_v3_read_ap1rn(i);
>> +		if (val)
>> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
> here don't we need to shift by the actual number of subpriority bits?
> isn't nr_pre_bits the max implemented preemption bits but not
> necessarily the actual chosen number set by bpr?

Hmmm. I don't think that works. If you did that, you could end-up in a
bizarre situation where you can completely miss the current active
priority. Try for example:

	nr_pre_bits=5
	set BPR1=3 (5 preemption bits)
	read IAR, interrupt priority = 0x10, set bit 2 in AP1R0
	set BPR=4 (4 preemption bits)

With this setting, you've changed the active priority from being 0x10
(with BPR1=3) to being 8. This is wrong, as this should be an invariant.

The only way to avoid this unfortunate state of affair is to always
normalize the active priority to always be stored as if BPR had its
smallest possible value (which happens to be nr_pre_bits).

>> +
>> +		hap += 32;
>> +	}
>> +
>> +	return GICv3_IDLE_PRIORITY;
>> +}
>> +
>>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>>  {
>>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>>  	return bpr;
>>  }
>>  
> Would be nice to have a short doc comment.
> I understand this zeros the subpriority field in the priority value, is
> it correct? pseudocode PriorityGroup()?

Yes, I should probably add some references to the pseudocode.

>> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
>> +{
>> +	unsigned int bpr;
>> +
>> +	if (!grp)
>> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
>> +	else
>> +		bpr = __vgic_v3_get_bpr1(vmcr);
>> +
>> +	return pri & (GENMASK(7, 0) << bpr);
>  & GENMASK(7, bpr)?

Not sure about that. If grp==0, bpr can range from 1 to 8. If it is 8,
what is the meaning of GENMASK(7,8)?

>> +}
>> +
>> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>> +{
>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> +	u8 hap = pre >> (8 - nr_pre_bits);
> Could you add a comment about what is hap. I tend to think it is the
> group priority but then I don't get why we don't shift by 8 -bpr

"hap" stands for Highest Active Priority. And for the reasons describer
above, we need to normalize it, irrespective of the BPR.

Does it make sense?

Thanks,

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

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-17  9:54     ` Auger Eric
  (?)
@ 2017-05-22 18:52       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-22 18:52 UTC (permalink / raw)
  To: Auger Eric
  Cc: Christoffer Dall, Mark Rutland, kvm, David Daney,
	Catalin Marinas, Robert Richter, kvmarm, linux-arm-kernel

On Wed, May 17 2017 at 11:54:23 am BST, Auger Eric <eric.auger@redhat.com> wrote:
> Hi,
>
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> As we're about to access the Active Priority registers a lot more,
>> let's define accessors that take the register number as a parameter.
>> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 100 insertions(+), 16 deletions(-)
>> 
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 32c3295929b0..990d9d1e85d0 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>  	}
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP0R3_EL2);
>> +		break;
>> +	}
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP1R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP1R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP1R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP1R3_EL2);
>> +		break;
>> +	}
>> +}
>> +
>> +static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
>> +{
>> +	u32 val;
>> +
>> +	switch (n) {
>> +	case 0:
>> +		val = read_gicreg(ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		val = read_gicreg(ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		val = read_gicreg(ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		val = read_gicreg(ICH_AP0R3_EL2);
>> +		break;
>> +	default:
>> +		unreachable();
> I am not familiar with that macro. For my curiosity why is it used here
> and not in write functions.

I probably have looked at the assembly code and realised that using this
macro was helping the compiler not to generate horrible code because it
doesn't know that it will always return a value.

The "write" part doesn't need this not to be awful, so I didn't feel the
need to add it. Can do though.

>
> Besides Mark's comment,
>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks,

	M.
-- 
Jazz is not dead, it just smell funny.

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-22 18:52       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-22 18:52 UTC (permalink / raw)
  To: Auger Eric
  Cc: Christoffer Dall, Mark Rutland, kvm, David Daney,
	Catalin Marinas, Robert Richter, kvmarm, linux-arm-kernel

On Wed, May 17 2017 at 11:54:23 am BST, Auger Eric <eric.auger@redhat.com> wrote:
> Hi,
>
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> As we're about to access the Active Priority registers a lot more,
>> let's define accessors that take the register number as a parameter.
>> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 100 insertions(+), 16 deletions(-)
>> 
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 32c3295929b0..990d9d1e85d0 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>  	}
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP0R3_EL2);
>> +		break;
>> +	}
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP1R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP1R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP1R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP1R3_EL2);
>> +		break;
>> +	}
>> +}
>> +
>> +static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
>> +{
>> +	u32 val;
>> +
>> +	switch (n) {
>> +	case 0:
>> +		val = read_gicreg(ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		val = read_gicreg(ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		val = read_gicreg(ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		val = read_gicreg(ICH_AP0R3_EL2);
>> +		break;
>> +	default:
>> +		unreachable();
> I am not familiar with that macro. For my curiosity why is it used here
> and not in write functions.

I probably have looked at the assembly code and realised that using this
macro was helping the compiler not to generate horrible code because it
doesn't know that it will always return a value.

The "write" part doesn't need this not to be awful, so I didn't feel the
need to add it. Can do though.

>
> Besides Mark's comment,
>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks,

	M.
-- 
Jazz is not dead, it just smell funny.

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-22 18:52       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-22 18:52 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 17 2017 at 11:54:23 am BST, Auger Eric <eric.auger@redhat.com> wrote:
> Hi,
>
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> As we're about to access the Active Priority registers a lot more,
>> let's define accessors that take the register number as a parameter.
>> 
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>  1 file changed, 100 insertions(+), 16 deletions(-)
>> 
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 32c3295929b0..990d9d1e85d0 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>  	}
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP0R3_EL2);
>> +		break;
>> +	}
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_ap1rn(u32 val, int n)
>> +{
>> +	switch (n) {
>> +	case 0:
>> +		write_gicreg(val, ICH_AP1R0_EL2);
>> +		break;
>> +	case 1:
>> +		write_gicreg(val, ICH_AP1R1_EL2);
>> +		break;
>> +	case 2:
>> +		write_gicreg(val, ICH_AP1R2_EL2);
>> +		break;
>> +	case 3:
>> +		write_gicreg(val, ICH_AP1R3_EL2);
>> +		break;
>> +	}
>> +}
>> +
>> +static u32 __hyp_text __vgic_v3_read_ap0rn(int n)
>> +{
>> +	u32 val;
>> +
>> +	switch (n) {
>> +	case 0:
>> +		val = read_gicreg(ICH_AP0R0_EL2);
>> +		break;
>> +	case 1:
>> +		val = read_gicreg(ICH_AP0R1_EL2);
>> +		break;
>> +	case 2:
>> +		val = read_gicreg(ICH_AP0R2_EL2);
>> +		break;
>> +	case 3:
>> +		val = read_gicreg(ICH_AP0R3_EL2);
>> +		break;
>> +	default:
>> +		unreachable();
> I am not familiar with that macro. For my curiosity why is it used here
> and not in write functions.

I probably have looked at the assembly code and realised that using this
macro was helping the compiler not to generate horrible code because it
doesn't know that it will always return a value.

The "write" part doesn't need this not to be awful, so I didn't feel the
need to add it. Can do though.

>
> Besides Mark's comment,
>
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks,

	M.
-- 
Jazz is not dead, it just smell funny.

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

* Re: [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  2017-05-22 17:52       ` Marc Zyngier
@ 2017-05-23  7:22         ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-23  7:22 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc,

On 22/05/2017 19:52, Marc Zyngier wrote:
> Hi Eric,
> 
> On 18/05/17 08:41, Auger Eric wrote:
>> Hi Marc,
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> Add a handler for reading the guest's view of the ICC_IAR1_EL1
>>> register. This involves finding the highest priority Group-1
>>> interrupt, checking against both PMR and the active group
>>> priority, activating the interrupt and setting the group
>>> priority as active.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 135 insertions(+)
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index 97cbca19430d..7610ea4e8337 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -391,6 +391,7 @@
>>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>>  #define ICH_LR_PRIORITY_SHIFT		48
>>> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>>>  
>>>  /* These are for GICv2 emulation only */
>>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index 473ef22508e6..49aad1de3ac8 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>>>  
>>>  #ifdef CONFIG_ARM64
>>>  
>>> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
>>> +{
>>> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
>>> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>>> +
>>> +	return crm != 8;
>>> +}
>>> +
>>> +#define GICv3_IDLE_PRIORITY	0xff
>>> +
>>> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>> +						    u32 vmcr,
>>> +						    u64 *lr_val)
>>> +{
>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>> +	u8 priority = GICv3_IDLE_PRIORITY;
>>> +	int i, lr = -1;
>>> +
>>> +	for (i = 0; i < used_lrs; i++) {
>>> +		u64 val = __gic_v3_get_lr(i);
>>> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>>> +
>>> +		/* Not pending in the state? */
>>> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
>>> +			continue;
>>> +
>>> +		/* Group-0 interrupt, but Group-0 disabled? */
>>> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
>>> +			continue;
>>> +
>>> +		/* Group-1 interrupt, but Group-1 disabled? */
>>> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
>>> +			continue;
>>> +
>>> +		/* Not the highest priority? */
>>> +		if (lr_prio >= priority)
>>> +			continue;
>>> +
>>> +		/* This is a candidate */
>>> +		priority = lr_prio;
>>> +		*lr_val = val;
>>> +		lr = i;
>>> +	}
>>> +
>>> +	if (lr == -1)
>>> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
>>> +
>>> +	return lr;
>>> +}
>>> +
>>> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>> +{
>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
>> s/nr_aprs/nr_apr_regs ?
> 
> Sure, I can do that if that helps.
> 
>>> +	u32 hap = 0;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < nr_aprs; i++) {
>>> +		u32 val;
>>> +
>>> +		val  = __vgic_v3_read_ap0rn(i);
>>> +		val |= __vgic_v3_read_ap1rn(i);
>>> +		if (val)
>>> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
>> here don't we need to shift by the actual number of subpriority bits?
>> isn't nr_pre_bits the max implemented preemption bits but not
>> necessarily the actual chosen number set by bpr?
> 
> Hmmm. I don't think that works. If you did that, you could end-up in a
> bizarre situation where you can completely miss the current active
> priority. Try for example:
> 
> 	nr_pre_bits=5
> 	set BPR1=3 (5 preemption bits)
> 	read IAR, interrupt priority = 0x10, set bit 2 in AP1R0
> 	set BPR=4 (4 preemption bits)
> 
> With this setting, you've changed the active priority from being 0x10
> (with BPR1=3) to being 8. This is wrong, as this should be an invariant.
> 
> The only way to avoid this unfortunate state of affair is to always
> normalize the active priority to always be stored as if BPR had its
> smallest possible value (which happens to be nr_pre_bits).

Hum ok. I get your point now and that looks correct to me too. Maybe a
small comment for subsequent readers would avoid the same question.
> 
>>> +
>>> +		hap += 32;
>>> +	}
>>> +
>>> +	return GICv3_IDLE_PRIORITY;
>>> +}
>>> +
>>>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>>>  {
>>>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>>> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>>>  	return bpr;
>>>  }
>>>  
>> Would be nice to have a short doc comment.
>> I understand this zeros the subpriority field in the priority value, is
>> it correct? pseudocode PriorityGroup()?
> 
> Yes, I should probably add some references to the pseudocode.
> 
>>> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
>>> +{
>>> +	unsigned int bpr;
>>> +
>>> +	if (!grp)
>>> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
>>> +	else
>>> +		bpr = __vgic_v3_get_bpr1(vmcr);
>>> +
>>> +	return pri & (GENMASK(7, 0) << bpr);
>>  & GENMASK(7, bpr)?
> 
> Not sure about that. If grp==0, bpr can range from 1 to 8. If it is 8,
> what is the meaning of GENMASK(7,8)?

OK forget it ;-)
> 
>>> +}
>>> +
>>> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>> +{
>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> +	u8 hap = pre >> (8 - nr_pre_bits);
>> Could you add a comment about what is hap. I tend to think it is the
>> group priority but then I don't get why we don't shift by 8 -bpr
> 
> "hap" stands for Highest Active Priority. And for the reasons describer
> above, we need to normalize it, irrespective of the BPR.
> 
> Does it make sense?

yes it does.

So Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

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

* [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
@ 2017-05-23  7:22         ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-23  7:22 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 22/05/2017 19:52, Marc Zyngier wrote:
> Hi Eric,
> 
> On 18/05/17 08:41, Auger Eric wrote:
>> Hi Marc,
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> Add a handler for reading the guest's view of the ICC_IAR1_EL1
>>> register. This involves finding the highest priority Group-1
>>> interrupt, checking against both PMR and the active group
>>> priority, activating the interrupt and setting the group
>>> priority as active.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 135 insertions(+)
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index 97cbca19430d..7610ea4e8337 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -391,6 +391,7 @@
>>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>>  #define ICH_LR_PRIORITY_SHIFT		48
>>> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>>>  
>>>  /* These are for GICv2 emulation only */
>>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index 473ef22508e6..49aad1de3ac8 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>>>  
>>>  #ifdef CONFIG_ARM64
>>>  
>>> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
>>> +{
>>> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
>>> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>>> +
>>> +	return crm != 8;
>>> +}
>>> +
>>> +#define GICv3_IDLE_PRIORITY	0xff
>>> +
>>> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>> +						    u32 vmcr,
>>> +						    u64 *lr_val)
>>> +{
>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>> +	u8 priority = GICv3_IDLE_PRIORITY;
>>> +	int i, lr = -1;
>>> +
>>> +	for (i = 0; i < used_lrs; i++) {
>>> +		u64 val = __gic_v3_get_lr(i);
>>> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>>> +
>>> +		/* Not pending in the state? */
>>> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
>>> +			continue;
>>> +
>>> +		/* Group-0 interrupt, but Group-0 disabled? */
>>> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
>>> +			continue;
>>> +
>>> +		/* Group-1 interrupt, but Group-1 disabled? */
>>> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
>>> +			continue;
>>> +
>>> +		/* Not the highest priority? */
>>> +		if (lr_prio >= priority)
>>> +			continue;
>>> +
>>> +		/* This is a candidate */
>>> +		priority = lr_prio;
>>> +		*lr_val = val;
>>> +		lr = i;
>>> +	}
>>> +
>>> +	if (lr == -1)
>>> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
>>> +
>>> +	return lr;
>>> +}
>>> +
>>> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>> +{
>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
>> s/nr_aprs/nr_apr_regs ?
> 
> Sure, I can do that if that helps.
> 
>>> +	u32 hap = 0;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < nr_aprs; i++) {
>>> +		u32 val;
>>> +
>>> +		val  = __vgic_v3_read_ap0rn(i);
>>> +		val |= __vgic_v3_read_ap1rn(i);
>>> +		if (val)
>>> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
>> here don't we need to shift by the actual number of subpriority bits?
>> isn't nr_pre_bits the max implemented preemption bits but not
>> necessarily the actual chosen number set by bpr?
> 
> Hmmm. I don't think that works. If you did that, you could end-up in a
> bizarre situation where you can completely miss the current active
> priority. Try for example:
> 
> 	nr_pre_bits=5
> 	set BPR1=3 (5 preemption bits)
> 	read IAR, interrupt priority = 0x10, set bit 2 in AP1R0
> 	set BPR=4 (4 preemption bits)
> 
> With this setting, you've changed the active priority from being 0x10
> (with BPR1=3) to being 8. This is wrong, as this should be an invariant.
> 
> The only way to avoid this unfortunate state of affair is to always
> normalize the active priority to always be stored as if BPR had its
> smallest possible value (which happens to be nr_pre_bits).

Hum ok. I get your point now and that looks correct to me too. Maybe a
small comment for subsequent readers would avoid the same question.
> 
>>> +
>>> +		hap += 32;
>>> +	}
>>> +
>>> +	return GICv3_IDLE_PRIORITY;
>>> +}
>>> +
>>>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>>>  {
>>>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>>> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>>>  	return bpr;
>>>  }
>>>  
>> Would be nice to have a short doc comment.
>> I understand this zeros the subpriority field in the priority value, is
>> it correct? pseudocode PriorityGroup()?
> 
> Yes, I should probably add some references to the pseudocode.
> 
>>> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
>>> +{
>>> +	unsigned int bpr;
>>> +
>>> +	if (!grp)
>>> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
>>> +	else
>>> +		bpr = __vgic_v3_get_bpr1(vmcr);
>>> +
>>> +	return pri & (GENMASK(7, 0) << bpr);
>>  & GENMASK(7, bpr)?
> 
> Not sure about that. If grp==0, bpr can range from 1 to 8. If it is 8,
> what is the meaning of GENMASK(7,8)?

OK forget it ;-)
> 
>>> +}
>>> +
>>> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>> +{
>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> +	u8 hap = pre >> (8 - nr_pre_bits);
>> Could you add a comment about what is hap. I tend to think it is the
>> group priority but then I don't get why we don't shift by 8 -bpr
> 
> "hap" stands for Highest Active Priority. And for the reasons describer
> above, we need to normalize it, irrespective of the BPR.
> 
> Does it make sense?

yes it does.

So Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> Thanks,
> 
> 	M.
> 

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

* Re: [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
  2017-05-23  7:22         ` Auger Eric
@ 2017-05-23  9:26           ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-23  9:26 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

On 23/05/17 08:22, Auger Eric wrote:
> Hi Marc,
> 
> On 22/05/2017 19:52, Marc Zyngier wrote:
>> Hi Eric,
>>
>> On 18/05/17 08:41, Auger Eric wrote:
>>> Hi Marc,
>>>
>>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>>> Add a handler for reading the guest's view of the ICC_IAR1_EL1
>>>> register. This involves finding the highest priority Group-1
>>>> interrupt, checking against both PMR and the active group
>>>> priority, activating the interrupt and setting the group
>>>> priority as active.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>> ---
>>>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>>>>  2 files changed, 135 insertions(+)
>>>>
>>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>>> index 97cbca19430d..7610ea4e8337 100644
>>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>>> @@ -391,6 +391,7 @@
>>>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>>>  #define ICH_LR_PRIORITY_SHIFT		48
>>>> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>>>>  
>>>>  /* These are for GICv2 emulation only */
>>>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>> index 473ef22508e6..49aad1de3ac8 100644
>>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>>>>  
>>>>  #ifdef CONFIG_ARM64
>>>>  
>>>> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
>>>> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>>>> +
>>>> +	return crm != 8;
>>>> +}
>>>> +
>>>> +#define GICv3_IDLE_PRIORITY	0xff
>>>> +
>>>> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>> +						    u32 vmcr,
>>>> +						    u64 *lr_val)
>>>> +{
>>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>>> +	u8 priority = GICv3_IDLE_PRIORITY;
>>>> +	int i, lr = -1;
>>>> +
>>>> +	for (i = 0; i < used_lrs; i++) {
>>>> +		u64 val = __gic_v3_get_lr(i);
>>>> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>>>> +
>>>> +		/* Not pending in the state? */
>>>> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
>>>> +			continue;
>>>> +
>>>> +		/* Group-0 interrupt, but Group-0 disabled? */
>>>> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
>>>> +			continue;
>>>> +
>>>> +		/* Group-1 interrupt, but Group-1 disabled? */
>>>> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
>>>> +			continue;
>>>> +
>>>> +		/* Not the highest priority? */
>>>> +		if (lr_prio >= priority)
>>>> +			continue;
>>>> +
>>>> +		/* This is a candidate */
>>>> +		priority = lr_prio;
>>>> +		*lr_val = val;
>>>> +		lr = i;
>>>> +	}
>>>> +
>>>> +	if (lr == -1)
>>>> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
>>>> +
>>>> +	return lr;
>>>> +}
>>>> +
>>>> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>>> +{
>>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
>>> s/nr_aprs/nr_apr_regs ?
>>
>> Sure, I can do that if that helps.
>>
>>>> +	u32 hap = 0;
>>>> +	int i;
>>>> +
>>>> +	for (i = 0; i < nr_aprs; i++) {
>>>> +		u32 val;
>>>> +
>>>> +		val  = __vgic_v3_read_ap0rn(i);
>>>> +		val |= __vgic_v3_read_ap1rn(i);
>>>> +		if (val)
>>>> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
>>> here don't we need to shift by the actual number of subpriority bits?
>>> isn't nr_pre_bits the max implemented preemption bits but not
>>> necessarily the actual chosen number set by bpr?
>>
>> Hmmm. I don't think that works. If you did that, you could end-up in a
>> bizarre situation where you can completely miss the current active
>> priority. Try for example:
>>
>> 	nr_pre_bits=5
>> 	set BPR1=3 (5 preemption bits)
>> 	read IAR, interrupt priority = 0x10, set bit 2 in AP1R0
>> 	set BPR=4 (4 preemption bits)
>>
>> With this setting, you've changed the active priority from being 0x10
>> (with BPR1=3) to being 8. This is wrong, as this should be an invariant.
>>
>> The only way to avoid this unfortunate state of affair is to always
>> normalize the active priority to always be stored as if BPR had its
>> smallest possible value (which happens to be nr_pre_bits).
> 
> Hum ok. I get your point now and that looks correct to me too. Maybe a
> small comment for subsequent readers would avoid the same question.

Definitely. This whole thing gives me headaches each time I have to look
at it again.

>>>> +
>>>> +		hap += 32;
>>>> +	}
>>>> +
>>>> +	return GICv3_IDLE_PRIORITY;
>>>> +}
>>>> +
>>>>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>>>>  {
>>>>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>>>> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>>>>  	return bpr;
>>>>  }
>>>>  
>>> Would be nice to have a short doc comment.
>>> I understand this zeros the subpriority field in the priority value, is
>>> it correct? pseudocode PriorityGroup()?
>>
>> Yes, I should probably add some references to the pseudocode.
>>
>>>> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
>>>> +{
>>>> +	unsigned int bpr;
>>>> +
>>>> +	if (!grp)
>>>> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
>>>> +	else
>>>> +		bpr = __vgic_v3_get_bpr1(vmcr);
>>>> +
>>>> +	return pri & (GENMASK(7, 0) << bpr);
>>>  & GENMASK(7, bpr)?
>>
>> Not sure about that. If grp==0, bpr can range from 1 to 8. If it is 8,
>> what is the meaning of GENMASK(7,8)?
> 
> OK forget it ;-)
>>
>>>> +}
>>>> +
>>>> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>>> +{
>>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>>> +	u8 hap = pre >> (8 - nr_pre_bits);
>>> Could you add a comment about what is hap. I tend to think it is the
>>> group priority but then I don't get why we don't shift by 8 -bpr
>>
>> "hap" stands for Highest Active Priority. And for the reasons describer
>> above, we need to normalize it, irrespective of the BPR.
>>
>> Does it make sense?
> 
> yes it does.
> 
> So Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks Eric!

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

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

* [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler
@ 2017-05-23  9:26           ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-23  9:26 UTC (permalink / raw)
  To: linux-arm-kernel

On 23/05/17 08:22, Auger Eric wrote:
> Hi Marc,
> 
> On 22/05/2017 19:52, Marc Zyngier wrote:
>> Hi Eric,
>>
>> On 18/05/17 08:41, Auger Eric wrote:
>>> Hi Marc,
>>>
>>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>>> Add a handler for reading the guest's view of the ICC_IAR1_EL1
>>>> register. This involves finding the highest priority Group-1
>>>> interrupt, checking against both PMR and the active group
>>>> priority, activating the interrupt and setting the group
>>>> priority as active.
>>>>
>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>> ---
>>>>  include/linux/irqchip/arm-gic-v3.h |   1 +
>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 134 +++++++++++++++++++++++++++++++++++++
>>>>  2 files changed, 135 insertions(+)
>>>>
>>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>>> index 97cbca19430d..7610ea4e8337 100644
>>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>>> @@ -391,6 +391,7 @@
>>>>  #define ICH_LR_PHYS_ID_SHIFT		32
>>>>  #define ICH_LR_PHYS_ID_MASK		(0x3ffULL << ICH_LR_PHYS_ID_SHIFT)
>>>>  #define ICH_LR_PRIORITY_SHIFT		48
>>>> +#define ICH_LR_PRIORITY_MASK		(0xffULL << ICH_LR_PRIORITY_SHIFT)
>>>>  
>>>>  /* These are for GICv2 emulation only */
>>>>  #define GICH_LR_VIRTUALID		(0x3ffUL << 0)
>>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>> index 473ef22508e6..49aad1de3ac8 100644
>>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>> @@ -375,6 +375,77 @@ void __hyp_text __vgic_v3_write_vmcr(u32 vmcr)
>>>>  
>>>>  #ifdef CONFIG_ARM64
>>>>  
>>>> +static int __hyp_text __vgic_v3_get_group(struct kvm_vcpu *vcpu)
>>>> +{
>>>> +	u32 esr = kvm_vcpu_get_hsr(vcpu);
>>>> +	u8 crm = (esr & ESR_ELx_SYS64_ISS_CRM_MASK) >> ESR_ELx_SYS64_ISS_CRM_SHIFT;
>>>> +
>>>> +	return crm != 8;
>>>> +}
>>>> +
>>>> +#define GICv3_IDLE_PRIORITY	0xff
>>>> +
>>>> +static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>> +						    u32 vmcr,
>>>> +						    u64 *lr_val)
>>>> +{
>>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>>> +	u8 priority = GICv3_IDLE_PRIORITY;
>>>> +	int i, lr = -1;
>>>> +
>>>> +	for (i = 0; i < used_lrs; i++) {
>>>> +		u64 val = __gic_v3_get_lr(i);
>>>> +		u8 lr_prio = (val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>>>> +
>>>> +		/* Not pending in the state? */
>>>> +		if ((val & ICH_LR_STATE) != ICH_LR_PENDING_BIT)
>>>> +			continue;
>>>> +
>>>> +		/* Group-0 interrupt, but Group-0 disabled? */
>>>> +		if (!(val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG0_MASK))
>>>> +			continue;
>>>> +
>>>> +		/* Group-1 interrupt, but Group-1 disabled? */
>>>> +		if ((val & ICH_LR_GROUP) && !(vmcr & ICH_VMCR_ENG1_MASK))
>>>> +			continue;
>>>> +
>>>> +		/* Not the highest priority? */
>>>> +		if (lr_prio >= priority)
>>>> +			continue;
>>>> +
>>>> +		/* This is a candidate */
>>>> +		priority = lr_prio;
>>>> +		*lr_val = val;
>>>> +		lr = i;
>>>> +	}
>>>> +
>>>> +	if (lr == -1)
>>>> +		*lr_val = ICC_IAR1_EL1_SPURIOUS;
>>>> +
>>>> +	return lr;
>>>> +}
>>>> +
>>>> +static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>>> +{
>>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
>>> s/nr_aprs/nr_apr_regs ?
>>
>> Sure, I can do that if that helps.
>>
>>>> +	u32 hap = 0;
>>>> +	int i;
>>>> +
>>>> +	for (i = 0; i < nr_aprs; i++) {
>>>> +		u32 val;
>>>> +
>>>> +		val  = __vgic_v3_read_ap0rn(i);
>>>> +		val |= __vgic_v3_read_ap1rn(i);
>>>> +		if (val)
>>>> +			return (hap + __ffs(val)) << (8 - nr_pre_bits);
>>> here don't we need to shift by the actual number of subpriority bits?
>>> isn't nr_pre_bits the max implemented preemption bits but not
>>> necessarily the actual chosen number set by bpr?
>>
>> Hmmm. I don't think that works. If you did that, you could end-up in a
>> bizarre situation where you can completely miss the current active
>> priority. Try for example:
>>
>> 	nr_pre_bits=5
>> 	set BPR1=3 (5 preemption bits)
>> 	read IAR, interrupt priority = 0x10, set bit 2 in AP1R0
>> 	set BPR=4 (4 preemption bits)
>>
>> With this setting, you've changed the active priority from being 0x10
>> (with BPR1=3) to being 8. This is wrong, as this should be an invariant.
>>
>> The only way to avoid this unfortunate state of affair is to always
>> normalize the active priority to always be stored as if BPR had its
>> smallest possible value (which happens to be nr_pre_bits).
> 
> Hum ok. I get your point now and that looks correct to me too. Maybe a
> small comment for subsequent readers would avoid the same question.

Definitely. This whole thing gives me headaches each time I have to look
at it again.

>>>> +
>>>> +		hap += 32;
>>>> +	}
>>>> +
>>>> +	return GICv3_IDLE_PRIORITY;
>>>> +}
>>>> +
>>>>  static unsigned int __hyp_text __vgic_v3_get_bpr0(u32 vmcr)
>>>>  {
>>>>  	return (vmcr & ICH_VMCR_BPR0_MASK) >> ICH_VMCR_BPR0_SHIFT;
>>>> @@ -395,6 +466,66 @@ static unsigned int __hyp_text __vgic_v3_get_bpr1(u32 vmcr)
>>>>  	return bpr;
>>>>  }
>>>>  
>>> Would be nice to have a short doc comment.
>>> I understand this zeros the subpriority field in the priority value, is
>>> it correct? pseudocode PriorityGroup()?
>>
>> Yes, I should probably add some references to the pseudocode.
>>
>>>> +static u8 __hyp_text __vgic_v3_pri_to_pre(u8 pri, u32 vmcr, int grp)
>>>> +{
>>>> +	unsigned int bpr;
>>>> +
>>>> +	if (!grp)
>>>> +		bpr = __vgic_v3_get_bpr0(vmcr) + 1;
>>>> +	else
>>>> +		bpr = __vgic_v3_get_bpr1(vmcr);
>>>> +
>>>> +	return pri & (GENMASK(7, 0) << bpr);
>>>  & GENMASK(7, bpr)?
>>
>> Not sure about that. If grp==0, bpr can range from 1 to 8. If it is 8,
>> what is the meaning of GENMASK(7,8)?
> 
> OK forget it ;-)
>>
>>>> +}
>>>> +
>>>> +static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>>> +{
>>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>>> +	u8 hap = pre >> (8 - nr_pre_bits);
>>> Could you add a comment about what is hap. I tend to think it is the
>>> group priority but then I don't get why we don't shift by 8 -bpr
>>
>> "hap" stands for Highest Active Priority. And for the reasons describer
>> above, we need to normalize it, irrespective of the BPR.
>>
>> Does it make sense?
> 
> yes it does.
> 
> So Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks Eric!

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

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

* Re: [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  7:48     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  7:48 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

H Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
> registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 95 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 15c142ce991c..aad46b8eea5e 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -180,6 +180,7 @@
>  
>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>  
> +#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index a76351b3ad66..b6803989da1f 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
>  	__vgic_v3_write_vmcr(vmcr);
>  }
>  
> +static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
Shouldn't you test somewhere that n is correct given the number of
implemented priority bits
> +{
> +	u32 val;
> +
> +	if (!__vgic_v3_get_group(vcpu))
I don't really get how an access to AP1Rn can end up in AP0Rn. I am not
able to find any related description in the spec?

Thanks

Eric
> +		val = __vgic_v3_read_ap0rn(n);

> +	else
> +		val = __vgic_v3_read_ap1rn(n);
> +
> +	vcpu_set_reg(vcpu, rt, val);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
> +{
> +	u32 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (!__vgic_v3_get_group(vcpu))
> +		__vgic_v3_write_ap0rn(val, n);
> +	else
> +		__vgic_v3_write_ap1rn(val, n);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 0);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 1);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 2);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 3);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 0);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 1);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 2);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 3);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_bpr1;
>  		break;
> +	case SYS_ICC_AP1Rn_EL1(0):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr0;
> +		else
> +			fn = __vgic_v3_write_apxr0;
> +		break;
> +	case SYS_ICC_AP1Rn_EL1(1):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr1;
> +		else
> +			fn = __vgic_v3_write_apxr1;
> +		break;
> +	case SYS_ICC_AP1Rn_EL1(2):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr2;
> +		else
> +			fn = __vgic_v3_write_apxr2;
> +		break;
> +	case SYS_ICC_AP1Rn_EL1(3):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr3;
> +		else
> +			fn = __vgic_v3_write_apxr3;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
@ 2017-05-30  7:48     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  7:48 UTC (permalink / raw)
  To: linux-arm-kernel

H Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
> registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 95 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 15c142ce991c..aad46b8eea5e 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -180,6 +180,7 @@
>  
>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>  
> +#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index a76351b3ad66..b6803989da1f 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
>  	__vgic_v3_write_vmcr(vmcr);
>  }
>  
> +static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
Shouldn't you test somewhere that n is correct given the number of
implemented priority bits
> +{
> +	u32 val;
> +
> +	if (!__vgic_v3_get_group(vcpu))
I don't really get how an access to AP1Rn can end up in AP0Rn. I am not
able to find any related description in the spec?

Thanks

Eric
> +		val = __vgic_v3_read_ap0rn(n);

> +	else
> +		val = __vgic_v3_read_ap1rn(n);
> +
> +	vcpu_set_reg(vcpu, rt, val);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
> +{
> +	u32 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (!__vgic_v3_get_group(vcpu))
> +		__vgic_v3_write_ap0rn(val, n);
> +	else
> +		__vgic_v3_write_ap1rn(val, n);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 0);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 1);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 2);
> +}
> +
> +static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	__vgic_v3_read_apxrn(vcpu, rt, 3);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 0);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 1);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 2);
> +}
> +
> +static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
> +					     u32 vmcr, int rt)
> +{
> +	__vgic_v3_write_apxrn(vcpu, rt, 3);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_bpr1;
>  		break;
> +	case SYS_ICC_AP1Rn_EL1(0):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr0;
> +		else
> +			fn = __vgic_v3_write_apxr0;
> +		break;
> +	case SYS_ICC_AP1Rn_EL1(1):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr1;
> +		else
> +			fn = __vgic_v3_write_apxr1;
> +		break;
> +	case SYS_ICC_AP1Rn_EL1(2):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr2;
> +		else
> +			fn = __vgic_v3_write_apxr2;
> +		break;
> +	case SYS_ICC_AP1Rn_EL1(3):
> +		if (is_read)
> +			fn = __vgic_v3_read_apxr3;
> +		else
> +			fn = __vgic_v3_write_apxr3;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  7:48     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  7:48 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
> register. This involves dropping the priority of the interrupt,
> and deactivating it if required (EOImode == 0).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |   2 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 121 insertions(+)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 7610ea4e8337..c56d9bc2c904 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,8 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_EOIcount_SHIFT		27
> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>  
>  #define ICH_VMCR_CBPR_SHIFT		4
>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 49aad1de3ac8..a76351b3ad66 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>  	return lr;
>  }
>  
> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
> +					       int intid, u64 *lr_val)
> +{
> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> +	int i;
> +
> +	for (i = 0; i < used_lrs; i++) {
> +		u64 val = __gic_v3_get_lr(i);
> +
> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
> +		    (val & ICH_LR_ACTIVE_BIT)) {
I guess it is safe because we don't have yet virtual interrupts directly
mapped to phys IRQs, besides timer one?
> +			*lr_val = val;
> +			return i;
> +		}
> +	}
> +
> +	*lr_val = ICC_IAR1_EL1_SPURIOUS;
> +	return -1;
> +}
> +
>  static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>  {
>  	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> @@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>  	__vgic_v3_write_ap1rn(val | bit, apr);
>  }
>  
> +static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
> +{
> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
may be worth to introduce a macro to compute the number of APRn regs.
This may be more understandable.
> +	u32 hap = 0;
> +	int i;
> +
> +	for (i = 0; i < nr_aprs; i++) {
> +		u32 ap0, ap1;
> +		int c0, c1;
> +
> +		ap0 = __vgic_v3_read_ap0rn(i);
> +		ap1 = __vgic_v3_read_ap1rn(i);
> +		if (!ap0 && !ap1) {
> +			hap += 32;
> +			continue;
> +		}
> +
> +		c0 = ap0 ? __ffs(ap0) : 32;
> +		c1 = ap1 ? __ffs(ap1) : 32;
> +
> +		/* Always clear the LSB, which is the highest priority */
> +		if (c0 < c1) {
> +			ap0 &= ap0 - 1;
> +			__vgic_v3_write_ap0rn(ap0, i);
> +			hap += c0;
> +		} else {
> +			ap1 &= ap1 - 1;
> +			__vgic_v3_write_ap1rn(ap1, i);
> +			hap += c1;
> +		}
> +
> +		return hap << (8 - nr_pre_bits);
> +	}
> +
> +	return GICv3_IDLE_PRIORITY;
> +}
> +
>  static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u64 lr_val;
> @@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
>  	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
>  }
>  
> +static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
> +{
> +	lr_val &= ~ICH_LR_ACTIVE_BIT;
> +	if (lr_val & ICH_LR_HW) {
> +		u32 pid;
nit: insert a line
> +		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
> +		gic_write_dir(pid);
> +	}
> +
> +	__gic_v3_set_lr(lr_val, lr);
> +}
> +
> +static void __hyp_text __vgic_v3_bump_eoicount(void)
> +{
> +	u32 hcr;
> +
> +	hcr = read_gicreg(ICH_HCR_EL2);
> +	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
> +	write_gicreg(hcr, ICH_HCR_EL2);
> +}
> +
> +static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u32 vid = vcpu_get_reg(vcpu, rt);
> +	u64 lr_val;
> +	u8 lr_prio, act_prio;
> +	int lr, grp;
> +
> +	grp = __vgic_v3_get_group(vcpu);
> +
> +	/* Drop priority in any case */
> +	act_prio = __vgic_v3_clear_highest_active_priority();
> +
> +	/* If EOIing an LPI, no deactivate to be performed */
> +	if (vid >= VGIC_MIN_LPI)
> +		return;
> +
> +	/* EOImode == 1, nothing to be done here */
> +	if (vmcr & ICH_VMCR_EOIM_MASK)
> +		return;
> +
> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
> +	if (lr == -1) {
> +		__vgic_v3_bump_eoicount();
> +		return;
> +	}
> +
> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
> +
> +	/* If priorities or group do not match, the guest has fscked-up. */
> +	if (grp != !!(lr_val & ICH_LR_GROUP) ||
> +	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
> +		return;
> +
> +	/* Let's now perform the deactivation */
> +	__vgic_v3_clear_active_lr(lr, lr_val);
> +}
> +
>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
> @@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_IAR1_EL1:
>  		fn = __vgic_v3_read_iar;
>  		break;
> +	case SYS_ICC_EOIR1_EL1:
> +		fn = __vgic_v3_write_eoir;
> +		break;
>  	case SYS_ICC_GRPEN1_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_igrpen1;

Looks good to me

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric

> 

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-30  7:48     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  7:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
> register. This involves dropping the priority of the interrupt,
> and deactivating it if required (EOImode == 0).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h |   2 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>  2 files changed, 121 insertions(+)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 7610ea4e8337..c56d9bc2c904 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,8 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_EOIcount_SHIFT		27
> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>  
>  #define ICH_VMCR_CBPR_SHIFT		4
>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 49aad1de3ac8..a76351b3ad66 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>  	return lr;
>  }
>  
> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
> +					       int intid, u64 *lr_val)
> +{
> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> +	int i;
> +
> +	for (i = 0; i < used_lrs; i++) {
> +		u64 val = __gic_v3_get_lr(i);
> +
> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
> +		    (val & ICH_LR_ACTIVE_BIT)) {
I guess it is safe because we don't have yet virtual interrupts directly
mapped to phys IRQs, besides timer one?
> +			*lr_val = val;
> +			return i;
> +		}
> +	}
> +
> +	*lr_val = ICC_IAR1_EL1_SPURIOUS;
> +	return -1;
> +}
> +
>  static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>  {
>  	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> @@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>  	__vgic_v3_write_ap1rn(val | bit, apr);
>  }
>  
> +static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
> +{
> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
may be worth to introduce a macro to compute the number of APRn regs.
This may be more understandable.
> +	u32 hap = 0;
> +	int i;
> +
> +	for (i = 0; i < nr_aprs; i++) {
> +		u32 ap0, ap1;
> +		int c0, c1;
> +
> +		ap0 = __vgic_v3_read_ap0rn(i);
> +		ap1 = __vgic_v3_read_ap1rn(i);
> +		if (!ap0 && !ap1) {
> +			hap += 32;
> +			continue;
> +		}
> +
> +		c0 = ap0 ? __ffs(ap0) : 32;
> +		c1 = ap1 ? __ffs(ap1) : 32;
> +
> +		/* Always clear the LSB, which is the highest priority */
> +		if (c0 < c1) {
> +			ap0 &= ap0 - 1;
> +			__vgic_v3_write_ap0rn(ap0, i);
> +			hap += c0;
> +		} else {
> +			ap1 &= ap1 - 1;
> +			__vgic_v3_write_ap1rn(ap1, i);
> +			hap += c1;
> +		}
> +
> +		return hap << (8 - nr_pre_bits);
> +	}
> +
> +	return GICv3_IDLE_PRIORITY;
> +}
> +
>  static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u64 lr_val;
> @@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
>  	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
>  }
>  
> +static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
> +{
> +	lr_val &= ~ICH_LR_ACTIVE_BIT;
> +	if (lr_val & ICH_LR_HW) {
> +		u32 pid;
nit: insert a line
> +		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
> +		gic_write_dir(pid);
> +	}
> +
> +	__gic_v3_set_lr(lr_val, lr);
> +}
> +
> +static void __hyp_text __vgic_v3_bump_eoicount(void)
> +{
> +	u32 hcr;
> +
> +	hcr = read_gicreg(ICH_HCR_EL2);
> +	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
> +	write_gicreg(hcr, ICH_HCR_EL2);
> +}
> +
> +static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u32 vid = vcpu_get_reg(vcpu, rt);
> +	u64 lr_val;
> +	u8 lr_prio, act_prio;
> +	int lr, grp;
> +
> +	grp = __vgic_v3_get_group(vcpu);
> +
> +	/* Drop priority in any case */
> +	act_prio = __vgic_v3_clear_highest_active_priority();
> +
> +	/* If EOIing an LPI, no deactivate to be performed */
> +	if (vid >= VGIC_MIN_LPI)
> +		return;
> +
> +	/* EOImode == 1, nothing to be done here */
> +	if (vmcr & ICH_VMCR_EOIM_MASK)
> +		return;
> +
> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
> +	if (lr == -1) {
> +		__vgic_v3_bump_eoicount();
> +		return;
> +	}
> +
> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
> +
> +	/* If priorities or group do not match, the guest has fscked-up. */
> +	if (grp != !!(lr_val & ICH_LR_GROUP) ||
> +	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
> +		return;
> +
> +	/* Let's now perform the deactivation */
> +	__vgic_v3_clear_active_lr(lr, lr_val);
> +}
> +
>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
> @@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_IAR1_EL1:
>  		fn = __vgic_v3_read_iar;
>  		break;
> +	case SYS_ICC_EOIR1_EL1:
> +		fn = __vgic_v3_write_eoir;
> +		break;
>  	case SYS_ICC_GRPEN1_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_igrpen1;

Looks good to me

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric

> 

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

* Re: [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
  2017-05-30  7:48     ` Auger Eric
@ 2017-05-30  8:02       ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  8:02 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc,

On 30/05/2017 09:48, Auger Eric wrote:
> H Marc,
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
>> registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm64/include/asm/sysreg.h |  1 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 95 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
>> index 15c142ce991c..aad46b8eea5e 100644
>> --- a/arch/arm64/include/asm/sysreg.h
>> +++ b/arch/arm64/include/asm/sysreg.h
>> @@ -180,6 +180,7 @@
>>  
>>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>>  
>> +#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index a76351b3ad66..b6803989da1f 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
>>  	__vgic_v3_write_vmcr(vmcr);
>>  }
>>  
>> +static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
> Shouldn't you test somewhere that n is correct given the number of
> implemented priority bits
>> +{
>> +	u32 val;
>> +
>> +	if (!__vgic_v3_get_group(vcpu))
> I don't really get how an access to AP1Rn can end up in AP0Rn. I am not
> able to find any related description in the spec?
Forget that one. This is simply a generic helper and an access from NS
world will access the AP1Rn reg.

so besides the comment on "n" check,

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> Thanks
> 
> Eric
>> +		val = __vgic_v3_read_ap0rn(n);
> 
>> +	else
>> +		val = __vgic_v3_read_ap1rn(n);
>> +
>> +	vcpu_set_reg(vcpu, rt, val);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
>> +{
>> +	u32 val = vcpu_get_reg(vcpu, rt);
>> +
>> +	if (!__vgic_v3_get_group(vcpu))
>> +		__vgic_v3_write_ap0rn(val, n);
>> +	else
>> +		__vgic_v3_write_ap1rn(val, n);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 0);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 1);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 2);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 3);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 0);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 1);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 2);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 3);
>> +}
>> +
>>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>  {
>>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
>> @@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>  		else
>>  			fn = __vgic_v3_write_bpr1;
>>  		break;
>> +	case SYS_ICC_AP1Rn_EL1(0):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr0;
>> +		else
>> +			fn = __vgic_v3_write_apxr0;
>> +		break;
>> +	case SYS_ICC_AP1Rn_EL1(1):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr1;
>> +		else
>> +			fn = __vgic_v3_write_apxr1;
>> +		break;
>> +	case SYS_ICC_AP1Rn_EL1(2):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr2;
>> +		else
>> +			fn = __vgic_v3_write_apxr2;
>> +		break;
>> +	case SYS_ICC_AP1Rn_EL1(3):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr3;
>> +		else
>> +			fn = __vgic_v3_write_apxr3;
>> +		break;
>>  	default:
>>  		return 0;
>>  	}
>>

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

* [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
@ 2017-05-30  8:02       ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  8:02 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 30/05/2017 09:48, Auger Eric wrote:
> H Marc,
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
>> registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  arch/arm64/include/asm/sysreg.h |  1 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
>>  2 files changed, 95 insertions(+)
>>
>> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
>> index 15c142ce991c..aad46b8eea5e 100644
>> --- a/arch/arm64/include/asm/sysreg.h
>> +++ b/arch/arm64/include/asm/sysreg.h
>> @@ -180,6 +180,7 @@
>>  
>>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>>  
>> +#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index a76351b3ad66..b6803989da1f 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
>>  	__vgic_v3_write_vmcr(vmcr);
>>  }
>>  
>> +static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
> Shouldn't you test somewhere that n is correct given the number of
> implemented priority bits
>> +{
>> +	u32 val;
>> +
>> +	if (!__vgic_v3_get_group(vcpu))
> I don't really get how an access to AP1Rn can end up in AP0Rn. I am not
> able to find any related description in the spec?
Forget that one. This is simply a generic helper and an access from NS
world will access the AP1Rn reg.

so besides the comment on "n" check,

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> 
> Thanks
> 
> Eric
>> +		val = __vgic_v3_read_ap0rn(n);
> 
>> +	else
>> +		val = __vgic_v3_read_ap1rn(n);
>> +
>> +	vcpu_set_reg(vcpu, rt, val);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
>> +{
>> +	u32 val = vcpu_get_reg(vcpu, rt);
>> +
>> +	if (!__vgic_v3_get_group(vcpu))
>> +		__vgic_v3_write_ap0rn(val, n);
>> +	else
>> +		__vgic_v3_write_ap1rn(val, n);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr0(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 0);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr1(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 1);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr2(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 2);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_read_apxr3(struct kvm_vcpu *vcpu,
>> +					    u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_read_apxrn(vcpu, rt, 3);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr0(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 0);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr1(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 1);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr2(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 2);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
>> +					     u32 vmcr, int rt)
>> +{
>> +	__vgic_v3_write_apxrn(vcpu, rt, 3);
>> +}
>> +
>>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>  {
>>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
>> @@ -722,6 +792,30 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>  		else
>>  			fn = __vgic_v3_write_bpr1;
>>  		break;
>> +	case SYS_ICC_AP1Rn_EL1(0):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr0;
>> +		else
>> +			fn = __vgic_v3_write_apxr0;
>> +		break;
>> +	case SYS_ICC_AP1Rn_EL1(1):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr1;
>> +		else
>> +			fn = __vgic_v3_write_apxr1;
>> +		break;
>> +	case SYS_ICC_AP1Rn_EL1(2):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr2;
>> +		else
>> +			fn = __vgic_v3_write_apxr2;
>> +		break;
>> +	case SYS_ICC_AP1Rn_EL1(3):
>> +		if (is_read)
>> +			fn = __vgic_v3_read_apxr3;
>> +		else
>> +			fn = __vgic_v3_write_apxr3;
>> +		break;
>>  	default:
>>  		return 0;
>>  	}
>>

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

* Re: [PATCH 16/31] KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  8:05     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  8:05 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,
On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading the guest's view of the ICV_HPPIR1_EL1
> register. This is a simple parsing of the available LRs, extracting the
> highest available interrupt.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index aad46b8eea5e..bd000686194a 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -185,6 +185,7 @@
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>  #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
> +#define SYS_ICC_HPPIR1_EL1		sys_reg(3, 0, 12, 12, 2)
>  #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
>  #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
>  #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index b6803989da1f..a521e105ade1 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -754,6 +754,26 @@ static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
>  	__vgic_v3_write_apxrn(vcpu, rt, 3);
>  }
>  
> +static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	u64 lr_val;
> +	int lr, lr_grp, grp;
> +
> +	grp = __vgic_v3_get_group(vcpu);
> +
> +	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
> +	if (lr == -1)
> +		goto spurious;
> +
> +	lr_grp = !!(lr_val & ICH_LR_GROUP);
> +	if (lr_grp != grp)
> +		lr_val = ICC_IAR1_EL1_SPURIOUS;
> +
> +spurious:
> +	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -816,6 +836,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_apxr3;
>  		break;
> +	case SYS_ICC_HPPIR1_EL1:
> +		fn = __vgic_v3_read_hppir;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 16/31] KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler
@ 2017-05-30  8:05     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  8:05 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,
On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading the guest's view of the ICV_HPPIR1_EL1
> register. This is a simple parsing of the available LRs, extracting the
> highest available interrupt.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index aad46b8eea5e..bd000686194a 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -185,6 +185,7 @@
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>  #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
> +#define SYS_ICC_HPPIR1_EL1		sys_reg(3, 0, 12, 12, 2)
>  #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
>  #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
>  #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index b6803989da1f..a521e105ade1 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -754,6 +754,26 @@ static void __hyp_text __vgic_v3_write_apxr3(struct kvm_vcpu *vcpu,
>  	__vgic_v3_write_apxrn(vcpu, rt, 3);
>  }
>  
> +static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	u64 lr_val;
> +	int lr, lr_grp, grp;
> +
> +	grp = __vgic_v3_get_group(vcpu);
> +
> +	lr = __vgic_v3_highest_priority_lr(vcpu, vmcr, &lr_val);
> +	if (lr == -1)
> +		goto spurious;
> +
> +	lr_grp = !!(lr_val & ICH_LR_GROUP);
> +	if (lr_grp != grp)
> +		lr_val = ICC_IAR1_EL1_SPURIOUS;
> +
> +spurious:
> +	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -816,6 +836,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_apxr3;
>  		break;
> +	case SYS_ICC_HPPIR1_EL1:
> +		fn = __vgic_v3_read_hppir;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  9:07     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:07 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> In order to be able to trap Group-1 GICv3 system registers, we need to
> set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
before, conditionally
> done after having restored the guest's state, and cleared on exit.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h | 1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
>  virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
>  3 files changed, 12 insertions(+)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index c56d9bc2c904..a1739843343e 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,7 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_TALL1			(1 << 12)
>  #define ICH_HCR_EOIcount_SHIFT		27
>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>  
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index a521e105ade1..a27671b1e9af 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -257,6 +257,9 @@ 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))
> +			write_gicreg(0, ICH_HCR_EL2);
Not directly related to this patch but this is not obvious to me why we
reset the ICH_HCR_EL2 only when used_lrs != 0.
> +
>  		cpu_if->vgic_elrsr = 0xffff;
>  		cpu_if->vgic_ap0r[0] = 0;
>  		cpu_if->vgic_ap0r[1] = 0;
> @@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>  
>  		for (i = 0; i < used_lrs; i++)
>  			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
> +	} else {
> +		/* Always write ICH_HCR_EL2 to enable trapping */
"always" is a bit weird as this is conditional
> +		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
> +			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
and same question here. Why don't we always restore the ICH_HCR_EL2.
Assuming when exiting the guest the vCPU I/F was enabled and used_lrs=0,
when restoring don't we leave the vCPU I/F disabled? I must miss
something but I don't find who is re-enabling the vCPU I/F in that case?
>  	}
>  
>  	/*
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 063526443781..547b8374fb64 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -21,6 +21,8 @@
>  
>  #include "vgic.h"
>  
> +static bool group1_trap;
> +
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> @@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  
>  	/* Get the show on the road... */
>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
> +	if (group1_trap)
I don't remember the rationale behind using the bool here and using
static_branch_unlikely in the other cases.

May be good to squash the next patch to understand how group1_trap is set.

Thanks

Eric
> +		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
>  }
>  
>  /* check for overlapping regions and for regions crossing the end of memory */
> 

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

* [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
@ 2017-05-30  9:07     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:07 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 03/05/2017 12:45, Marc Zyngier wrote:
> In order to be able to trap Group-1 GICv3 system registers, we need to
> set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
before, conditionally
> done after having restored the guest's state, and cleared on exit.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  include/linux/irqchip/arm-gic-v3.h | 1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
>  virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
>  3 files changed, 12 insertions(+)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index c56d9bc2c904..a1739843343e 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,7 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_TALL1			(1 << 12)
>  #define ICH_HCR_EOIcount_SHIFT		27
>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>  
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index a521e105ade1..a27671b1e9af 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -257,6 +257,9 @@ 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))
> +			write_gicreg(0, ICH_HCR_EL2);
Not directly related to this patch but this is not obvious to me why we
reset the ICH_HCR_EL2 only when used_lrs != 0.
> +
>  		cpu_if->vgic_elrsr = 0xffff;
>  		cpu_if->vgic_ap0r[0] = 0;
>  		cpu_if->vgic_ap0r[1] = 0;
> @@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>  
>  		for (i = 0; i < used_lrs; i++)
>  			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
> +	} else {
> +		/* Always write ICH_HCR_EL2 to enable trapping */
"always" is a bit weird as this is conditional
> +		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
> +			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
and same question here. Why don't we always restore the ICH_HCR_EL2.
Assuming when exiting the guest the vCPU I/F was enabled and used_lrs=0,
when restoring don't we leave the vCPU I/F disabled? I must miss
something but I don't find who is re-enabling the vCPU I/F in that case?
>  	}
>  
>  	/*
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 063526443781..547b8374fb64 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -21,6 +21,8 @@
>  
>  #include "vgic.h"
>  
> +static bool group1_trap;
> +
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
> @@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  
>  	/* Get the show on the road... */
>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
> +	if (group1_trap)
I don't remember the rationale behind using the bool here and using
static_branch_unlikely in the other cases.

May be good to squash the next patch to understand how group1_trap is set.

Thanks

Eric
> +		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
>  }
>  
>  /* check for overlapping regions and for regions crossing the end of memory */
> 

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

* Re: [PATCH 19/31] KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  9:48     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,
On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_BPR0_EL1
> register, which is located in the ICH_VMCR_EL2.BPR0 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 36 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 37 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index bd000686194a..d20be0b28ca4 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -180,6 +180,7 @@
>  
>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>  
> +#define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
>  #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index a27671b1e9af..b21bb0c77ec2 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -666,11 +666,41 @@ static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr,
>  	__vgic_v3_write_vmcr(vmcr);
>  }
>  
> +static void __hyp_text __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr0(vmcr));
> +}
> +
>  static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
>  }
>  
> +static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +	u8 bpr_min = 7 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +
> +	/* Enforce BPR limiting */
> +	if (val < bpr_min)
> +		val = bpr_min;
> +
> +	val <<= ICH_VMCR_BPR0_SHIFT;
> +	val &= ICH_VMCR_BPR0_MASK;
> +	vmcr &= ~ICH_VMCR_BPR0_MASK;
> +	vmcr |= val;
> +
> +	if (vmcr & ICH_VMCR_CBPR_MASK) {
> +		val = __vgic_v3_get_bpr1(vmcr);
> +		val <<= ICH_VMCR_BPR1_SHIFT;
> +		val &= ICH_VMCR_BPR1_MASK;
> +		vmcr &= ~ICH_VMCR_BPR1_MASK;
> +		vmcr |= val;
> +	}
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u64 val = vcpu_get_reg(vcpu, rt);
> @@ -846,6 +876,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_HPPIR1_EL1:
>  		fn = __vgic_v3_read_hppir;
>  		break;
> +	case SYS_ICC_BPR0_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_bpr0;
> +		else
> +			fn = __vgic_v3_write_bpr0;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 19/31] KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler
@ 2017-05-30  9:48     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,
On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_BPR0_EL1
> register, which is located in the ICH_VMCR_EL2.BPR0 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 36 ++++++++++++++++++++++++++++++++++++
>  2 files changed, 37 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index bd000686194a..d20be0b28ca4 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -180,6 +180,7 @@
>  
>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>  
> +#define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
>  #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index a27671b1e9af..b21bb0c77ec2 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -666,11 +666,41 @@ static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr,
>  	__vgic_v3_write_vmcr(vmcr);
>  }
>  
> +static void __hyp_text __vgic_v3_read_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr0(vmcr));
> +}
> +
>  static void __hyp_text __vgic_v3_read_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, __vgic_v3_get_bpr1(vmcr));
>  }
>  
> +static void __hyp_text __vgic_v3_write_bpr0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +	u8 bpr_min = 7 - vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
> +
> +	/* Enforce BPR limiting */
> +	if (val < bpr_min)
> +		val = bpr_min;
> +
> +	val <<= ICH_VMCR_BPR0_SHIFT;
> +	val &= ICH_VMCR_BPR0_MASK;
> +	vmcr &= ~ICH_VMCR_BPR0_MASK;
> +	vmcr |= val;
> +
> +	if (vmcr & ICH_VMCR_CBPR_MASK) {
> +		val = __vgic_v3_get_bpr1(vmcr);
> +		val <<= ICH_VMCR_BPR1_SHIFT;
> +		val &= ICH_VMCR_BPR1_MASK;
> +		vmcr &= ~ICH_VMCR_BPR1_MASK;
> +		vmcr |= val;
> +	}
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u64 val = vcpu_get_reg(vcpu, rt);
> @@ -846,6 +876,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_HPPIR1_EL1:
>  		fn = __vgic_v3_read_hppir;
>  		break;
> +	case SYS_ICC_BPR0_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_bpr0;
> +		else
> +			fn = __vgic_v3_write_bpr0;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 21/31] KVM: arm64: vgic-v3: Add misc Group-0 handlers
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  9:48     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> A number of Group-0 registers can be handled by the same accessors
> as that of Group-1, so let's add the required system register encodings
> and catch them in the dispatching function.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/sysreg.h | 4 ++++
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 7 +++++++
>  2 files changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index ba93bc7ac8e4..9971c5c435a7 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -180,7 +180,11 @@
>  
>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>  
> +#define SYS_ICC_IAR0_EL1		sys_reg(3, 0, 12, 8, 0)
> +#define SYS_ICC_EOIR0_EL1		sys_reg(3, 0, 12, 8, 1)
> +#define SYS_ICC_HPPIR0_EL1		sys_reg(3, 0, 12, 8, 2)
>  #define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
> +#define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
>  #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 77d5d12389ec..9c639f57268b 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -848,9 +848,11 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
>  
>  	switch (sysreg) {
> +	case SYS_ICC_IAR0_EL1:
>  	case SYS_ICC_IAR1_EL1:
>  		fn = __vgic_v3_read_iar;
>  		break;
> +	case SYS_ICC_EOIR0_EL1:
>  	case SYS_ICC_EOIR1_EL1:
>  		fn = __vgic_v3_write_eoir;
>  		break;
> @@ -866,30 +868,35 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_bpr1;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(0):
>  	case SYS_ICC_AP1Rn_EL1(0):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr0;
>  		else
>  			fn = __vgic_v3_write_apxr0;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(1):
>  	case SYS_ICC_AP1Rn_EL1(1):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr1;
>  		else
>  			fn = __vgic_v3_write_apxr1;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(2):
>  	case SYS_ICC_AP1Rn_EL1(2):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr2;
>  		else
>  			fn = __vgic_v3_write_apxr2;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(3):
>  	case SYS_ICC_AP1Rn_EL1(3):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr3;
>  		else
>  			fn = __vgic_v3_write_apxr3;
>  		break;
> +	case SYS_ICC_HPPIR0_EL1:
>  	case SYS_ICC_HPPIR1_EL1:
>  		fn = __vgic_v3_read_hppir;
>  		break;
> 

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

* [PATCH 21/31] KVM: arm64: vgic-v3: Add misc Group-0 handlers
@ 2017-05-30  9:48     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> A number of Group-0 registers can be handled by the same accessors
> as that of Group-1, so let's add the required system register encodings
> and catch them in the dispatching function.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/sysreg.h | 4 ++++
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 7 +++++++
>  2 files changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index ba93bc7ac8e4..9971c5c435a7 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -180,7 +180,11 @@
>  
>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>  
> +#define SYS_ICC_IAR0_EL1		sys_reg(3, 0, 12, 8, 0)
> +#define SYS_ICC_EOIR0_EL1		sys_reg(3, 0, 12, 8, 1)
> +#define SYS_ICC_HPPIR0_EL1		sys_reg(3, 0, 12, 8, 2)
>  #define SYS_ICC_BPR0_EL1		sys_reg(3, 0, 12, 8, 3)
> +#define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
>  #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 77d5d12389ec..9c639f57268b 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -848,9 +848,11 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	is_read = (esr & ESR_ELx_SYS64_ISS_DIR_MASK) == ESR_ELx_SYS64_ISS_DIR_READ;
>  
>  	switch (sysreg) {
> +	case SYS_ICC_IAR0_EL1:
>  	case SYS_ICC_IAR1_EL1:
>  		fn = __vgic_v3_read_iar;
>  		break;
> +	case SYS_ICC_EOIR0_EL1:
>  	case SYS_ICC_EOIR1_EL1:
>  		fn = __vgic_v3_write_eoir;
>  		break;
> @@ -866,30 +868,35 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_bpr1;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(0):
>  	case SYS_ICC_AP1Rn_EL1(0):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr0;
>  		else
>  			fn = __vgic_v3_write_apxr0;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(1):
>  	case SYS_ICC_AP1Rn_EL1(1):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr1;
>  		else
>  			fn = __vgic_v3_write_apxr1;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(2):
>  	case SYS_ICC_AP1Rn_EL1(2):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr2;
>  		else
>  			fn = __vgic_v3_write_apxr2;
>  		break;
> +	case SYS_ICC_AP0Rn_EL1(3):
>  	case SYS_ICC_AP1Rn_EL1(3):
>  		if (is_read)
>  			fn = __vgic_v3_read_apxr3;
>  		else
>  			fn = __vgic_v3_write_apxr3;
>  		break;
> +	case SYS_ICC_HPPIR0_EL1:
>  	case SYS_ICC_HPPIR1_EL1:
>  		fn = __vgic_v3_read_hppir;
>  		break;
> 

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

* Re: [PATCH 20/31] KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  9:48     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_IGRPEN0_EL1
> register, which is located in the ICH_VMCR_EL2.VENG0 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index d20be0b28ca4..ba93bc7ac8e4 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -190,6 +190,7 @@
>  #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
>  #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
>  #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
> +#define SYS_ICC_GRPEN0_EL1		sys_reg(3, 0, 12, 12, 6)
>  #define SYS_ICC_GRPEN1_EL1		sys_reg(3, 0, 12, 12, 7)
>  
>  #define SYS_CONTEXTIDR_EL1		sys_reg(3, 0, 13, 0, 1)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index b21bb0c77ec2..77d5d12389ec 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -649,11 +649,28 @@ static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int
>  	__vgic_v3_clear_active_lr(lr, lr_val);
>  }
>  
> +static void __hyp_text __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK));
> +}
> +
>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
>  }
>  
> +static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (val & 1)
> +		vmcr |= ICH_VMCR_ENG0_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_ENG0_MASK;
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u64 val = vcpu_get_reg(vcpu, rt);
> @@ -876,6 +893,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_HPPIR1_EL1:
>  		fn = __vgic_v3_read_hppir;
>  		break;
> +	case SYS_ICC_GRPEN0_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_igrpen0;
> +		else
> +			fn = __vgic_v3_write_igrpen0;
> +		break;
>  	case SYS_ICC_BPR0_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_bpr0;
> 

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

* [PATCH 20/31] KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler
@ 2017-05-30  9:48     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_IGRPEN0_EL1
> register, which is located in the ICH_VMCR_EL2.VENG0 field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 23 +++++++++++++++++++++++
>  2 files changed, 24 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index d20be0b28ca4..ba93bc7ac8e4 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -190,6 +190,7 @@
>  #define SYS_ICC_BPR1_EL1		sys_reg(3, 0, 12, 12, 3)
>  #define SYS_ICC_CTLR_EL1		sys_reg(3, 0, 12, 12, 4)
>  #define SYS_ICC_SRE_EL1			sys_reg(3, 0, 12, 12, 5)
> +#define SYS_ICC_GRPEN0_EL1		sys_reg(3, 0, 12, 12, 6)
>  #define SYS_ICC_GRPEN1_EL1		sys_reg(3, 0, 12, 12, 7)
>  
>  #define SYS_CONTEXTIDR_EL1		sys_reg(3, 0, 13, 0, 1)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index b21bb0c77ec2..77d5d12389ec 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -649,11 +649,28 @@ static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int
>  	__vgic_v3_clear_active_lr(lr, lr_val);
>  }
>  
> +static void __hyp_text __vgic_v3_read_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG0_MASK));
> +}
> +
>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
>  }
>  
> +static void __hyp_text __vgic_v3_write_igrpen0(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
> +{
> +	u64 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (val & 1)
> +		vmcr |= ICH_VMCR_ENG0_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_ENG0_MASK;
> +
> +	__vgic_v3_write_vmcr(vmcr);
> +}
> +
>  static void __hyp_text __vgic_v3_write_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u64 val = vcpu_get_reg(vcpu, rt);
> @@ -876,6 +893,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_HPPIR1_EL1:
>  		fn = __vgic_v3_read_hppir;
>  		break;
> +	case SYS_ICC_GRPEN0_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_igrpen0;
> +		else
> +			fn = __vgic_v3_write_igrpen0;
> +		break;
>  	case SYS_ICC_BPR0_EL1:
>  		if (is_read)
>  			fn = __vgic_v3_read_bpr0;
> 

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

* Re: [PATCH 22/31] KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  9:48     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> In order to be able to trap Group-0 GICv3 system registers, we need to
> set ICH_HCR_EL2.TALL0 begore entering the guest. This is conditionnaly
> done after having restored the guest's state, and cleared on exit.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

> ---
>  include/linux/irqchip/arm-gic-v3.h | 1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 5 ++++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index a1739843343e..7fef09bcf7b1 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,7 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_TALL0			(1 << 11)
>  #define ICH_HCR_TALL1			(1 << 12)
>  #define ICH_HCR_EOIcount_SHIFT		27
>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 71ecf448ca49..812f179a6931 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -21,6 +21,7 @@
>  
>  #include "vgic.h"
>  
> +static bool group0_trap;
>  static bool group1_trap;
>  
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
> @@ -241,6 +242,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  
>  	/* Get the show on the road... */
>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
> +	if (group0_trap)
> +		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
Hum ok, now I get why you use the bool, sorry ;-)

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
>  	if (group1_trap)
>  		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
>  }
> @@ -381,7 +384,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	if (kvm_vgic_global_state.vcpu_base == 0)
>  		kvm_info("disabling GICv2 emulation\n");
>  
> -	if (group1_trap) {
> +	if (group0_trap || group1_trap) {
>  		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
>  	}
> 

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

* [PATCH 22/31] KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers
@ 2017-05-30  9:48     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:48 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> In order to be able to trap Group-0 GICv3 system registers, we need to
> set ICH_HCR_EL2.TALL0 begore entering the guest. This is conditionnaly
> done after having restored the guest's state, and cleared on exit.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

> ---
>  include/linux/irqchip/arm-gic-v3.h | 1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 5 ++++-
>  2 files changed, 5 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index a1739843343e..7fef09bcf7b1 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,7 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_TALL0			(1 << 11)
>  #define ICH_HCR_TALL1			(1 << 12)
>  #define ICH_HCR_EOIcount_SHIFT		27
>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 71ecf448ca49..812f179a6931 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -21,6 +21,7 @@
>  
>  #include "vgic.h"
>  
> +static bool group0_trap;
>  static bool group1_trap;
>  
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
> @@ -241,6 +242,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  
>  	/* Get the show on the road... */
>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
> +	if (group0_trap)
> +		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
Hum ok, now I get why you use the bool, sorry ;-)

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
>  	if (group1_trap)
>  		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
>  }
> @@ -381,7 +384,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	if (kvm_vgic_global_state.vcpu_base == 0)
>  		kvm_info("disabling GICv2 emulation\n");
>  
> -	if (group1_trap) {
> +	if (group0_trap || group1_trap) {
>  		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
>  	}
> 

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

* Re: [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30  9:56     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Now that we're able to safely handle common sysreg access, let's
> give the user the opportunity to enable it by passing a specific
> command-line option (vgic_v3.common_trap).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

What is the rationale behind trapping those common sysreg accesses. This
is not enabled by default for some erratas. Is it to complete the
trapping modality. May be worth to explain.

Besides

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  include/linux/irqchip/arm-gic-v3.h |  1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 11 ++++++++++-
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 7fef09bcf7b1..2692217ac667 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,7 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_TC			(1 << 10)
>  #define ICH_HCR_TALL0			(1 << 11)
>  #define ICH_HCR_TALL1			(1 << 12)
>  #define ICH_HCR_EOIcount_SHIFT		27
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 445e86c8b00c..717219ab58a2 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -23,6 +23,7 @@
>  
>  static bool group0_trap;
>  static bool group1_trap;
> +static bool common_trap;
>  
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
> @@ -246,6 +247,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
>  	if (group1_trap)
>  		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
> +	if (common_trap)
> +		vgic_v3->vgic_hcr |= ICH_HCR_TC;
>  }
>  
>  /* check for overlapping regions and for regions crossing the end of memory */
> @@ -339,6 +342,12 @@ static int __init early_group1_trap_cfg(char *buf)
>  }
>  early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
>  
> +static int __init early_common_trap_cfg(char *buf)
> +{
> +	return strtobool(buf, &common_trap);
> +}
> +early_param("vgic_v3.common_trap", early_common_trap_cfg);
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> @@ -397,7 +406,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	}
>  #endif
>  
> -	if (group0_trap || group1_trap) {
> +	if (group0_trap || group1_trap || common_trap) {
>  		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
>  	}
> 

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

* [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
@ 2017-05-30  9:56     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Now that we're able to safely handle common sysreg access, let's
> give the user the opportunity to enable it by passing a specific
> command-line option (vgic_v3.common_trap).
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

What is the rationale behind trapping those common sysreg accesses. This
is not enabled by default for some erratas. Is it to complete the
trapping modality. May be worth to explain.

Besides

Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  include/linux/irqchip/arm-gic-v3.h |  1 +
>  virt/kvm/arm/vgic/vgic-v3.c        | 11 ++++++++++-
>  2 files changed, 11 insertions(+), 1 deletion(-)
> 
> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> index 7fef09bcf7b1..2692217ac667 100644
> --- a/include/linux/irqchip/arm-gic-v3.h
> +++ b/include/linux/irqchip/arm-gic-v3.h
> @@ -403,6 +403,7 @@
>  
>  #define ICH_HCR_EN			(1 << 0)
>  #define ICH_HCR_UIE			(1 << 1)
> +#define ICH_HCR_TC			(1 << 10)
>  #define ICH_HCR_TALL0			(1 << 11)
>  #define ICH_HCR_TALL1			(1 << 12)
>  #define ICH_HCR_EOIcount_SHIFT		27
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 445e86c8b00c..717219ab58a2 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -23,6 +23,7 @@
>  
>  static bool group0_trap;
>  static bool group1_trap;
> +static bool common_trap;
>  
>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>  {
> @@ -246,6 +247,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>  		vgic_v3->vgic_hcr |= ICH_HCR_TALL0;
>  	if (group1_trap)
>  		vgic_v3->vgic_hcr |= ICH_HCR_TALL1;
> +	if (common_trap)
> +		vgic_v3->vgic_hcr |= ICH_HCR_TC;
>  }
>  
>  /* check for overlapping regions and for regions crossing the end of memory */
> @@ -339,6 +342,12 @@ static int __init early_group1_trap_cfg(char *buf)
>  }
>  early_param("vgic_v3.group1_trap", early_group1_trap_cfg);
>  
> +static int __init early_common_trap_cfg(char *buf)
> +{
> +	return strtobool(buf, &common_trap);
> +}
> +early_param("vgic_v3.common_trap", early_common_trap_cfg);
> +
>  /**
>   * vgic_v3_probe - probe for a GICv3 compatible interrupt controller in DT
>   * @node:	pointer to the DT node
> @@ -397,7 +406,7 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	}
>  #endif
>  
> -	if (group0_trap || group1_trap) {
> +	if (group0_trap || group1_trap || common_trap) {
>  		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
>  	}
> 

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

* Re: [PATCH 31/31] KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30  9:56     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,
On 03/05/2017 12:46, Marc Zyngier wrote:
> In order to facilitate debug, let's log which class of GICv3 system
> registers are trapped.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  virt/kvm/arm/vgic/vgic-v3.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 717219ab58a2..9110657b502c 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -407,7 +407,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  #endif
>  
>  	if (group0_trap || group1_trap || common_trap) {
> -		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
> +		kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
> +			 group0_trap ? "G0" : "",
> +			 group1_trap ? "G1" : "",
> +			 common_trap ? "C"  : "");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
>  	}
>  
> 

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

* [PATCH 31/31] KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped
@ 2017-05-30  9:56     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,
On 03/05/2017 12:46, Marc Zyngier wrote:
> In order to facilitate debug, let's log which class of GICv3 system
> registers are trapped.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  virt/kvm/arm/vgic/vgic-v3.c | 5 ++++-
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 717219ab58a2..9110657b502c 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -407,7 +407,10 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  #endif
>  
>  	if (group0_trap || group1_trap || common_trap) {
> -		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
> +		kvm_info("GICv3 sysreg trapping enabled ([%s%s%s], reduced performance)\n",
> +			 group0_trap ? "G0" : "",
> +			 group1_trap ? "G1" : "",
> +			 common_trap ? "C"  : "");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
>  	}
>  
> 

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

* Re: [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30  9:56     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Some Cavium Thunder CPUs suffer a problem where a KVM guest may
> inadvertently cause the host kernel to quit receiving interrupts.
> 
> Use the Group-0/1 trapping in order to deal with it.
> 
> [maz]: Adapted patch to the Group-0/1 trapping, reworked commit log
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  Documentation/arm64/silicon-errata.txt |  1 +
>  arch/arm64/Kconfig                     | 11 +++++++++++
>  arch/arm64/include/asm/cpucaps.h       |  3 ++-
>  arch/arm64/kernel/cpu_errata.c         | 21 +++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c            |  7 +++++++
>  5 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
> index 10f2dddbf449..f5f93dca54b7 100644
> --- a/Documentation/arm64/silicon-errata.txt
> +++ b/Documentation/arm64/silicon-errata.txt
> @@ -62,6 +62,7 @@ stable kernels.
>  | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154        |
>  | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456        |
>  | Cavium         | ThunderX SMMUv2 | #27704          | N/A                         |
> +| Cavium         | ThunderX Core   | #30115          | CAVIUM_ERRATUM_30115        |
>  |                |                 |                 |                             |
>  | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
>  |                |                 |                 |                             |
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 3dcd7ec69bca..0950b21e4d17 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -480,6 +480,17 @@ config CAVIUM_ERRATUM_27456
>  
>  	  If unsure, say Y.
>  
> +config CAVIUM_ERRATUM_30115
> +	bool "Cavium erratum 30115: Guest may disable interrupts in host"
> +	default y
> +	help
> +	  On ThunderX T88 pass 1.x through 2.2, T81 pass 1.0 through
> +	  1.2, and T83 Pass 1.0, KVM guest execution may disable
> +	  interrupts in host. Trapping GICv3 group-1 accesses sidesteps
> +	  the issue.
> +
> +	  If unsure, say Y.
> +
>  config QCOM_FALKOR_ERRATUM_1003
>  	bool "Falkor E1003: Incorrect translation due to ASID change"
>  	default y
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index b3aab8a17868..8d2272c6822c 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -38,7 +38,8 @@
>  #define ARM64_WORKAROUND_REPEAT_TLBI		17
>  #define ARM64_WORKAROUND_QCOM_FALKOR_E1003	18
>  #define ARM64_WORKAROUND_858921			19
> +#define ARM64_WORKAROUND_CAVIUM_30115		20
>  
> -#define ARM64_NCAPS				20
> +#define ARM64_NCAPS				21
>  
>  #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 2ed2a7657711..0e27f86ee709 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -133,6 +133,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
>  	},
>  #endif
> +#ifdef CONFIG_CAVIUM_ERRATUM_30115
> +	{
> +	/* Cavium ThunderX, T88 pass 1.x - 2.2 */
> +		.desc = "Cavium erratum 30115",
> +		.capability = ARM64_WORKAROUND_CAVIUM_30115,
> +		MIDR_RANGE(MIDR_THUNDERX, 0x00,
> +			   (1 << MIDR_VARIANT_SHIFT) | 2),
> +	},
> +	{
> +	/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
> +		.desc = "Cavium erratum 30115",
> +		.capability = ARM64_WORKAROUND_CAVIUM_30115,
> +		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
> +	},
> +	{
> +	/* Cavium ThunderX, T83 pass 1.0 */
> +		.desc = "Cavium erratum 30115",
> +		.capability = ARM64_WORKAROUND_CAVIUM_30115,
> +		MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
> +	},
> +#endif
>  	{
>  		.desc = "Mismatched cache line size",
>  		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 7c82c586d44a..445e86c8b00c 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -390,6 +390,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	if (kvm_vgic_global_state.vcpu_base == 0)
>  		kvm_info("disabling GICv2 emulation\n");
>  
> +#ifdef CONFIG_ARM64
> +	if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
> +		group0_trap = true;
> +		group1_trap = true;
> +	}
> +#endif
> +
>  	if (group0_trap || group1_trap) {
>  		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
> 

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

* [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
@ 2017-05-30  9:56     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Some Cavium Thunder CPUs suffer a problem where a KVM guest may
> inadvertently cause the host kernel to quit receiving interrupts.
> 
> Use the Group-0/1 trapping in order to deal with it.
> 
> [maz]: Adapted patch to the Group-0/1 trapping, reworked commit log
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  Documentation/arm64/silicon-errata.txt |  1 +
>  arch/arm64/Kconfig                     | 11 +++++++++++
>  arch/arm64/include/asm/cpucaps.h       |  3 ++-
>  arch/arm64/kernel/cpu_errata.c         | 21 +++++++++++++++++++++
>  virt/kvm/arm/vgic/vgic-v3.c            |  7 +++++++
>  5 files changed, 42 insertions(+), 1 deletion(-)
> 
> diff --git a/Documentation/arm64/silicon-errata.txt b/Documentation/arm64/silicon-errata.txt
> index 10f2dddbf449..f5f93dca54b7 100644
> --- a/Documentation/arm64/silicon-errata.txt
> +++ b/Documentation/arm64/silicon-errata.txt
> @@ -62,6 +62,7 @@ stable kernels.
>  | Cavium         | ThunderX GICv3  | #23154          | CAVIUM_ERRATUM_23154        |
>  | Cavium         | ThunderX Core   | #27456          | CAVIUM_ERRATUM_27456        |
>  | Cavium         | ThunderX SMMUv2 | #27704          | N/A                         |
> +| Cavium         | ThunderX Core   | #30115          | CAVIUM_ERRATUM_30115        |
>  |                |                 |                 |                             |
>  | Freescale/NXP  | LS2080A/LS1043A | A-008585        | FSL_ERRATUM_A008585         |
>  |                |                 |                 |                             |
> diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig
> index 3dcd7ec69bca..0950b21e4d17 100644
> --- a/arch/arm64/Kconfig
> +++ b/arch/arm64/Kconfig
> @@ -480,6 +480,17 @@ config CAVIUM_ERRATUM_27456
>  
>  	  If unsure, say Y.
>  
> +config CAVIUM_ERRATUM_30115
> +	bool "Cavium erratum 30115: Guest may disable interrupts in host"
> +	default y
> +	help
> +	  On ThunderX T88 pass 1.x through 2.2, T81 pass 1.0 through
> +	  1.2, and T83 Pass 1.0, KVM guest execution may disable
> +	  interrupts in host. Trapping GICv3 group-1 accesses sidesteps
> +	  the issue.
> +
> +	  If unsure, say Y.
> +
>  config QCOM_FALKOR_ERRATUM_1003
>  	bool "Falkor E1003: Incorrect translation due to ASID change"
>  	default y
> diff --git a/arch/arm64/include/asm/cpucaps.h b/arch/arm64/include/asm/cpucaps.h
> index b3aab8a17868..8d2272c6822c 100644
> --- a/arch/arm64/include/asm/cpucaps.h
> +++ b/arch/arm64/include/asm/cpucaps.h
> @@ -38,7 +38,8 @@
>  #define ARM64_WORKAROUND_REPEAT_TLBI		17
>  #define ARM64_WORKAROUND_QCOM_FALKOR_E1003	18
>  #define ARM64_WORKAROUND_858921			19
> +#define ARM64_WORKAROUND_CAVIUM_30115		20
>  
> -#define ARM64_NCAPS				20
> +#define ARM64_NCAPS				21
>  
>  #endif /* __ASM_CPUCAPS_H */
> diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c
> index 2ed2a7657711..0e27f86ee709 100644
> --- a/arch/arm64/kernel/cpu_errata.c
> +++ b/arch/arm64/kernel/cpu_errata.c
> @@ -133,6 +133,27 @@ const struct arm64_cpu_capabilities arm64_errata[] = {
>  		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x00),
>  	},
>  #endif
> +#ifdef CONFIG_CAVIUM_ERRATUM_30115
> +	{
> +	/* Cavium ThunderX, T88 pass 1.x - 2.2 */
> +		.desc = "Cavium erratum 30115",
> +		.capability = ARM64_WORKAROUND_CAVIUM_30115,
> +		MIDR_RANGE(MIDR_THUNDERX, 0x00,
> +			   (1 << MIDR_VARIANT_SHIFT) | 2),
> +	},
> +	{
> +	/* Cavium ThunderX, T81 pass 1.0 - 1.2 */
> +		.desc = "Cavium erratum 30115",
> +		.capability = ARM64_WORKAROUND_CAVIUM_30115,
> +		MIDR_RANGE(MIDR_THUNDERX_81XX, 0x00, 0x02),
> +	},
> +	{
> +	/* Cavium ThunderX, T83 pass 1.0 */
> +		.desc = "Cavium erratum 30115",
> +		.capability = ARM64_WORKAROUND_CAVIUM_30115,
> +		MIDR_RANGE(MIDR_THUNDERX_83XX, 0x00, 0x00),
> +	},
> +#endif
>  	{
>  		.desc = "Mismatched cache line size",
>  		.capability = ARM64_MISMATCHED_CACHE_LINE_SIZE,
> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
> index 7c82c586d44a..445e86c8b00c 100644
> --- a/virt/kvm/arm/vgic/vgic-v3.c
> +++ b/virt/kvm/arm/vgic/vgic-v3.c
> @@ -390,6 +390,13 @@ int vgic_v3_probe(const struct gic_kvm_info *info)
>  	if (kvm_vgic_global_state.vcpu_base == 0)
>  		kvm_info("disabling GICv2 emulation\n");
>  
> +#ifdef CONFIG_ARM64
> +	if (cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_30115)) {
> +		group0_trap = true;
> +		group1_trap = true;
> +	}
> +#endif
> +
>  	if (group0_trap || group1_trap) {
>  		kvm_info("GICv3 sysreg trapping enabled (reduced performance)\n");
>  		static_branch_enable(&vgic_v3_cpuif_trap);
> 

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

* Re: [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-05-30  9:56     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/cputype.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
> index 0984d1b3a8f2..235e77d98261 100644
> --- a/arch/arm64/include/asm/cputype.h
> +++ b/arch/arm64/include/asm/cputype.h
> @@ -86,6 +86,7 @@
>  
>  #define CAVIUM_CPU_PART_THUNDERX	0x0A1
>  #define CAVIUM_CPU_PART_THUNDERX_81XX	0x0A2
> +#define CAVIUM_CPU_PART_THUNDERX_83XX	0x0A3
>  
>  #define BRCM_CPU_PART_VULCAN		0x516
>  
> @@ -96,6 +97,7 @@
>  #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
>  #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
>  #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
> +#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
>  #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
>  
>  #ifndef __ASSEMBLY__
> 

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

* [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
@ 2017-05-30  9:56     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30  9:56 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:45, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/cputype.h | 2 ++
>  1 file changed, 2 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/cputype.h b/arch/arm64/include/asm/cputype.h
> index 0984d1b3a8f2..235e77d98261 100644
> --- a/arch/arm64/include/asm/cputype.h
> +++ b/arch/arm64/include/asm/cputype.h
> @@ -86,6 +86,7 @@
>  
>  #define CAVIUM_CPU_PART_THUNDERX	0x0A1
>  #define CAVIUM_CPU_PART_THUNDERX_81XX	0x0A2
> +#define CAVIUM_CPU_PART_THUNDERX_83XX	0x0A3
>  
>  #define BRCM_CPU_PART_VULCAN		0x516
>  
> @@ -96,6 +97,7 @@
>  #define MIDR_CORTEX_A73 MIDR_CPU_MODEL(ARM_CPU_IMP_ARM, ARM_CPU_PART_CORTEX_A73)
>  #define MIDR_THUNDERX	MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX)
>  #define MIDR_THUNDERX_81XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_81XX)
> +#define MIDR_THUNDERX_83XX MIDR_CPU_MODEL(ARM_CPU_IMP_CAVIUM, CAVIUM_CPU_PART_THUNDERX_83XX)
>  #define MIDR_QCOM_FALKOR_V1 MIDR_CPU_MODEL(ARM_CPU_IMP_QCOM, QCOM_CPU_PART_FALKOR_V1)
>  
>  #ifndef __ASSEMBLY__
> 

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

* Re: [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30 10:15     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:15 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Marc,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for writing the guest's view of the ICC_DIR_EL1
> register, performing the deactivation of an interrupt if EOImode
> is set ot 1.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 9c639f57268b..563dd2d16c59 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
>  	write_gicreg(hcr, ICH_HCR_EL2);
>  }
>  
> +static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
> +					   u32 vmcr, int rt)
> +{
> +	u32 vid = vcpu_get_reg(vcpu, rt);
> +	u64 lr_val;
> +	int lr;
> +
> +	/* No deactivate to be performed on an LPI */
> +	if (vid >= VGIC_MIN_LPI)
> +		return;

don't you need to test the EOImode first? Spec says:
"
When EOImode == ‘0’. GICv3 implementations must ignore such writes. In
systems supporting system error generation, an implementation might
generate an SEI.
"

Thanks

Eric

> +
> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
> +	if (lr == -1) {
> +		__vgic_v3_bump_eoicount();
> +		return;
> +	}
> +
> +	__vgic_v3_clear_active_lr(lr, lr_val);
> +}
> +
>  static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u32 vid = vcpu_get_reg(vcpu, rt);
> @@ -912,6 +932,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_bpr0;
>  		break;
> +	case SYS_ICC_DIR_EL1:
> +		fn = __vgic_v3_write_dir;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
@ 2017-05-30 10:15     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:15 UTC (permalink / raw)
  To: linux-arm-kernel

Marc,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for writing the guest's view of the ICC_DIR_EL1
> register, performing the deactivation of an interrupt if EOImode
> is set ot 1.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 9c639f57268b..563dd2d16c59 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
>  	write_gicreg(hcr, ICH_HCR_EL2);
>  }
>  
> +static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
> +					   u32 vmcr, int rt)
> +{
> +	u32 vid = vcpu_get_reg(vcpu, rt);
> +	u64 lr_val;
> +	int lr;
> +
> +	/* No deactivate to be performed on an LPI */
> +	if (vid >= VGIC_MIN_LPI)
> +		return;

don't you need to test the EOImode first? Spec says:
"
When EOImode == ?0?. GICv3 implementations must ignore such writes. In
systems supporting system error generation, an implementation might
generate an SEI.
"

Thanks

Eric

> +
> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
> +	if (lr == -1) {
> +		__vgic_v3_bump_eoicount();
> +		return;
> +	}
> +
> +	__vgic_v3_clear_active_lr(lr, lr_val);
> +}
> +
>  static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>  {
>  	u32 vid = vcpu_get_reg(vcpu, rt);
> @@ -912,6 +932,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_bpr0;
>  		break;
> +	case SYS_ICC_DIR_EL1:
> +		fn = __vgic_v3_write_dir;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 27/31] KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30 10:16     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:16 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for reading the guest's view of the ICV_RPR_EL1
> register, returning the highest active priority.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 10 ++++++++++
>  2 files changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 9971c5c435a7..c4d48e403629 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -187,6 +187,7 @@
>  #define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
>  #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
> +#define SYS_ICC_RPR_EL1			sys_reg(3, 0, 12, 11, 3)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>  #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 563dd2d16c59..3a5f54f445b9 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -848,6 +848,13 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
>  	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
>  }
>  
> +static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
> +					  u32 vmcr, int rt)
> +{
> +	u32 val = __vgic_v3_get_highest_active_priority();
> +	vcpu_set_reg(vcpu, rt, val);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -935,6 +942,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_DIR_EL1:
>  		fn = __vgic_v3_write_dir;
>  		break;
> +	case SYS_ICC_RPR_EL1:
> +		fn = __vgic_v3_read_rpr;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 27/31] KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler
@ 2017-05-30 10:16     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:16 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for reading the guest's view of the ICV_RPR_EL1
> register, returning the highest active priority.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  arch/arm64/include/asm/sysreg.h |  1 +
>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 10 ++++++++++
>  2 files changed, 11 insertions(+)
> 
> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
> index 9971c5c435a7..c4d48e403629 100644
> --- a/arch/arm64/include/asm/sysreg.h
> +++ b/arch/arm64/include/asm/sysreg.h
> @@ -187,6 +187,7 @@
>  #define SYS_ICC_AP0Rn_EL1(n)		sys_reg(3, 0, 12, 8, 4 | n)
>  #define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
> +#define SYS_ICC_RPR_EL1			sys_reg(3, 0, 12, 11, 3)
>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>  #define SYS_ICC_EOIR1_EL1		sys_reg(3, 0, 12, 12, 1)
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 563dd2d16c59..3a5f54f445b9 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -848,6 +848,13 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
>  	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
>  }
>  
> +static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
> +					  u32 vmcr, int rt)
> +{
> +	u32 val = __vgic_v3_get_highest_active_priority();
> +	vcpu_set_reg(vcpu, rt, val);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -935,6 +942,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_DIR_EL1:
>  		fn = __vgic_v3_write_dir;
>  		break;
> +	case SYS_ICC_RPR_EL1:
> +		fn = __vgic_v3_read_rpr;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 28/31] KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30 10:27     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:27 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICV_CTLR_EL1
> register. only EOIMode and CBPR are of interest here, as all the other
> bits directly come from ICH_VTR_EL2 and are Read-Only.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 46 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 3a5f54f445b9..981201bf7a5e 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -855,6 +855,46 @@ static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
>  	vcpu_set_reg(vcpu, rt, val);
>  }
>  
> +static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu,
> +					   u32 vmcr, int rt)
> +{
> +	u32 vtr, val;
> +
> +	vtr = read_gicreg(ICH_VTR_EL2);
> +	/* PRIbits */
> +	val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
> +	/* IDbits */
> +	val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
> +	/* SEIS */
> +	val |= ((vtr >> 22) & 1) << ICC_CTLR_EL1_SEIS_SHIFT;
> +	/* A3V */
> +	val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
> +	/* EOImode */
> +	val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
> +	/* CBPR */
> +	val |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
> +
> +	vcpu_set_reg(vcpu, rt, val);
> +}
> +
> +static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	u32 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (val & ICC_CTLR_EL1_CBPR_MASK)
> +		vmcr |= ICH_VMCR_CBPR_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_CBPR_MASK;
> +
> +	if (val & ICC_CTLR_EL1_EOImode_MASK)
> +		vmcr |= ICH_VMCR_EOIM_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_EOIM_MASK;
> +
> +	write_gicreg(vmcr, ICH_VMCR_EL2);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -945,6 +985,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_RPR_EL1:
>  		fn = __vgic_v3_read_rpr;
>  		break;
> +	case SYS_ICC_CTLR_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_ctlr;
> +		else
> +			fn = __vgic_v3_write_ctlr;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 28/31] KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler
@ 2017-05-30 10:27     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:27 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICV_CTLR_EL1
> register. only EOIMode and CBPR are of interest here, as all the other
> bits directly come from ICH_VTR_EL2 and are Read-Only.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks

Eric
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 46 +++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 46 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 3a5f54f445b9..981201bf7a5e 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -855,6 +855,46 @@ static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
>  	vcpu_set_reg(vcpu, rt, val);
>  }
>  
> +static void __hyp_text __vgic_v3_read_ctlr(struct kvm_vcpu *vcpu,
> +					   u32 vmcr, int rt)
> +{
> +	u32 vtr, val;
> +
> +	vtr = read_gicreg(ICH_VTR_EL2);
> +	/* PRIbits */
> +	val = ((vtr >> 29) & 7) << ICC_CTLR_EL1_PRI_BITS_SHIFT;
> +	/* IDbits */
> +	val |= ((vtr >> 23) & 7) << ICC_CTLR_EL1_ID_BITS_SHIFT;
> +	/* SEIS */
> +	val |= ((vtr >> 22) & 1) << ICC_CTLR_EL1_SEIS_SHIFT;
> +	/* A3V */
> +	val |= ((vtr >> 21) & 1) << ICC_CTLR_EL1_A3V_SHIFT;
> +	/* EOImode */
> +	val |= ((vmcr & ICH_VMCR_EOIM_MASK) >> ICH_VMCR_EOIM_SHIFT) << ICC_CTLR_EL1_EOImode_SHIFT;
> +	/* CBPR */
> +	val |= (vmcr & ICH_VMCR_CBPR_MASK) >> ICH_VMCR_CBPR_SHIFT;
> +
> +	vcpu_set_reg(vcpu, rt, val);
> +}
> +
> +static void __hyp_text __vgic_v3_write_ctlr(struct kvm_vcpu *vcpu,
> +					    u32 vmcr, int rt)
> +{
> +	u32 val = vcpu_get_reg(vcpu, rt);
> +
> +	if (val & ICC_CTLR_EL1_CBPR_MASK)
> +		vmcr |= ICH_VMCR_CBPR_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_CBPR_MASK;
> +
> +	if (val & ICC_CTLR_EL1_EOImode_MASK)
> +		vmcr |= ICH_VMCR_EOIM_MASK;
> +	else
> +		vmcr &= ~ICH_VMCR_EOIM_MASK;
> +
> +	write_gicreg(vmcr, ICH_VMCR_EL2);
> +}
> +
>  int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  {
>  	int rt = kvm_vcpu_sys_get_rt(vcpu);
> @@ -945,6 +985,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  	case SYS_ICC_RPR_EL1:
>  		fn = __vgic_v3_read_rpr;
>  		break;
> +	case SYS_ICC_CTLR_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_ctlr;
> +		else
> +			fn = __vgic_v3_write_ctlr;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 29/31] KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-05-30 10:34     ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:34 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_PMR_EL1
> register, which is located in the ICH_VMCR_EL2.VPMR field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 981201bf7a5e..4fbeeb54704e 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -848,6 +848,27 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
>  	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
>  }
>  
> +static void __hyp_text __vgic_v3_read_pmr(struct kvm_vcpu *vcpu,
> +					  u32 vmcr, int rt)
> +{
> +	vmcr &= ICH_VMCR_PMR_MASK;
> +	vmcr >>= ICH_VMCR_PMR_SHIFT;
> +	vcpu_set_reg(vcpu, rt, vmcr);
> +}
> +
> +static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu,
> +					   u32 vmcr, int rt)
> +{
> +	u32 val = vcpu_get_reg(vcpu, rt);
> +
> +	val <<= ICH_VMCR_PMR_SHIFT;
> +	val &= ICH_VMCR_PMR_MASK;
> +	vmcr &= ~ICH_VMCR_PMR_MASK;
> +	vmcr |= val;
> +
> +	write_gicreg(vmcr, ICH_VMCR_EL2);
> +}
> +
>  static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
>  					  u32 vmcr, int rt)
>  {
> @@ -991,6 +1012,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_ctlr;
>  		break;
> +	case SYS_ICC_PMR_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_pmr;
> +		else
> +			fn = __vgic_v3_write_pmr;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* [PATCH 29/31] KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler
@ 2017-05-30 10:34     ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-30 10:34 UTC (permalink / raw)
  To: linux-arm-kernel

Hi,

On 03/05/2017 12:46, Marc Zyngier wrote:
> Add a handler for reading/writing the guest's view of the ICC_PMR_EL1
> register, which is located in the ICH_VMCR_EL2.VPMR field.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>

Eric
> ---
>  virt/kvm/arm/hyp/vgic-v3-sr.c | 27 +++++++++++++++++++++++++++
>  1 file changed, 27 insertions(+)
> 
> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> index 981201bf7a5e..4fbeeb54704e 100644
> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> @@ -848,6 +848,27 @@ static void __hyp_text __vgic_v3_read_hppir(struct kvm_vcpu *vcpu,
>  	vcpu_set_reg(vcpu, rt, lr_val & ICH_LR_VIRTUAL_ID_MASK);
>  }
>  
> +static void __hyp_text __vgic_v3_read_pmr(struct kvm_vcpu *vcpu,
> +					  u32 vmcr, int rt)
> +{
> +	vmcr &= ICH_VMCR_PMR_MASK;
> +	vmcr >>= ICH_VMCR_PMR_SHIFT;
> +	vcpu_set_reg(vcpu, rt, vmcr);
> +}
> +
> +static void __hyp_text __vgic_v3_write_pmr(struct kvm_vcpu *vcpu,
> +					   u32 vmcr, int rt)
> +{
> +	u32 val = vcpu_get_reg(vcpu, rt);
> +
> +	val <<= ICH_VMCR_PMR_SHIFT;
> +	val &= ICH_VMCR_PMR_MASK;
> +	vmcr &= ~ICH_VMCR_PMR_MASK;
> +	vmcr |= val;
> +
> +	write_gicreg(vmcr, ICH_VMCR_EL2);
> +}
> +
>  static void __hyp_text __vgic_v3_read_rpr(struct kvm_vcpu *vcpu,
>  					  u32 vmcr, int rt)
>  {
> @@ -991,6 +1012,12 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>  		else
>  			fn = __vgic_v3_write_ctlr;
>  		break;
> +	case SYS_ICC_PMR_EL1:
> +		if (is_read)
> +			fn = __vgic_v3_read_pmr;
> +		else
> +			fn = __vgic_v3_write_pmr;
> +		break;
>  	default:
>  		return 0;
>  	}
> 

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

* Re: [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
  2017-05-30  8:02       ` Auger Eric
@ 2017-05-30 14:21         ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:21 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Eric,

On 30/05/17 09:02, Auger Eric wrote:
> Hi Marc,
> 
> On 30/05/2017 09:48, Auger Eric wrote:
>> H Marc,
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
>>> registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  arch/arm64/include/asm/sysreg.h |  1 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 95 insertions(+)
>>>
>>> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
>>> index 15c142ce991c..aad46b8eea5e 100644
>>> --- a/arch/arm64/include/asm/sysreg.h
>>> +++ b/arch/arm64/include/asm/sysreg.h
>>> @@ -180,6 +180,7 @@
>>>  
>>>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>>>  
>>> +#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>>>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>>>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>>>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index a76351b3ad66..b6803989da1f 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
>>>  	__vgic_v3_write_vmcr(vmcr);
>>>  }
>>>  
>>> +static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
>> Shouldn't you test somewhere that n is correct given the number of
>> implemented priority bits

If n is invalid, then the corresponding system register access will have
UNDEFed at EL1, irrespective of the trapping (UNDEF has a higher
priority than trapping, unfortunately).

>>> +{
>>> +	u32 val;
>>> +
>>> +	if (!__vgic_v3_get_group(vcpu))
>> I don't really get how an access to AP1Rn can end up in AP0Rn. I am not
>> able to find any related description in the spec?
> Forget that one. This is simply a generic helper and an access from NS
> world will access the AP1Rn reg.

It is not really S vs NS here, since the guest is probably aware it is
running non-secure. The GICv3 architecture allows the guest to have its
own Group0 interrupts (reported as FIQ).

> so besides the comment on "n" check,
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks!

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

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

* [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler
@ 2017-05-30 14:21         ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:21 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Eric,

On 30/05/17 09:02, Auger Eric wrote:
> Hi Marc,
> 
> On 30/05/2017 09:48, Auger Eric wrote:
>> H Marc,
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> Add a handler for reading/writing the guest's view of the ICV_AP1Rn_EL1
>>> registers. We just map them to the corresponding ICH_AP1Rn_EL2 registers.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  arch/arm64/include/asm/sysreg.h |  1 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c   | 94 +++++++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 95 insertions(+)
>>>
>>> diff --git a/arch/arm64/include/asm/sysreg.h b/arch/arm64/include/asm/sysreg.h
>>> index 15c142ce991c..aad46b8eea5e 100644
>>> --- a/arch/arm64/include/asm/sysreg.h
>>> +++ b/arch/arm64/include/asm/sysreg.h
>>> @@ -180,6 +180,7 @@
>>>  
>>>  #define SYS_VBAR_EL1			sys_reg(3, 0, 12, 0, 0)
>>>  
>>> +#define SYS_ICC_AP1Rn_EL1(n)		sys_reg(3, 0, 12, 9, n)
>>>  #define SYS_ICC_DIR_EL1			sys_reg(3, 0, 12, 11, 1)
>>>  #define SYS_ICC_SGI1R_EL1		sys_reg(3, 0, 12, 11, 5)
>>>  #define SYS_ICC_IAR1_EL1		sys_reg(3, 0, 12, 12, 0)
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index a76351b3ad66..b6803989da1f 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -684,6 +684,76 @@ static void __hyp_text __vgic_v3_write_bpr1(struct kvm_vcpu *vcpu, u32 vmcr, int
>>>  	__vgic_v3_write_vmcr(vmcr);
>>>  }
>>>  
>>> +static void __hyp_text __vgic_v3_read_apxrn(struct kvm_vcpu *vcpu, int rt, int n)
>> Shouldn't you test somewhere that n is correct given the number of
>> implemented priority bits

If n is invalid, then the corresponding system register access will have
UNDEFed at EL1, irrespective of the trapping (UNDEF has a higher
priority than trapping, unfortunately).

>>> +{
>>> +	u32 val;
>>> +
>>> +	if (!__vgic_v3_get_group(vcpu))
>> I don't really get how an access to AP1Rn can end up in AP0Rn. I am not
>> able to find any related description in the spec?
> Forget that one. This is simply a generic helper and an access from NS
> world will access the AP1Rn reg.

It is not really S vs NS here, since the guest is probably aware it is
running non-secure. The GICv3 architecture allows the guest to have its
own Group0 interrupts (reported as FIQ).

> so besides the comment on "n" check,
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks!

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

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-30  7:48     ` Auger Eric
@ 2017-05-30 14:24       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:24 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

On 30/05/17 08:48, Auger Eric wrote:
> Hi Marc
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>> register. This involves dropping the priority of the interrupt,
>> and deactivating it if required (EOImode == 0).
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 121 insertions(+)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index 7610ea4e8337..c56d9bc2c904 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -403,6 +403,8 @@
>>  
>>  #define ICH_HCR_EN			(1 << 0)
>>  #define ICH_HCR_UIE			(1 << 1)
>> +#define ICH_HCR_EOIcount_SHIFT		27
>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>  
>>  #define ICH_VMCR_CBPR_SHIFT		4
>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 49aad1de3ac8..a76351b3ad66 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>  	return lr;
>>  }
>>  
>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>> +					       int intid, u64 *lr_val)
>> +{
>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>> +	int i;
>> +
>> +	for (i = 0; i < used_lrs; i++) {
>> +		u64 val = __gic_v3_get_lr(i);
>> +
>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>> +		    (val & ICH_LR_ACTIVE_BIT)) {
> I guess it is safe because we don't have yet virtual interrupts directly
> mapped to phys IRQs, besides timer one?

What would that change? I don't see how having a HW interrupt here would
be unsafe... Am I missing something?

>> +			*lr_val = val;
>> +			return i;
>> +		}
>> +	}
>> +
>> +	*lr_val = ICC_IAR1_EL1_SPURIOUS;
>> +	return -1;
>> +}
>> +
>>  static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>  {
>>  	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> @@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>  	__vgic_v3_write_ap1rn(val | bit, apr);
>>  }
>>  
>> +static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
>> +{
>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
> may be worth to introduce a macro to compute the number of APRn regs.
> This may be more understandable.

Sure, will do.

>> +	u32 hap = 0;
>> +	int i;
>> +
>> +	for (i = 0; i < nr_aprs; i++) {
>> +		u32 ap0, ap1;
>> +		int c0, c1;
>> +
>> +		ap0 = __vgic_v3_read_ap0rn(i);
>> +		ap1 = __vgic_v3_read_ap1rn(i);
>> +		if (!ap0 && !ap1) {
>> +			hap += 32;
>> +			continue;
>> +		}
>> +
>> +		c0 = ap0 ? __ffs(ap0) : 32;
>> +		c1 = ap1 ? __ffs(ap1) : 32;
>> +
>> +		/* Always clear the LSB, which is the highest priority */
>> +		if (c0 < c1) {
>> +			ap0 &= ap0 - 1;
>> +			__vgic_v3_write_ap0rn(ap0, i);
>> +			hap += c0;
>> +		} else {
>> +			ap1 &= ap1 - 1;
>> +			__vgic_v3_write_ap1rn(ap1, i);
>> +			hap += c1;
>> +		}
>> +
>> +		return hap << (8 - nr_pre_bits);
>> +	}
>> +
>> +	return GICv3_IDLE_PRIORITY;
>> +}
>> +
>>  static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>  {
>>  	u64 lr_val;
>> @@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
>>  	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
>>  }
>>  
>> +static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
>> +{
>> +	lr_val &= ~ICH_LR_ACTIVE_BIT;
>> +	if (lr_val & ICH_LR_HW) {
>> +		u32 pid;
> nit: insert a line

OK.

>> +		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
>> +		gic_write_dir(pid);
>> +	}
>> +
>> +	__gic_v3_set_lr(lr_val, lr);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_bump_eoicount(void)
>> +{
>> +	u32 hcr;
>> +
>> +	hcr = read_gicreg(ICH_HCR_EL2);
>> +	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
>> +	write_gicreg(hcr, ICH_HCR_EL2);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>> +{
>> +	u32 vid = vcpu_get_reg(vcpu, rt);
>> +	u64 lr_val;
>> +	u8 lr_prio, act_prio;
>> +	int lr, grp;
>> +
>> +	grp = __vgic_v3_get_group(vcpu);
>> +
>> +	/* Drop priority in any case */
>> +	act_prio = __vgic_v3_clear_highest_active_priority();
>> +
>> +	/* If EOIing an LPI, no deactivate to be performed */
>> +	if (vid >= VGIC_MIN_LPI)
>> +		return;
>> +
>> +	/* EOImode == 1, nothing to be done here */
>> +	if (vmcr & ICH_VMCR_EOIM_MASK)
>> +		return;
>> +
>> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
>> +	if (lr == -1) {
>> +		__vgic_v3_bump_eoicount();
>> +		return;
>> +	}
>> +
>> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>> +
>> +	/* If priorities or group do not match, the guest has fscked-up. */
>> +	if (grp != !!(lr_val & ICH_LR_GROUP) ||
>> +	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
>> +		return;
>> +
>> +	/* Let's now perform the deactivation */
>> +	__vgic_v3_clear_active_lr(lr, lr_val);
>> +}
>> +
>>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>  {
>>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
>> @@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>  	case SYS_ICC_IAR1_EL1:
>>  		fn = __vgic_v3_read_iar;
>>  		break;
>> +	case SYS_ICC_EOIR1_EL1:
>> +		fn = __vgic_v3_write_eoir;
>> +		break;
>>  	case SYS_ICC_GRPEN1_EL1:
>>  		if (is_read)
>>  			fn = __vgic_v3_read_igrpen1;
> 
> Looks good to me
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks!

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

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-30 14:24       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:24 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/05/17 08:48, Auger Eric wrote:
> Hi Marc
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>> register. This involves dropping the priority of the interrupt,
>> and deactivating it if required (EOImode == 0).
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 121 insertions(+)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index 7610ea4e8337..c56d9bc2c904 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -403,6 +403,8 @@
>>  
>>  #define ICH_HCR_EN			(1 << 0)
>>  #define ICH_HCR_UIE			(1 << 1)
>> +#define ICH_HCR_EOIcount_SHIFT		27
>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>  
>>  #define ICH_VMCR_CBPR_SHIFT		4
>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 49aad1de3ac8..a76351b3ad66 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>  	return lr;
>>  }
>>  
>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>> +					       int intid, u64 *lr_val)
>> +{
>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>> +	int i;
>> +
>> +	for (i = 0; i < used_lrs; i++) {
>> +		u64 val = __gic_v3_get_lr(i);
>> +
>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>> +		    (val & ICH_LR_ACTIVE_BIT)) {
> I guess it is safe because we don't have yet virtual interrupts directly
> mapped to phys IRQs, besides timer one?

What would that change? I don't see how having a HW interrupt here would
be unsafe... Am I missing something?

>> +			*lr_val = val;
>> +			return i;
>> +		}
>> +	}
>> +
>> +	*lr_val = ICC_IAR1_EL1_SPURIOUS;
>> +	return -1;
>> +}
>> +
>>  static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>  {
>>  	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> @@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>  	__vgic_v3_write_ap1rn(val | bit, apr);
>>  }
>>  
>> +static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
>> +{
>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
> may be worth to introduce a macro to compute the number of APRn regs.
> This may be more understandable.

Sure, will do.

>> +	u32 hap = 0;
>> +	int i;
>> +
>> +	for (i = 0; i < nr_aprs; i++) {
>> +		u32 ap0, ap1;
>> +		int c0, c1;
>> +
>> +		ap0 = __vgic_v3_read_ap0rn(i);
>> +		ap1 = __vgic_v3_read_ap1rn(i);
>> +		if (!ap0 && !ap1) {
>> +			hap += 32;
>> +			continue;
>> +		}
>> +
>> +		c0 = ap0 ? __ffs(ap0) : 32;
>> +		c1 = ap1 ? __ffs(ap1) : 32;
>> +
>> +		/* Always clear the LSB, which is the highest priority */
>> +		if (c0 < c1) {
>> +			ap0 &= ap0 - 1;
>> +			__vgic_v3_write_ap0rn(ap0, i);
>> +			hap += c0;
>> +		} else {
>> +			ap1 &= ap1 - 1;
>> +			__vgic_v3_write_ap1rn(ap1, i);
>> +			hap += c1;
>> +		}
>> +
>> +		return hap << (8 - nr_pre_bits);
>> +	}
>> +
>> +	return GICv3_IDLE_PRIORITY;
>> +}
>> +
>>  static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>  {
>>  	u64 lr_val;
>> @@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
>>  	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
>>  }
>>  
>> +static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
>> +{
>> +	lr_val &= ~ICH_LR_ACTIVE_BIT;
>> +	if (lr_val & ICH_LR_HW) {
>> +		u32 pid;
> nit: insert a line

OK.

>> +		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
>> +		gic_write_dir(pid);
>> +	}
>> +
>> +	__gic_v3_set_lr(lr_val, lr);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_bump_eoicount(void)
>> +{
>> +	u32 hcr;
>> +
>> +	hcr = read_gicreg(ICH_HCR_EL2);
>> +	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
>> +	write_gicreg(hcr, ICH_HCR_EL2);
>> +}
>> +
>> +static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>> +{
>> +	u32 vid = vcpu_get_reg(vcpu, rt);
>> +	u64 lr_val;
>> +	u8 lr_prio, act_prio;
>> +	int lr, grp;
>> +
>> +	grp = __vgic_v3_get_group(vcpu);
>> +
>> +	/* Drop priority in any case */
>> +	act_prio = __vgic_v3_clear_highest_active_priority();
>> +
>> +	/* If EOIing an LPI, no deactivate to be performed */
>> +	if (vid >= VGIC_MIN_LPI)
>> +		return;
>> +
>> +	/* EOImode == 1, nothing to be done here */
>> +	if (vmcr & ICH_VMCR_EOIM_MASK)
>> +		return;
>> +
>> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
>> +	if (lr == -1) {
>> +		__vgic_v3_bump_eoicount();
>> +		return;
>> +	}
>> +
>> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>> +
>> +	/* If priorities or group do not match, the guest has fscked-up. */
>> +	if (grp != !!(lr_val & ICH_LR_GROUP) ||
>> +	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
>> +		return;
>> +
>> +	/* Let's now perform the deactivation */
>> +	__vgic_v3_clear_active_lr(lr, lr_val);
>> +}
>> +
>>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>  {
>>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
>> @@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>  	case SYS_ICC_IAR1_EL1:
>>  		fn = __vgic_v3_read_iar;
>>  		break;
>> +	case SYS_ICC_EOIR1_EL1:
>> +		fn = __vgic_v3_write_eoir;
>> +		break;
>>  	case SYS_ICC_GRPEN1_EL1:
>>  		if (is_read)
>>  			fn = __vgic_v3_read_igrpen1;
> 
> Looks good to me
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks!

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

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

* Re: [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
  2017-05-30  9:07     ` Auger Eric
@ 2017-05-30 14:32       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:32 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

On 30/05/17 10:07, Auger Eric wrote:
> Hi Marc,
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> In order to be able to trap Group-1 GICv3 system registers, we need to
>> set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
> before, conditionally
>> done after having restored the guest's state, and cleared on exit.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/irqchip/arm-gic-v3.h | 1 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
>>  virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
>>  3 files changed, 12 insertions(+)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index c56d9bc2c904..a1739843343e 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -403,6 +403,7 @@
>>  
>>  #define ICH_HCR_EN			(1 << 0)
>>  #define ICH_HCR_UIE			(1 << 1)
>> +#define ICH_HCR_TALL1			(1 << 12)
>>  #define ICH_HCR_EOIcount_SHIFT		27
>>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>  
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index a521e105ade1..a27671b1e9af 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -257,6 +257,9 @@ 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))
>> +			write_gicreg(0, ICH_HCR_EL2);
> Not directly related to this patch but this is not obvious to me why we
> reset the ICH_HCR_EL2 only when used_lrs != 0.

That's because if there is no interrupt to inject, then we've never
enabled the virtual CPU interface, and we've only configured VMCR.

>> +
>>  		cpu_if->vgic_elrsr = 0xffff;
>>  		cpu_if->vgic_ap0r[0] = 0;
>>  		cpu_if->vgic_ap0r[1] = 0;
>> @@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>>  
>>  		for (i = 0; i < used_lrs; i++)
>>  			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
>> +	} else {
>> +		/* Always write ICH_HCR_EL2 to enable trapping */
> "always" is a bit weird as this is conditional

Ah, true. How about:
		/*
                 * If we don't have any interrupt to inject, but that
		 * trapping is enabled, write the ICH_HCR_EL2 config.
		 */

>> +		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
>> +			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
> and same question here. Why don't we always restore the ICH_HCR_EL2.
> Assuming when exiting the guest the vCPU I/F was enabled and used_lrs=0,

That case doesn't exist. The only case where we enable the virtual cpuif
is when we have something to inject (hence used_lrs != 0).

> when restoring don't we leave the vCPU I/F disabled? I must miss
> something but I don't find who is re-enabling the vCPU I/F in that case?

See above. This case shouldn't exist, and is only introduced here for
the benefit of the trapping.

>>  	}
>>  
>>  	/*
>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>> index 063526443781..547b8374fb64 100644
>> --- a/virt/kvm/arm/vgic/vgic-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>> @@ -21,6 +21,8 @@
>>  
>>  #include "vgic.h"
>>  
>> +static bool group1_trap;
>> +
>>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>>  {
>>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>> @@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>>  
>>  	/* Get the show on the road... */
>>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
>> +	if (group1_trap)
> I don't remember the rationale behind using the bool here and using
> static_branch_unlikely in the other cases.

That's just the initial config path, before setting the static key.

> 
> May be good to squash the next patch to understand how group1_trap is set.

Sure, I'll have a look at that.

Thanks,

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

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

* [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
@ 2017-05-30 14:32       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:32 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/05/17 10:07, Auger Eric wrote:
> Hi Marc,
> 
> On 03/05/2017 12:45, Marc Zyngier wrote:
>> In order to be able to trap Group-1 GICv3 system registers, we need to
>> set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
> before, conditionally
>> done after having restored the guest's state, and cleared on exit.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  include/linux/irqchip/arm-gic-v3.h | 1 +
>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
>>  virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
>>  3 files changed, 12 insertions(+)
>>
>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>> index c56d9bc2c904..a1739843343e 100644
>> --- a/include/linux/irqchip/arm-gic-v3.h
>> +++ b/include/linux/irqchip/arm-gic-v3.h
>> @@ -403,6 +403,7 @@
>>  
>>  #define ICH_HCR_EN			(1 << 0)
>>  #define ICH_HCR_UIE			(1 << 1)
>> +#define ICH_HCR_TALL1			(1 << 12)
>>  #define ICH_HCR_EOIcount_SHIFT		27
>>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>  
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index a521e105ade1..a27671b1e9af 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -257,6 +257,9 @@ 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))
>> +			write_gicreg(0, ICH_HCR_EL2);
> Not directly related to this patch but this is not obvious to me why we
> reset the ICH_HCR_EL2 only when used_lrs != 0.

That's because if there is no interrupt to inject, then we've never
enabled the virtual CPU interface, and we've only configured VMCR.

>> +
>>  		cpu_if->vgic_elrsr = 0xffff;
>>  		cpu_if->vgic_ap0r[0] = 0;
>>  		cpu_if->vgic_ap0r[1] = 0;
>> @@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>>  
>>  		for (i = 0; i < used_lrs; i++)
>>  			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
>> +	} else {
>> +		/* Always write ICH_HCR_EL2 to enable trapping */
> "always" is a bit weird as this is conditional

Ah, true. How about:
		/*
                 * If we don't have any interrupt to inject, but that
		 * trapping is enabled, write the ICH_HCR_EL2 config.
		 */

>> +		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
>> +			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
> and same question here. Why don't we always restore the ICH_HCR_EL2.
> Assuming when exiting the guest the vCPU I/F was enabled and used_lrs=0,

That case doesn't exist. The only case where we enable the virtual cpuif
is when we have something to inject (hence used_lrs != 0).

> when restoring don't we leave the vCPU I/F disabled? I must miss
> something but I don't find who is re-enabling the vCPU I/F in that case?

See above. This case shouldn't exist, and is only introduced here for
the benefit of the trapping.

>>  	}
>>  
>>  	/*
>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>> index 063526443781..547b8374fb64 100644
>> --- a/virt/kvm/arm/vgic/vgic-v3.c
>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>> @@ -21,6 +21,8 @@
>>  
>>  #include "vgic.h"
>>  
>> +static bool group1_trap;
>> +
>>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>>  {
>>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>> @@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>>  
>>  	/* Get the show on the road... */
>>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
>> +	if (group1_trap)
> I don't remember the rationale behind using the bool here and using
> static_branch_unlikely in the other cases.

That's just the initial config path, before setting the static key.

> 
> May be good to squash the next patch to understand how group1_trap is set.

Sure, I'll have a look at that.

Thanks,

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

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

* Re: [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
  2017-05-30  9:56     ` Auger Eric
@ 2017-05-30 14:41       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:41 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

On 30/05/17 10:56, Auger Eric wrote:
> Hi,
> 
> On 03/05/2017 12:46, Marc Zyngier wrote:
>> Now that we're able to safely handle common sysreg access, let's
>> give the user the opportunity to enable it by passing a specific
>> command-line option (vgic_v3.common_trap).
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> 
> What is the rationale behind trapping those common sysreg accesses. This
> is not enabled by default for some erratas. Is it to complete the
> trapping modality. May be worth to explain.

That's strictly for completeness. Let's assume some hypothetical HW has
a bug on the EOI path, where the physical interrupt wouldn't get
properly deactivated on the physical distributor. In order to deal with
that when EOImode==1 in the guest, you'd need to trap DIR as well. Same
thing if PMR was broken as well.

Also, we could implement some form of tracing of all the GICv3 accessors
if we wanted such a functionality (trying to find something more
gratifying than basic errata workaround here... ;-).

> 
> Besides
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks,

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

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

* [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line
@ 2017-05-30 14:41       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:41 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/05/17 10:56, Auger Eric wrote:
> Hi,
> 
> On 03/05/2017 12:46, Marc Zyngier wrote:
>> Now that we're able to safely handle common sysreg access, let's
>> give the user the opportunity to enable it by passing a specific
>> command-line option (vgic_v3.common_trap).
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> 
> What is the rationale behind trapping those common sysreg accesses. This
> is not enabled by default for some erratas. Is it to complete the
> trapping modality. May be worth to explain.

That's strictly for completeness. Let's assume some hypothetical HW has
a bug on the EOI path, where the physical interrupt wouldn't get
properly deactivated on the physical distributor. In order to deal with
that when EOImode==1 in the guest, you'd need to trap DIR as well. Same
thing if PMR was broken as well.

Also, we could implement some form of tracing of all the GICv3 accessors
if we wanted such a functionality (trying to find something more
gratifying than basic errata workaround here... ;-).

> 
> Besides
> 
> Reviewed-by: Eric Auger <eric.auger@redhat.com>

Thanks,

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

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

* Re: [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
  2017-05-30 10:15     ` Auger Eric
@ 2017-05-30 14:45       ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:45 UTC (permalink / raw)
  To: Auger Eric, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

On 30/05/17 11:15, Auger Eric wrote:
> Marc,
> 
> On 03/05/2017 12:46, Marc Zyngier wrote:
>> Add a handler for writing the guest's view of the ICC_DIR_EL1
>> register, performing the deactivation of an interrupt if EOImode
>> is set ot 1.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
>>  1 file changed, 23 insertions(+)
>>
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 9c639f57268b..563dd2d16c59 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
>>  	write_gicreg(hcr, ICH_HCR_EL2);
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
>> +					   u32 vmcr, int rt)
>> +{
>> +	u32 vid = vcpu_get_reg(vcpu, rt);
>> +	u64 lr_val;
>> +	int lr;
>> +
>> +	/* No deactivate to be performed on an LPI */
>> +	if (vid >= VGIC_MIN_LPI)
>> +		return;
> 
> don't you need to test the EOImode first? Spec says:
> "
> When EOImode == ‘0’. GICv3 implementations must ignore such writes. In
> systems supporting system error generation, an implementation might
> generate an SEI.
> "

Ah, very good point! Thanks for the heads up!

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

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

* [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler
@ 2017-05-30 14:45       ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 14:45 UTC (permalink / raw)
  To: linux-arm-kernel

On 30/05/17 11:15, Auger Eric wrote:
> Marc,
> 
> On 03/05/2017 12:46, Marc Zyngier wrote:
>> Add a handler for writing the guest's view of the ICC_DIR_EL1
>> register, performing the deactivation of an interrupt if EOImode
>> is set ot 1.
>>
>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>> ---
>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 23 +++++++++++++++++++++++
>>  1 file changed, 23 insertions(+)
>>
>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> index 9c639f57268b..563dd2d16c59 100644
>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>> @@ -612,6 +612,26 @@ static void __hyp_text __vgic_v3_bump_eoicount(void)
>>  	write_gicreg(hcr, ICH_HCR_EL2);
>>  }
>>  
>> +static void __hyp_text __vgic_v3_write_dir(struct kvm_vcpu *vcpu,
>> +					   u32 vmcr, int rt)
>> +{
>> +	u32 vid = vcpu_get_reg(vcpu, rt);
>> +	u64 lr_val;
>> +	int lr;
>> +
>> +	/* No deactivate to be performed on an LPI */
>> +	if (vid >= VGIC_MIN_LPI)
>> +		return;
> 
> don't you need to test the EOImode first? Spec says:
> "
> When EOImode == ?0?. GICv3 implementations must ignore such writes. In
> systems supporting system error generation, an implementation might
> generate an SEI.
> "

Ah, very good point! Thanks for the heads up!

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

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-03 15:58       ` Marc Zyngier
@ 2017-05-30 16:17         ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 16:17 UTC (permalink / raw)
  To: Mark Rutland
  Cc: Christoffer Dall, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

On 03/05/17 16:58, Marc Zyngier wrote:
> On 03/05/17 16:32, Mark Rutland wrote:
>> On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
>>> As we're about to access the Active Priority registers a lot more,
>>> let's define accessors that take the register number as a parameter.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>>  1 file changed, 100 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index 32c3295929b0..990d9d1e85d0 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>>  	}
>>>  }
>>>  
>>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>>> +{
>>> +	switch (n) {
>>> +	case 0:
>>> +		write_gicreg(val, ICH_AP0R0_EL2);
>>> +		break;
>>> +	case 1:
>>> +		write_gicreg(val, ICH_AP0R1_EL2);
>>> +		break;
>>> +	case 2:
>>> +		write_gicreg(val, ICH_AP0R2_EL2);
>>> +		break;
>>> +	case 3:
>>> +		write_gicreg(val, ICH_AP0R3_EL2);
>>> +		break;
>>> +	}
>>
>> Is there any way we can get a build or runtime failure for an
>> out-of-bounds n value?
> 
> I'd rather avoid runtime failure on this path, because that's pretty
> terminal. Build-time is a possibility, to some extent.
> 
>>
>>> +}
>>
>> Given this is used with a constant n, you could make this:
>>
>> #define __vgic_v3_write_ap0rn(v, n) \
>> 	write_gicreg(v, ICH_AP0R##n##_EL2)
>>
>> ... which should also give you a warning for an out-of-bounds n.
>>
>> Similar could apply for the other helpers here.
>>
>> That would require some function -> macro conversion in later patches
>> though, so I can understand if you're not keen on that.
> 
> I don't mind reworking this if that makes it safer. But the real problem
> is that the register number and the group are not necessarily constants
> (see how this is used in __vgic_v3_get_highest_active_priority).
> 
> I'll have a look at how I can make that look a bit better.

So I had another look at that, and I'm not sure there is any way to make
it really nicer, other than expanding all of the apxrn accessors to deal
with non constant x and n (which makes the code look really awful).

I'm pretty confident that it is nigh impossible to get x or n out of
bounds so unless someone shouts, I plan on keeping this code mostly
unchanged for the next repost.

Thanks,

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

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-30 16:17         ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-30 16:17 UTC (permalink / raw)
  To: linux-arm-kernel

On 03/05/17 16:58, Marc Zyngier wrote:
> On 03/05/17 16:32, Mark Rutland wrote:
>> On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
>>> As we're about to access the Active Priority registers a lot more,
>>> let's define accessors that take the register number as a parameter.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c | 116 ++++++++++++++++++++++++++++++++++++------
>>>  1 file changed, 100 insertions(+), 16 deletions(-)
>>>
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index 32c3295929b0..990d9d1e85d0 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -118,6 +118,90 @@ static void __hyp_text __gic_v3_set_lr(u64 val, int lr)
>>>  	}
>>>  }
>>>  
>>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
>>> +{
>>> +	switch (n) {
>>> +	case 0:
>>> +		write_gicreg(val, ICH_AP0R0_EL2);
>>> +		break;
>>> +	case 1:
>>> +		write_gicreg(val, ICH_AP0R1_EL2);
>>> +		break;
>>> +	case 2:
>>> +		write_gicreg(val, ICH_AP0R2_EL2);
>>> +		break;
>>> +	case 3:
>>> +		write_gicreg(val, ICH_AP0R3_EL2);
>>> +		break;
>>> +	}
>>
>> Is there any way we can get a build or runtime failure for an
>> out-of-bounds n value?
> 
> I'd rather avoid runtime failure on this path, because that's pretty
> terminal. Build-time is a possibility, to some extent.
> 
>>
>>> +}
>>
>> Given this is used with a constant n, you could make this:
>>
>> #define __vgic_v3_write_ap0rn(v, n) \
>> 	write_gicreg(v, ICH_AP0R##n##_EL2)
>>
>> ... which should also give you a warning for an out-of-bounds n.
>>
>> Similar could apply for the other helpers here.
>>
>> That would require some function -> macro conversion in later patches
>> though, so I can understand if you're not keen on that.
> 
> I don't mind reworking this if that makes it safer. But the real problem
> is that the register number and the group are not necessarily constants
> (see how this is used in __vgic_v3_get_highest_active_priority).
> 
> I'll have a look at how I can make that look a bit better.

So I had another look at that, and I'm not sure there is any way to make
it really nicer, other than expanding all of the apxrn accessors to deal
with non constant x and n (which makes the code look really awful).

I'm pretty confident that it is nigh impossible to get x or n out of
bounds so unless someone shouts, I plan on keeping this code mostly
unchanged for the next repost.

Thanks,

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

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

* Re: [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
  2017-05-30 16:17         ` Marc Zyngier
@ 2017-05-30 16:42           ` Mark Rutland
  -1 siblings, 0 replies; 162+ messages in thread
From: Mark Rutland @ 2017-05-30 16:42 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Christoffer Dall, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel, kvm

On Tue, May 30, 2017 at 05:17:01PM +0100, Marc Zyngier wrote:
> On 03/05/17 16:58, Marc Zyngier wrote:
> > On 03/05/17 16:32, Mark Rutland wrote:
> >> On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
> >>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
> >>> +{
> >>> +	switch (n) {
> >>> +	case 0:
> >>> +		write_gicreg(val, ICH_AP0R0_EL2);
> >>> +		break;
> >>> +	case 1:
> >>> +		write_gicreg(val, ICH_AP0R1_EL2);
> >>> +		break;
> >>> +	case 2:
> >>> +		write_gicreg(val, ICH_AP0R2_EL2);
> >>> +		break;
> >>> +	case 3:
> >>> +		write_gicreg(val, ICH_AP0R3_EL2);
> >>> +		break;
> >>> +	}
> >>
> >> Is there any way we can get a build or runtime failure for an
> >> out-of-bounds n value?
> > 
> > I'd rather avoid runtime failure on this path, because that's pretty
> > terminal. Build-time is a possibility, to some extent.

> >> Given this is used with a constant n, you could make this:
> >>
> >> #define __vgic_v3_write_ap0rn(v, n) \
> >> 	write_gicreg(v, ICH_AP0R##n##_EL2)
> >>
> >> ... which should also give you a warning for an out-of-bounds n.
> >>
> >> Similar could apply for the other helpers here.
> >>
> >> That would require some function -> macro conversion in later patches
> >> though, so I can understand if you're not keen on that.
> > 
> > I don't mind reworking this if that makes it safer. But the real problem
> > is that the register number and the group are not necessarily constants
> > (see how this is used in __vgic_v3_get_highest_active_priority).
> > 
> > I'll have a look at how I can make that look a bit better.
> 
> So I had another look at that, and I'm not sure there is any way to make
> it really nicer, other than expanding all of the apxrn accessors to deal
> with non constant x and n (which makes the code look really awful).
> 
> I'm pretty confident that it is nigh impossible to get x or n out of
> bounds so unless someone shouts, I plan on keeping this code mostly
> unchanged for the next repost.

Fair enough, thanks for taking a look anyhow.

Thanks,
Mark.

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

* [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the ICH_APxRn_EL2 registers
@ 2017-05-30 16:42           ` Mark Rutland
  0 siblings, 0 replies; 162+ messages in thread
From: Mark Rutland @ 2017-05-30 16:42 UTC (permalink / raw)
  To: linux-arm-kernel

On Tue, May 30, 2017 at 05:17:01PM +0100, Marc Zyngier wrote:
> On 03/05/17 16:58, Marc Zyngier wrote:
> > On 03/05/17 16:32, Mark Rutland wrote:
> >> On Wed, May 03, 2017 at 11:45:42AM +0100, Marc Zyngier wrote:
> >>> +static void __hyp_text __vgic_v3_write_ap0rn(u32 val, int n)
> >>> +{
> >>> +	switch (n) {
> >>> +	case 0:
> >>> +		write_gicreg(val, ICH_AP0R0_EL2);
> >>> +		break;
> >>> +	case 1:
> >>> +		write_gicreg(val, ICH_AP0R1_EL2);
> >>> +		break;
> >>> +	case 2:
> >>> +		write_gicreg(val, ICH_AP0R2_EL2);
> >>> +		break;
> >>> +	case 3:
> >>> +		write_gicreg(val, ICH_AP0R3_EL2);
> >>> +		break;
> >>> +	}
> >>
> >> Is there any way we can get a build or runtime failure for an
> >> out-of-bounds n value?
> > 
> > I'd rather avoid runtime failure on this path, because that's pretty
> > terminal. Build-time is a possibility, to some extent.

> >> Given this is used with a constant n, you could make this:
> >>
> >> #define __vgic_v3_write_ap0rn(v, n) \
> >> 	write_gicreg(v, ICH_AP0R##n##_EL2)
> >>
> >> ... which should also give you a warning for an out-of-bounds n.
> >>
> >> Similar could apply for the other helpers here.
> >>
> >> That would require some function -> macro conversion in later patches
> >> though, so I can understand if you're not keen on that.
> > 
> > I don't mind reworking this if that makes it safer. But the real problem
> > is that the register number and the group are not necessarily constants
> > (see how this is used in __vgic_v3_get_highest_active_priority).
> > 
> > I'll have a look at how I can make that look a bit better.
> 
> So I had another look at that, and I'm not sure there is any way to make
> it really nicer, other than expanding all of the apxrn accessors to deal
> with non constant x and n (which makes the code look really awful).
> 
> I'm pretty confident that it is nigh impossible to get x or n out of
> bounds so unless someone shouts, I plan on keeping this code mostly
> unchanged for the next repost.

Fair enough, thanks for taking a look anyhow.

Thanks,
Mark.

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-30 14:24       ` Marc Zyngier
@ 2017-05-31  6:33         ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-31  6:33 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

Hi Marc,

On 30/05/2017 16:24, Marc Zyngier wrote:
> On 30/05/17 08:48, Auger Eric wrote:
>> Hi Marc
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>>> register. This involves dropping the priority of the interrupt,
>>> and deactivating it if required (EOImode == 0).
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 121 insertions(+)
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index 7610ea4e8337..c56d9bc2c904 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -403,6 +403,8 @@
>>>  
>>>  #define ICH_HCR_EN			(1 << 0)
>>>  #define ICH_HCR_UIE			(1 << 1)
>>> +#define ICH_HCR_EOIcount_SHIFT		27
>>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>  
>>>  #define ICH_VMCR_CBPR_SHIFT		4
>>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index 49aad1de3ac8..a76351b3ad66 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>  	return lr;
>>>  }
>>>  
>>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>>> +					       int intid, u64 *lr_val)
>>> +{
>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < used_lrs; i++) {
>>> +		u64 val = __gic_v3_get_lr(i);
>>> +
>>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>>> +		    (val & ICH_LR_ACTIVE_BIT)) {
>> I guess it is safe because we don't have yet virtual interrupts directly
>> mapped to phys IRQs, besides timer one?
> 
> What would that change? I don't see how having a HW interrupt here would
> be unsafe... Am I missing something?
I was thinking about the case of an HW mapped interrupt whose active
state must be observed at distributor level - as I understood the spec -
and not at LR level.

Thanks

Eric
> 
>>> +			*lr_val = val;
>>> +			return i;
>>> +		}
>>> +	}
>>> +
>>> +	*lr_val = ICC_IAR1_EL1_SPURIOUS;
>>> +	return -1;
>>> +}
>>> +
>>>  static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>>  {
>>>  	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> @@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>>  	__vgic_v3_write_ap1rn(val | bit, apr);
>>>  }
>>>  
>>> +static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
>>> +{
>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
>> may be worth to introduce a macro to compute the number of APRn regs.
>> This may be more understandable.
> 
> Sure, will do.
> 
>>> +	u32 hap = 0;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < nr_aprs; i++) {
>>> +		u32 ap0, ap1;
>>> +		int c0, c1;
>>> +
>>> +		ap0 = __vgic_v3_read_ap0rn(i);
>>> +		ap1 = __vgic_v3_read_ap1rn(i);
>>> +		if (!ap0 && !ap1) {
>>> +			hap += 32;
>>> +			continue;
>>> +		}
>>> +
>>> +		c0 = ap0 ? __ffs(ap0) : 32;
>>> +		c1 = ap1 ? __ffs(ap1) : 32;
>>> +
>>> +		/* Always clear the LSB, which is the highest priority */
>>> +		if (c0 < c1) {
>>> +			ap0 &= ap0 - 1;
>>> +			__vgic_v3_write_ap0rn(ap0, i);
>>> +			hap += c0;
>>> +		} else {
>>> +			ap1 &= ap1 - 1;
>>> +			__vgic_v3_write_ap1rn(ap1, i);
>>> +			hap += c1;
>>> +		}
>>> +
>>> +		return hap << (8 - nr_pre_bits);
>>> +	}
>>> +
>>> +	return GICv3_IDLE_PRIORITY;
>>> +}
>>> +
>>>  static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>>  {
>>>  	u64 lr_val;
>>> @@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
>>>  	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
>>>  }
>>>  
>>> +static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
>>> +{
>>> +	lr_val &= ~ICH_LR_ACTIVE_BIT;
>>> +	if (lr_val & ICH_LR_HW) {
>>> +		u32 pid;
>> nit: insert a line
> 
> OK.
> 
>>> +		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
>>> +		gic_write_dir(pid);
>>> +	}
>>> +
>>> +	__gic_v3_set_lr(lr_val, lr);
>>> +}
>>> +
>>> +static void __hyp_text __vgic_v3_bump_eoicount(void)
>>> +{
>>> +	u32 hcr;
>>> +
>>> +	hcr = read_gicreg(ICH_HCR_EL2);
>>> +	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
>>> +	write_gicreg(hcr, ICH_HCR_EL2);
>>> +}
>>> +
>>> +static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>> +{
>>> +	u32 vid = vcpu_get_reg(vcpu, rt);
>>> +	u64 lr_val;
>>> +	u8 lr_prio, act_prio;
>>> +	int lr, grp;
>>> +
>>> +	grp = __vgic_v3_get_group(vcpu);
>>> +
>>> +	/* Drop priority in any case */
>>> +	act_prio = __vgic_v3_clear_highest_active_priority();
>>> +
>>> +	/* If EOIing an LPI, no deactivate to be performed */
>>> +	if (vid >= VGIC_MIN_LPI)
>>> +		return;
>>> +
>>> +	/* EOImode == 1, nothing to be done here */
>>> +	if (vmcr & ICH_VMCR_EOIM_MASK)
>>> +		return;
>>> +
>>> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
>>> +	if (lr == -1) {
>>> +		__vgic_v3_bump_eoicount();
>>> +		return;
>>> +	}
>>> +
>>> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>>> +
>>> +	/* If priorities or group do not match, the guest has fscked-up. */
>>> +	if (grp != !!(lr_val & ICH_LR_GROUP) ||
>>> +	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
>>> +		return;
>>> +
>>> +	/* Let's now perform the deactivation */
>>> +	__vgic_v3_clear_active_lr(lr, lr_val);
>>> +}
>>> +
>>>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>>  {
>>>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
>>> @@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>>  	case SYS_ICC_IAR1_EL1:
>>>  		fn = __vgic_v3_read_iar;
>>>  		break;
>>> +	case SYS_ICC_EOIR1_EL1:
>>> +		fn = __vgic_v3_write_eoir;
>>> +		break;
>>>  	case SYS_ICC_GRPEN1_EL1:
>>>  		if (is_read)
>>>  			fn = __vgic_v3_read_igrpen1;
>>
>> Looks good to me
>>
>> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> 
> Thanks!
> 
> 	M.
> 

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-31  6:33         ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-31  6:33 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 30/05/2017 16:24, Marc Zyngier wrote:
> On 30/05/17 08:48, Auger Eric wrote:
>> Hi Marc
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>>> register. This involves dropping the priority of the interrupt,
>>> and deactivating it if required (EOImode == 0).
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>>  2 files changed, 121 insertions(+)
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index 7610ea4e8337..c56d9bc2c904 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -403,6 +403,8 @@
>>>  
>>>  #define ICH_HCR_EN			(1 << 0)
>>>  #define ICH_HCR_UIE			(1 << 1)
>>> +#define ICH_HCR_EOIcount_SHIFT		27
>>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>  
>>>  #define ICH_VMCR_CBPR_SHIFT		4
>>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index 49aad1de3ac8..a76351b3ad66 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>  	return lr;
>>>  }
>>>  
>>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>>> +					       int intid, u64 *lr_val)
>>> +{
>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < used_lrs; i++) {
>>> +		u64 val = __gic_v3_get_lr(i);
>>> +
>>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>>> +		    (val & ICH_LR_ACTIVE_BIT)) {
>> I guess it is safe because we don't have yet virtual interrupts directly
>> mapped to phys IRQs, besides timer one?
> 
> What would that change? I don't see how having a HW interrupt here would
> be unsafe... Am I missing something?
I was thinking about the case of an HW mapped interrupt whose active
state must be observed at distributor level - as I understood the spec -
and not at LR level.

Thanks

Eric
> 
>>> +			*lr_val = val;
>>> +			return i;
>>> +		}
>>> +	}
>>> +
>>> +	*lr_val = ICC_IAR1_EL1_SPURIOUS;
>>> +	return -1;
>>> +}
>>> +
>>>  static int __hyp_text __vgic_v3_get_highest_active_priority(void)
>>>  {
>>>  	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> @@ -490,6 +510,44 @@ static void __hyp_text __vgic_v3_set_active_priority(u8 pre)
>>>  	__vgic_v3_write_ap1rn(val | bit, apr);
>>>  }
>>>  
>>> +static int __hyp_text __vgic_v3_clear_highest_active_priority(void)
>>> +{
>>> +	u8 nr_pre_bits = vtr_to_nr_pre_bits(read_gicreg(ICH_VTR_EL2));
>>> +	u8 nr_aprs = 1 << (nr_pre_bits - 5);
>> may be worth to introduce a macro to compute the number of APRn regs.
>> This may be more understandable.
> 
> Sure, will do.
> 
>>> +	u32 hap = 0;
>>> +	int i;
>>> +
>>> +	for (i = 0; i < nr_aprs; i++) {
>>> +		u32 ap0, ap1;
>>> +		int c0, c1;
>>> +
>>> +		ap0 = __vgic_v3_read_ap0rn(i);
>>> +		ap1 = __vgic_v3_read_ap1rn(i);
>>> +		if (!ap0 && !ap1) {
>>> +			hap += 32;
>>> +			continue;
>>> +		}
>>> +
>>> +		c0 = ap0 ? __ffs(ap0) : 32;
>>> +		c1 = ap1 ? __ffs(ap1) : 32;
>>> +
>>> +		/* Always clear the LSB, which is the highest priority */
>>> +		if (c0 < c1) {
>>> +			ap0 &= ap0 - 1;
>>> +			__vgic_v3_write_ap0rn(ap0, i);
>>> +			hap += c0;
>>> +		} else {
>>> +			ap1 &= ap1 - 1;
>>> +			__vgic_v3_write_ap1rn(ap1, i);
>>> +			hap += c1;
>>> +		}
>>> +
>>> +		return hap << (8 - nr_pre_bits);
>>> +	}
>>> +
>>> +	return GICv3_IDLE_PRIORITY;
>>> +}
>>> +
>>>  static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>>  {
>>>  	u64 lr_val;
>>> @@ -526,6 +584,64 @@ static void __hyp_text __vgic_v3_read_iar(struct kvm_vcpu *vcpu, u32 vmcr, int r
>>>  	vcpu_set_reg(vcpu, rt, ICC_IAR1_EL1_SPURIOUS);
>>>  }
>>>  
>>> +static void __hyp_text __vgic_v3_clear_active_lr(int lr, u64 lr_val)
>>> +{
>>> +	lr_val &= ~ICH_LR_ACTIVE_BIT;
>>> +	if (lr_val & ICH_LR_HW) {
>>> +		u32 pid;
>> nit: insert a line
> 
> OK.
> 
>>> +		pid = (lr_val & ICH_LR_PHYS_ID_MASK) >> ICH_LR_PHYS_ID_SHIFT;
>>> +		gic_write_dir(pid);
>>> +	}
>>> +
>>> +	__gic_v3_set_lr(lr_val, lr);
>>> +}
>>> +
>>> +static void __hyp_text __vgic_v3_bump_eoicount(void)
>>> +{
>>> +	u32 hcr;
>>> +
>>> +	hcr = read_gicreg(ICH_HCR_EL2);
>>> +	hcr += 1 << ICH_HCR_EOIcount_SHIFT;
>>> +	write_gicreg(hcr, ICH_HCR_EL2);
>>> +}
>>> +
>>> +static void __hyp_text __vgic_v3_write_eoir(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>> +{
>>> +	u32 vid = vcpu_get_reg(vcpu, rt);
>>> +	u64 lr_val;
>>> +	u8 lr_prio, act_prio;
>>> +	int lr, grp;
>>> +
>>> +	grp = __vgic_v3_get_group(vcpu);
>>> +
>>> +	/* Drop priority in any case */
>>> +	act_prio = __vgic_v3_clear_highest_active_priority();
>>> +
>>> +	/* If EOIing an LPI, no deactivate to be performed */
>>> +	if (vid >= VGIC_MIN_LPI)
>>> +		return;
>>> +
>>> +	/* EOImode == 1, nothing to be done here */
>>> +	if (vmcr & ICH_VMCR_EOIM_MASK)
>>> +		return;
>>> +
>>> +	lr = __vgic_v3_find_active_lr(vcpu, vid, &lr_val);
>>> +	if (lr == -1) {
>>> +		__vgic_v3_bump_eoicount();
>>> +		return;
>>> +	}
>>> +
>>> +	lr_prio = (lr_val & ICH_LR_PRIORITY_MASK) >> ICH_LR_PRIORITY_SHIFT;
>>> +
>>> +	/* If priorities or group do not match, the guest has fscked-up. */
>>> +	if (grp != !!(lr_val & ICH_LR_GROUP) ||
>>> +	    __vgic_v3_pri_to_pre(lr_prio, vmcr, grp) != act_prio)
>>> +		return;
>>> +
>>> +	/* Let's now perform the deactivation */
>>> +	__vgic_v3_clear_active_lr(lr, lr_val);
>>> +}
>>> +
>>>  static void __hyp_text __vgic_v3_read_igrpen1(struct kvm_vcpu *vcpu, u32 vmcr, int rt)
>>>  {
>>>  	vcpu_set_reg(vcpu, rt, !!(vmcr & ICH_VMCR_ENG1_MASK));
>>> @@ -591,6 +707,9 @@ int __hyp_text __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu)
>>>  	case SYS_ICC_IAR1_EL1:
>>>  		fn = __vgic_v3_read_iar;
>>>  		break;
>>> +	case SYS_ICC_EOIR1_EL1:
>>> +		fn = __vgic_v3_write_eoir;
>>> +		break;
>>>  	case SYS_ICC_GRPEN1_EL1:
>>>  		if (is_read)
>>>  			fn = __vgic_v3_read_igrpen1;
>>
>> Looks good to me
>>
>> Reviewed-by: Eric Auger <eric.auger@redhat.com>
> 
> Thanks!
> 
> 	M.
> 

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

* Re: [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
  2017-05-30 14:32       ` Marc Zyngier
@ 2017-05-31  6:43         ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-31  6:43 UTC (permalink / raw)
  To: Marc Zyngier, Christoffer Dall
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	kvmarm, linux-arm-kernel

Hi Marc,

On 30/05/2017 16:32, Marc Zyngier wrote:
> On 30/05/17 10:07, Auger Eric wrote:
>> Hi Marc,
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> In order to be able to trap Group-1 GICv3 system registers, we need to
>>> set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
>> before, conditionally
>>> done after having restored the guest's state, and cleared on exit.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/irqchip/arm-gic-v3.h | 1 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
>>>  virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
>>>  3 files changed, 12 insertions(+)
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index c56d9bc2c904..a1739843343e 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -403,6 +403,7 @@
>>>  
>>>  #define ICH_HCR_EN			(1 << 0)
>>>  #define ICH_HCR_UIE			(1 << 1)
>>> +#define ICH_HCR_TALL1			(1 << 12)
>>>  #define ICH_HCR_EOIcount_SHIFT		27
>>>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>  
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index a521e105ade1..a27671b1e9af 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -257,6 +257,9 @@ 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))
>>> +			write_gicreg(0, ICH_HCR_EL2);
>> Not directly related to this patch but this is not obvious to me why we
>> reset the ICH_HCR_EL2 only when used_lrs != 0.
> 
> That's because if there is no interrupt to inject, then we've never
> enabled the virtual CPU interface, and we've only configured VMCR.
> 
>>> +
>>>  		cpu_if->vgic_elrsr = 0xffff;
>>>  		cpu_if->vgic_ap0r[0] = 0;
>>>  		cpu_if->vgic_ap0r[1] = 0;
>>> @@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>>>  
>>>  		for (i = 0; i < used_lrs; i++)
>>>  			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
>>> +	} else {
>>> +		/* Always write ICH_HCR_EL2 to enable trapping */
>> "always" is a bit weird as this is conditional
> 
> Ah, true. How about:
> 		/*
>                  * If we don't have any interrupt to inject, but that
> 		 * trapping is enabled, write the ICH_HCR_EL2 config.
> 		 */
yes thanks
> 
>>> +		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
>>> +			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
>> and same question here. Why don't we always restore the ICH_HCR_EL2.
>> Assuming when exiting the guest the vCPU I/F was enabled and used_lrs=0,
> 
> That case doesn't exist. The only case where we enable the virtual cpuif
> is when we have something to inject (hence used_lrs != 0).

I got it. Thanks for the explanation.

Eric
> 
>> when restoring don't we leave the vCPU I/F disabled? I must miss
>> something but I don't find who is re-enabling the vCPU I/F in that case?
> 
> See above. This case shouldn't exist, and is only introduced here for
> the benefit of the trapping.
> 
>>>  	}
>>>  
>>>  	/*
>>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>>> index 063526443781..547b8374fb64 100644
>>> --- a/virt/kvm/arm/vgic/vgic-v3.c
>>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>>> @@ -21,6 +21,8 @@
>>>  
>>>  #include "vgic.h"
>>>  
>>> +static bool group1_trap;
>>> +
>>>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>>>  {
>>>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>>> @@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>>>  
>>>  	/* Get the show on the road... */
>>>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
>>> +	if (group1_trap)
>> I don't remember the rationale behind using the bool here and using
>> static_branch_unlikely in the other cases.
> 
> That's just the initial config path, before setting the static key.
> 
>>
>> May be good to squash the next patch to understand how group1_trap is set.
> 
> Sure, I'll have a look at that.
> 
> Thanks,
> 
> 	M.
> 

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

* [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers
@ 2017-05-31  6:43         ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-31  6:43 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 30/05/2017 16:32, Marc Zyngier wrote:
> On 30/05/17 10:07, Auger Eric wrote:
>> Hi Marc,
>>
>> On 03/05/2017 12:45, Marc Zyngier wrote:
>>> In order to be able to trap Group-1 GICv3 system registers, we need to
>>> set ICH_HCR_EL2.TALL1 begore entering the guest. This is conditionnaly
>> before, conditionally
>>> done after having restored the guest's state, and cleared on exit.
>>>
>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>> ---
>>>  include/linux/irqchip/arm-gic-v3.h | 1 +
>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 7 +++++++
>>>  virt/kvm/arm/vgic/vgic-v3.c        | 4 ++++
>>>  3 files changed, 12 insertions(+)
>>>
>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>> index c56d9bc2c904..a1739843343e 100644
>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>> @@ -403,6 +403,7 @@
>>>  
>>>  #define ICH_HCR_EN			(1 << 0)
>>>  #define ICH_HCR_UIE			(1 << 1)
>>> +#define ICH_HCR_TALL1			(1 << 12)
>>>  #define ICH_HCR_EOIcount_SHIFT		27
>>>  #define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>  
>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> index a521e105ade1..a27671b1e9af 100644
>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>> @@ -257,6 +257,9 @@ 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))
>>> +			write_gicreg(0, ICH_HCR_EL2);
>> Not directly related to this patch but this is not obvious to me why we
>> reset the ICH_HCR_EL2 only when used_lrs != 0.
> 
> That's because if there is no interrupt to inject, then we've never
> enabled the virtual CPU interface, and we've only configured VMCR.
> 
>>> +
>>>  		cpu_if->vgic_elrsr = 0xffff;
>>>  		cpu_if->vgic_ap0r[0] = 0;
>>>  		cpu_if->vgic_ap0r[1] = 0;
>>> @@ -329,6 +332,10 @@ void __hyp_text __vgic_v3_restore_state(struct kvm_vcpu *vcpu)
>>>  
>>>  		for (i = 0; i < used_lrs; i++)
>>>  			__gic_v3_set_lr(cpu_if->vgic_lr[i], i);
>>> +	} else {
>>> +		/* Always write ICH_HCR_EL2 to enable trapping */
>> "always" is a bit weird as this is conditional
> 
> Ah, true. How about:
> 		/*
>                  * If we don't have any interrupt to inject, but that
> 		 * trapping is enabled, write the ICH_HCR_EL2 config.
> 		 */
yes thanks
> 
>>> +		if (static_branch_unlikely(&vgic_v3_cpuif_trap))
>>> +			write_gicreg(cpu_if->vgic_hcr, ICH_HCR_EL2);
>> and same question here. Why don't we always restore the ICH_HCR_EL2.
>> Assuming when exiting the guest the vCPU I/F was enabled and used_lrs=0,
> 
> That case doesn't exist. The only case where we enable the virtual cpuif
> is when we have something to inject (hence used_lrs != 0).

I got it. Thanks for the explanation.

Eric
> 
>> when restoring don't we leave the vCPU I/F disabled? I must miss
>> something but I don't find who is re-enabling the vCPU I/F in that case?
> 
> See above. This case shouldn't exist, and is only introduced here for
> the benefit of the trapping.
> 
>>>  	}
>>>  
>>>  	/*
>>> diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
>>> index 063526443781..547b8374fb64 100644
>>> --- a/virt/kvm/arm/vgic/vgic-v3.c
>>> +++ b/virt/kvm/arm/vgic/vgic-v3.c
>>> @@ -21,6 +21,8 @@
>>>  
>>>  #include "vgic.h"
>>>  
>>> +static bool group1_trap;
>>> +
>>>  void vgic_v3_set_underflow(struct kvm_vcpu *vcpu)
>>>  {
>>>  	struct vgic_v3_cpu_if *cpuif = &vcpu->arch.vgic_cpu.vgic_v3;
>>> @@ -239,6 +241,8 @@ void vgic_v3_enable(struct kvm_vcpu *vcpu)
>>>  
>>>  	/* Get the show on the road... */
>>>  	vgic_v3->vgic_hcr = ICH_HCR_EN;
>>> +	if (group1_trap)
>> I don't remember the rationale behind using the bool here and using
>> static_branch_unlikely in the other cases.
> 
> That's just the initial config path, before setting the static key.
> 
>>
>> May be good to squash the next patch to understand how group1_trap is set.
> 
> Sure, I'll have a look at that.
> 
> Thanks,
> 
> 	M.
> 

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-31  6:33         ` Auger Eric
  (?)
@ 2017-05-31  6:46           ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-31  6:46 UTC (permalink / raw)
  To: Auger Eric
  Cc: Christoffer Dall, Mark Rutland, kvm, David Daney,
	Catalin Marinas, Robert Richter, kvmarm, linux-arm-kernel

On Wed, 31 May 2017 08:33:05 +0200
Auger Eric <eric.auger@redhat.com> wrote:

> Hi Marc,
> 
> On 30/05/2017 16:24, Marc Zyngier wrote:
> > On 30/05/17 08:48, Auger Eric wrote:  
> >> Hi Marc
> >>
> >> On 03/05/2017 12:45, Marc Zyngier wrote:  
> >>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
> >>> register. This involves dropping the priority of the interrupt,
> >>> and deactivating it if required (EOImode == 0).
> >>>
> >>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >>> ---
> >>>  include/linux/irqchip/arm-gic-v3.h |   2 +
> >>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
> >>>  2 files changed, 121 insertions(+)
> >>>
> >>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> >>> index 7610ea4e8337..c56d9bc2c904 100644
> >>> --- a/include/linux/irqchip/arm-gic-v3.h
> >>> +++ b/include/linux/irqchip/arm-gic-v3.h
> >>> @@ -403,6 +403,8 @@
> >>>  
> >>>  #define ICH_HCR_EN			(1 << 0)
> >>>  #define ICH_HCR_UIE			(1 << 1)
> >>> +#define ICH_HCR_EOIcount_SHIFT		27
> >>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
> >>>  
> >>>  #define ICH_VMCR_CBPR_SHIFT		4
> >>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
> >>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> index 49aad1de3ac8..a76351b3ad66 100644
> >>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
> >>>  	return lr;
> >>>  }
> >>>  
> >>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
> >>> +					       int intid, u64 *lr_val)
> >>> +{
> >>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> >>> +	int i;
> >>> +
> >>> +	for (i = 0; i < used_lrs; i++) {
> >>> +		u64 val = __gic_v3_get_lr(i);
> >>> +
> >>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
> >>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
> >> I guess it is safe because we don't have yet virtual interrupts directly
> >> mapped to phys IRQs, besides timer one?  
> > 
> > What would that change? I don't see how having a HW interrupt here would
> > be unsafe... Am I missing something?  
> I was thinking about the case of an HW mapped interrupt whose active
> state must be observed at distributor level - as I understood the spec -
> and not at LR level.

What part of the spec are you referring to?

A virtual interrupt, even backed by a HW interrupt, does have an active
state (unless it is an LPI). The only state we cannot observe in the LR
when the HW bit is set is the Active+Pending state because the pending
bit is then at the physical distributor level.

For all intent and purposes, the active state in the LR behaves the
same, irrespective of the HW state, until the guest issues a
deactivation (either using EOI or DIR, depending on EOImode).

Thanks,

	M.
-- 
Without deviation from the norm, progress is not possible.

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-31  6:46           ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-31  6:46 UTC (permalink / raw)
  To: Auger Eric
  Cc: Christoffer Dall, Mark Rutland, kvm, David Daney,
	Catalin Marinas, Robert Richter, kvmarm, linux-arm-kernel

On Wed, 31 May 2017 08:33:05 +0200
Auger Eric <eric.auger@redhat.com> wrote:

> Hi Marc,
> 
> On 30/05/2017 16:24, Marc Zyngier wrote:
> > On 30/05/17 08:48, Auger Eric wrote:  
> >> Hi Marc
> >>
> >> On 03/05/2017 12:45, Marc Zyngier wrote:  
> >>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
> >>> register. This involves dropping the priority of the interrupt,
> >>> and deactivating it if required (EOImode == 0).
> >>>
> >>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >>> ---
> >>>  include/linux/irqchip/arm-gic-v3.h |   2 +
> >>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
> >>>  2 files changed, 121 insertions(+)
> >>>
> >>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> >>> index 7610ea4e8337..c56d9bc2c904 100644
> >>> --- a/include/linux/irqchip/arm-gic-v3.h
> >>> +++ b/include/linux/irqchip/arm-gic-v3.h
> >>> @@ -403,6 +403,8 @@
> >>>  
> >>>  #define ICH_HCR_EN			(1 << 0)
> >>>  #define ICH_HCR_UIE			(1 << 1)
> >>> +#define ICH_HCR_EOIcount_SHIFT		27
> >>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
> >>>  
> >>>  #define ICH_VMCR_CBPR_SHIFT		4
> >>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
> >>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> index 49aad1de3ac8..a76351b3ad66 100644
> >>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
> >>>  	return lr;
> >>>  }
> >>>  
> >>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
> >>> +					       int intid, u64 *lr_val)
> >>> +{
> >>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> >>> +	int i;
> >>> +
> >>> +	for (i = 0; i < used_lrs; i++) {
> >>> +		u64 val = __gic_v3_get_lr(i);
> >>> +
> >>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
> >>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
> >> I guess it is safe because we don't have yet virtual interrupts directly
> >> mapped to phys IRQs, besides timer one?  
> > 
> > What would that change? I don't see how having a HW interrupt here would
> > be unsafe... Am I missing something?  
> I was thinking about the case of an HW mapped interrupt whose active
> state must be observed at distributor level - as I understood the spec -
> and not at LR level.

What part of the spec are you referring to?

A virtual interrupt, even backed by a HW interrupt, does have an active
state (unless it is an LPI). The only state we cannot observe in the LR
when the HW bit is set is the Active+Pending state because the pending
bit is then at the physical distributor level.

For all intent and purposes, the active state in the LR behaves the
same, irrespective of the HW state, until the guest issues a
deactivation (either using EOI or DIR, depending on EOImode).

Thanks,

	M.
-- 
Without deviation from the norm, progress is not possible.

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-31  6:46           ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-31  6:46 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, 31 May 2017 08:33:05 +0200
Auger Eric <eric.auger@redhat.com> wrote:

> Hi Marc,
> 
> On 30/05/2017 16:24, Marc Zyngier wrote:
> > On 30/05/17 08:48, Auger Eric wrote:  
> >> Hi Marc
> >>
> >> On 03/05/2017 12:45, Marc Zyngier wrote:  
> >>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
> >>> register. This involves dropping the priority of the interrupt,
> >>> and deactivating it if required (EOImode == 0).
> >>>
> >>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
> >>> ---
> >>>  include/linux/irqchip/arm-gic-v3.h |   2 +
> >>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
> >>>  2 files changed, 121 insertions(+)
> >>>
> >>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
> >>> index 7610ea4e8337..c56d9bc2c904 100644
> >>> --- a/include/linux/irqchip/arm-gic-v3.h
> >>> +++ b/include/linux/irqchip/arm-gic-v3.h
> >>> @@ -403,6 +403,8 @@
> >>>  
> >>>  #define ICH_HCR_EN			(1 << 0)
> >>>  #define ICH_HCR_UIE			(1 << 1)
> >>> +#define ICH_HCR_EOIcount_SHIFT		27
> >>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
> >>>  
> >>>  #define ICH_VMCR_CBPR_SHIFT		4
> >>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
> >>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> index 49aad1de3ac8..a76351b3ad66 100644
> >>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
> >>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
> >>>  	return lr;
> >>>  }
> >>>  
> >>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
> >>> +					       int intid, u64 *lr_val)
> >>> +{
> >>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
> >>> +	int i;
> >>> +
> >>> +	for (i = 0; i < used_lrs; i++) {
> >>> +		u64 val = __gic_v3_get_lr(i);
> >>> +
> >>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
> >>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
> >> I guess it is safe because we don't have yet virtual interrupts directly
> >> mapped to phys IRQs, besides timer one?  
> > 
> > What would that change? I don't see how having a HW interrupt here would
> > be unsafe... Am I missing something?  
> I was thinking about the case of an HW mapped interrupt whose active
> state must be observed at distributor level - as I understood the spec -
> and not at LR level.

What part of the spec are you referring to?

A virtual interrupt, even backed by a HW interrupt, does have an active
state (unless it is an LPI). The only state we cannot observe in the LR
when the HW bit is set is the Active+Pending state because the pending
bit is then at the physical distributor level.

For all intent and purposes, the active state in the LR behaves the
same, irrespective of the HW state, until the guest issues a
deactivation (either using EOI or DIR, depending on EOImode).

Thanks,

	M.
-- 
Without deviation from the norm, progress is not possible.

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-31  6:46           ` Marc Zyngier
@ 2017-05-31  7:26             ` Auger Eric
  -1 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-31  7:26 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Mark Rutland, kvm, David Daney, Catalin Marinas, Robert Richter,
	linux-arm-kernel, kvmarm, Christoffer Dall

Hi Marc,

On 31/05/2017 08:46, Marc Zyngier wrote:
> On Wed, 31 May 2017 08:33:05 +0200
> Auger Eric <eric.auger@redhat.com> wrote:
> 
>> Hi Marc,
>>
>> On 30/05/2017 16:24, Marc Zyngier wrote:
>>> On 30/05/17 08:48, Auger Eric wrote:  
>>>> Hi Marc
>>>>
>>>> On 03/05/2017 12:45, Marc Zyngier wrote:  
>>>>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>>>>> register. This involves dropping the priority of the interrupt,
>>>>> and deactivating it if required (EOImode == 0).
>>>>>
>>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>>> ---
>>>>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>>>>  2 files changed, 121 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>>>> index 7610ea4e8337..c56d9bc2c904 100644
>>>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>>>> @@ -403,6 +403,8 @@
>>>>>  
>>>>>  #define ICH_HCR_EN			(1 << 0)
>>>>>  #define ICH_HCR_UIE			(1 << 1)
>>>>> +#define ICH_HCR_EOIcount_SHIFT		27
>>>>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>>>  
>>>>>  #define ICH_VMCR_CBPR_SHIFT		4
>>>>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>>>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>> index 49aad1de3ac8..a76351b3ad66 100644
>>>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>>>  	return lr;
>>>>>  }
>>>>>  
>>>>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>>>>> +					       int intid, u64 *lr_val)
>>>>> +{
>>>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>>>> +	int i;
>>>>> +
>>>>> +	for (i = 0; i < used_lrs; i++) {
>>>>> +		u64 val = __gic_v3_get_lr(i);
>>>>> +
>>>>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>>>>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
>>>> I guess it is safe because we don't have yet virtual interrupts directly
>>>> mapped to phys IRQs, besides timer one?  
>>>
>>> What would that change? I don't see how having a HW interrupt here would
>>> be unsafe... Am I missing something?  
>> I was thinking about the case of an HW mapped interrupt whose active
>> state must be observed at distributor level - as I understood the spec -
>> and not at LR level.
> 
> What part of the spec are you referring to?
> 
> A virtual interrupt, even backed by a HW interrupt, does have an active
> state (unless it is an LPI). The only state we cannot observe in the LR
> when the HW bit is set is the Active+Pending state because the pending
> bit is then at the physical distributor level.
> 
> For all intent and purposes, the active state in the LR behaves the
> same, irrespective of the HW state, until the guest issues a
> deactivation (either using EOI or DIR, depending on EOImode).

Hum OK. I was referring to the note in table 5-9 of IHI0048B2 but
effectively I added a "s" where there is none :-(

"
For hardware interrupts, the pending and active state is held in the
physical Distributor rather than the virtual
CPU interface. A hypervisor must only use the pending and active state
for software originated interrupts
associated with virtual devices, or SGIs.
"

Sorry for the noise.

Eric

> 
> Thanks,
> 
> 	M.
> 

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-31  7:26             ` Auger Eric
  0 siblings, 0 replies; 162+ messages in thread
From: Auger Eric @ 2017-05-31  7:26 UTC (permalink / raw)
  To: linux-arm-kernel

Hi Marc,

On 31/05/2017 08:46, Marc Zyngier wrote:
> On Wed, 31 May 2017 08:33:05 +0200
> Auger Eric <eric.auger@redhat.com> wrote:
> 
>> Hi Marc,
>>
>> On 30/05/2017 16:24, Marc Zyngier wrote:
>>> On 30/05/17 08:48, Auger Eric wrote:  
>>>> Hi Marc
>>>>
>>>> On 03/05/2017 12:45, Marc Zyngier wrote:  
>>>>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>>>>> register. This involves dropping the priority of the interrupt,
>>>>> and deactivating it if required (EOImode == 0).
>>>>>
>>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>>> ---
>>>>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>>>>  2 files changed, 121 insertions(+)
>>>>>
>>>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>>>> index 7610ea4e8337..c56d9bc2c904 100644
>>>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>>>> @@ -403,6 +403,8 @@
>>>>>  
>>>>>  #define ICH_HCR_EN			(1 << 0)
>>>>>  #define ICH_HCR_UIE			(1 << 1)
>>>>> +#define ICH_HCR_EOIcount_SHIFT		27
>>>>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>>>  
>>>>>  #define ICH_VMCR_CBPR_SHIFT		4
>>>>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>>>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>> index 49aad1de3ac8..a76351b3ad66 100644
>>>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>>>  	return lr;
>>>>>  }
>>>>>  
>>>>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>>>>> +					       int intid, u64 *lr_val)
>>>>> +{
>>>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>>>> +	int i;
>>>>> +
>>>>> +	for (i = 0; i < used_lrs; i++) {
>>>>> +		u64 val = __gic_v3_get_lr(i);
>>>>> +
>>>>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>>>>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
>>>> I guess it is safe because we don't have yet virtual interrupts directly
>>>> mapped to phys IRQs, besides timer one?  
>>>
>>> What would that change? I don't see how having a HW interrupt here would
>>> be unsafe... Am I missing something?  
>> I was thinking about the case of an HW mapped interrupt whose active
>> state must be observed at distributor level - as I understood the spec -
>> and not at LR level.
> 
> What part of the spec are you referring to?
> 
> A virtual interrupt, even backed by a HW interrupt, does have an active
> state (unless it is an LPI). The only state we cannot observe in the LR
> when the HW bit is set is the Active+Pending state because the pending
> bit is then at the physical distributor level.
> 
> For all intent and purposes, the active state in the LR behaves the
> same, irrespective of the HW state, until the guest issues a
> deactivation (either using EOI or DIR, depending on EOImode).

Hum OK. I was referring to the note in table 5-9 of IHI0048B2 but
effectively I added a "s" where there is none :-(

"
For hardware interrupts, the pending and active state is held in the
physical Distributor rather than the virtual
CPU interface. A hypervisor must only use the pending and active state
for software originated interrupts
associated with virtual devices, or SGIs.
"

Sorry for the noise.

Eric

> 
> Thanks,
> 
> 	M.
> 

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

* Re: [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
  2017-05-31  7:26             ` Auger Eric
@ 2017-05-31  7:54               ` Marc Zyngier
  -1 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-31  7:54 UTC (permalink / raw)
  To: Auger Eric
  Cc: kvm, David Daney, Catalin Marinas, Robert Richter, kvmarm,
	linux-arm-kernel

On 31/05/17 08:26, Auger Eric wrote:
> Hi Marc,
> 
> On 31/05/2017 08:46, Marc Zyngier wrote:
>> On Wed, 31 May 2017 08:33:05 +0200
>> Auger Eric <eric.auger@redhat.com> wrote:
>>
>>> Hi Marc,
>>>
>>> On 30/05/2017 16:24, Marc Zyngier wrote:
>>>> On 30/05/17 08:48, Auger Eric wrote:  
>>>>> Hi Marc
>>>>>
>>>>> On 03/05/2017 12:45, Marc Zyngier wrote:  
>>>>>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>>>>>> register. This involves dropping the priority of the interrupt,
>>>>>> and deactivating it if required (EOImode == 0).
>>>>>>
>>>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>>>> ---
>>>>>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>>>>>  2 files changed, 121 insertions(+)
>>>>>>
>>>>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>>>>> index 7610ea4e8337..c56d9bc2c904 100644
>>>>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>>>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>>>>> @@ -403,6 +403,8 @@
>>>>>>  
>>>>>>  #define ICH_HCR_EN			(1 << 0)
>>>>>>  #define ICH_HCR_UIE			(1 << 1)
>>>>>> +#define ICH_HCR_EOIcount_SHIFT		27
>>>>>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>>>>  
>>>>>>  #define ICH_VMCR_CBPR_SHIFT		4
>>>>>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>>>>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>>> index 49aad1de3ac8..a76351b3ad66 100644
>>>>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>>>>  	return lr;
>>>>>>  }
>>>>>>  
>>>>>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>>>>>> +					       int intid, u64 *lr_val)
>>>>>> +{
>>>>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>>>>> +	int i;
>>>>>> +
>>>>>> +	for (i = 0; i < used_lrs; i++) {
>>>>>> +		u64 val = __gic_v3_get_lr(i);
>>>>>> +
>>>>>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>>>>>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
>>>>> I guess it is safe because we don't have yet virtual interrupts directly
>>>>> mapped to phys IRQs, besides timer one?  
>>>>
>>>> What would that change? I don't see how having a HW interrupt here would
>>>> be unsafe... Am I missing something?  
>>> I was thinking about the case of an HW mapped interrupt whose active
>>> state must be observed at distributor level - as I understood the spec -
>>> and not at LR level.
>>
>> What part of the spec are you referring to?
>>
>> A virtual interrupt, even backed by a HW interrupt, does have an active
>> state (unless it is an LPI). The only state we cannot observe in the LR
>> when the HW bit is set is the Active+Pending state because the pending
>> bit is then at the physical distributor level.
>>
>> For all intent and purposes, the active state in the LR behaves the
>> same, irrespective of the HW state, until the guest issues a
>> deactivation (either using EOI or DIR, depending on EOImode).
> 
> Hum OK. I was referring to the note in table 5-9 of IHI0048B2 but
> effectively I added a "s" where there is none :-(
> 
> "
> For hardware interrupts, the pending and active state is held in the
> physical Distributor rather than the virtual
> CPU interface. A hypervisor must only use the pending and active state
> for software originated interrupts
> associated with virtual devices, or SGIs.
> "
> 
> Sorry for the noise.

No worries. I've pestered against this verbiage multiple times because
it is incredibly misleading for non native speakers (I misinterpreted
this "pending and active state" a couple of times myself). This is why I
wrote Active+Pending above, because it is less ambiguous.

The GICv3 spec contains the same subtlety in multiple places. Man, how I
hate this thing, it is unbelievable.

Thanks,

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

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

* [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler
@ 2017-05-31  7:54               ` Marc Zyngier
  0 siblings, 0 replies; 162+ messages in thread
From: Marc Zyngier @ 2017-05-31  7:54 UTC (permalink / raw)
  To: linux-arm-kernel

On 31/05/17 08:26, Auger Eric wrote:
> Hi Marc,
> 
> On 31/05/2017 08:46, Marc Zyngier wrote:
>> On Wed, 31 May 2017 08:33:05 +0200
>> Auger Eric <eric.auger@redhat.com> wrote:
>>
>>> Hi Marc,
>>>
>>> On 30/05/2017 16:24, Marc Zyngier wrote:
>>>> On 30/05/17 08:48, Auger Eric wrote:  
>>>>> Hi Marc
>>>>>
>>>>> On 03/05/2017 12:45, Marc Zyngier wrote:  
>>>>>> Add a handler for writing the guest's view of the ICC_EOIR1_EL1
>>>>>> register. This involves dropping the priority of the interrupt,
>>>>>> and deactivating it if required (EOImode == 0).
>>>>>>
>>>>>> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
>>>>>> ---
>>>>>>  include/linux/irqchip/arm-gic-v3.h |   2 +
>>>>>>  virt/kvm/arm/hyp/vgic-v3-sr.c      | 119 +++++++++++++++++++++++++++++++++++++
>>>>>>  2 files changed, 121 insertions(+)
>>>>>>
>>>>>> diff --git a/include/linux/irqchip/arm-gic-v3.h b/include/linux/irqchip/arm-gic-v3.h
>>>>>> index 7610ea4e8337..c56d9bc2c904 100644
>>>>>> --- a/include/linux/irqchip/arm-gic-v3.h
>>>>>> +++ b/include/linux/irqchip/arm-gic-v3.h
>>>>>> @@ -403,6 +403,8 @@
>>>>>>  
>>>>>>  #define ICH_HCR_EN			(1 << 0)
>>>>>>  #define ICH_HCR_UIE			(1 << 1)
>>>>>> +#define ICH_HCR_EOIcount_SHIFT		27
>>>>>> +#define ICH_HCR_EOIcount_MASK		(0x1f << ICH_HCR_EOIcount_SHIFT)
>>>>>>  
>>>>>>  #define ICH_VMCR_CBPR_SHIFT		4
>>>>>>  #define ICH_VMCR_CBPR_MASK		(1 << ICH_VMCR_CBPR_SHIFT)
>>>>>> diff --git a/virt/kvm/arm/hyp/vgic-v3-sr.c b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>>> index 49aad1de3ac8..a76351b3ad66 100644
>>>>>> --- a/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>>> +++ b/virt/kvm/arm/hyp/vgic-v3-sr.c
>>>>>> @@ -425,6 +425,26 @@ static int __hyp_text __vgic_v3_highest_priority_lr(struct kvm_vcpu *vcpu,
>>>>>>  	return lr;
>>>>>>  }
>>>>>>  
>>>>>> +static int __hyp_text __vgic_v3_find_active_lr(struct kvm_vcpu *vcpu,
>>>>>> +					       int intid, u64 *lr_val)
>>>>>> +{
>>>>>> +	unsigned int used_lrs = vcpu->arch.vgic_cpu.used_lrs;
>>>>>> +	int i;
>>>>>> +
>>>>>> +	for (i = 0; i < used_lrs; i++) {
>>>>>> +		u64 val = __gic_v3_get_lr(i);
>>>>>> +
>>>>>> +		if ((val & ICH_LR_VIRTUAL_ID_MASK) == intid &&
>>>>>> +		    (val & ICH_LR_ACTIVE_BIT)) {  
>>>>> I guess it is safe because we don't have yet virtual interrupts directly
>>>>> mapped to phys IRQs, besides timer one?  
>>>>
>>>> What would that change? I don't see how having a HW interrupt here would
>>>> be unsafe... Am I missing something?  
>>> I was thinking about the case of an HW mapped interrupt whose active
>>> state must be observed at distributor level - as I understood the spec -
>>> and not at LR level.
>>
>> What part of the spec are you referring to?
>>
>> A virtual interrupt, even backed by a HW interrupt, does have an active
>> state (unless it is an LPI). The only state we cannot observe in the LR
>> when the HW bit is set is the Active+Pending state because the pending
>> bit is then at the physical distributor level.
>>
>> For all intent and purposes, the active state in the LR behaves the
>> same, irrespective of the HW state, until the guest issues a
>> deactivation (either using EOI or DIR, depending on EOImode).
> 
> Hum OK. I was referring to the note in table 5-9 of IHI0048B2 but
> effectively I added a "s" where there is none :-(
> 
> "
> For hardware interrupts, the pending and active state is held in the
> physical Distributor rather than the virtual
> CPU interface. A hypervisor must only use the pending and active state
> for software originated interrupts
> associated with virtual devices, or SGIs.
> "
> 
> Sorry for the noise.

No worries. I've pestered against this verbiage multiple times because
it is incredibly misleading for non native speakers (I misinterpreted
this "pending and active state" a couple of times myself). This is why I
wrote Active+Pending above, because it is less ambiguous.

The GICv3 spec contains the same subtlety in multiple places. Man, how I
hate this thing, it is unbelievable.

Thanks,

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

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

* Re: [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-06-09 10:38     ` Catalin Marinas
  -1 siblings, 0 replies; 162+ messages in thread
From: Catalin Marinas @ 2017-06-09 10:38 UTC (permalink / raw)
  To: Marc Zyngier; +Cc: kvm, David Daney, Robert Richter, linux-arm-kernel, kvmarm

On Wed, May 03, 2017 at 11:45:43AM +0100, Marc Zyngier wrote:
> It is often useful to compare an ESR syndrome reporting the trapping
> of a system register with a value matching that system register.
> 
> Since encoding both the sysreg and the ESR version seem to be a bit
> overkill, let's add a set of macros that convert an ESR value into
> the corresponding sysreg encoding.
> 
> We handle both AArch32 and AArch64, taking advantage of identical
> encodings between system registers and CP15 accessors.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

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

* [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding
@ 2017-06-09 10:38     ` Catalin Marinas
  0 siblings, 0 replies; 162+ messages in thread
From: Catalin Marinas @ 2017-06-09 10:38 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 03, 2017 at 11:45:43AM +0100, Marc Zyngier wrote:
> It is often useful to compare an ESR syndrome reporting the trapping
> of a system register with a value matching that system register.
> 
> Since encoding both the sysreg and the ESR version seem to be a bit
> overkill, let's add a set of macros that convert an ESR value into
> the corresponding sysreg encoding.
> 
> We handle both AArch32 and AArch64, taking advantage of identical
> encodings between system registers and CP15 accessors.
> 
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

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

* Re: [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
  2017-05-03 10:45   ` Marc Zyngier
@ 2017-06-09 10:39     ` Catalin Marinas
  -1 siblings, 0 replies; 162+ messages in thread
From: Catalin Marinas @ 2017-06-09 10:39 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Christoffer Dall, Mark Rutland, kvm, David Daney, Robert Richter,
	kvmarm, linux-arm-kernel

On Wed, May 03, 2017 at 11:45:59AM +0100, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

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

* [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs
@ 2017-06-09 10:39     ` Catalin Marinas
  0 siblings, 0 replies; 162+ messages in thread
From: Catalin Marinas @ 2017-06-09 10:39 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 03, 2017 at 11:45:59AM +0100, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

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

* Re: [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
  2017-05-03 10:46   ` Marc Zyngier
@ 2017-06-09 10:43     ` Catalin Marinas
  -1 siblings, 0 replies; 162+ messages in thread
From: Catalin Marinas @ 2017-06-09 10:43 UTC (permalink / raw)
  To: Marc Zyngier
  Cc: Christoffer Dall, Mark Rutland, kvm, David Daney, Robert Richter,
	kvmarm, linux-arm-kernel

On Wed, May 03, 2017 at 11:46:00AM +0100, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Some Cavium Thunder CPUs suffer a problem where a KVM guest may
> inadvertently cause the host kernel to quit receiving interrupts.
> 
> Use the Group-0/1 trapping in order to deal with it.
> 
> [maz]: Adapted patch to the Group-0/1 trapping, reworked commit log
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

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

* [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115
@ 2017-06-09 10:43     ` Catalin Marinas
  0 siblings, 0 replies; 162+ messages in thread
From: Catalin Marinas @ 2017-06-09 10:43 UTC (permalink / raw)
  To: linux-arm-kernel

On Wed, May 03, 2017 at 11:46:00AM +0100, Marc Zyngier wrote:
> From: David Daney <david.daney@cavium.com>
> 
> Some Cavium Thunder CPUs suffer a problem where a KVM guest may
> inadvertently cause the host kernel to quit receiving interrupts.
> 
> Use the Group-0/1 trapping in order to deal with it.
> 
> [maz]: Adapted patch to the Group-0/1 trapping, reworked commit log
> 
> Signed-off-by: David Daney <david.daney@cavium.com>
> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>

Acked-by: Catalin Marinas <catalin.marinas@arm.com>

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

end of thread, other threads:[~2017-06-09 10:43 UTC | newest]

Thread overview: 162+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-05-03 10:45 [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2 Marc Zyngier
2017-05-03 10:45 ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 01/31] arm64: KVM: Fix decoding of Rt/Rt2 when trapping AArch32 CP accesses Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 02/31] arm64: KVM: Do not use stack-protector to compile EL2 code Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 03/31] arm: KVM: Do not use stack-protector to compile HYP code Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 04/31] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 05/31] KVM: arm/arm64: vgic-v3: " Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 06/31] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 07/31] KVM: arm/arm64: vgic-v3: Add accessors for the " Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 15:32   ` Mark Rutland
2017-05-03 15:32     ` Mark Rutland
2017-05-03 15:58     ` Marc Zyngier
2017-05-03 15:58       ` Marc Zyngier
2017-05-30 16:17       ` Marc Zyngier
2017-05-30 16:17         ` Marc Zyngier
2017-05-30 16:42         ` Mark Rutland
2017-05-30 16:42           ` Mark Rutland
2017-05-17  9:54   ` Auger Eric
2017-05-17  9:54     ` Auger Eric
2017-05-22 18:52     ` Marc Zyngier
2017-05-22 18:52       ` Marc Zyngier
2017-05-22 18:52       ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 08/31] arm64: Add a facility to turn an ESR syndrome into a sysreg encoding Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 15:35   ` Mark Rutland
2017-05-03 15:35     ` Mark Rutland
2017-05-17  9:54   ` Auger Eric
2017-05-17  9:54     ` Auger Eric
2017-06-09 10:38   ` Catalin Marinas
2017-06-09 10:38     ` Catalin Marinas
2017-05-03 10:45 ` [PATCH 09/31] KVM: arm64: Make kvm_condition_valid32() accessible from EL2 Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-17  9:54   ` Auger Eric
2017-05-17  9:54     ` Auger Eric
2017-05-03 10:45 ` [PATCH 10/31] KVM: arm64: vgic-v3: Add hook to handle guest GICv3 sysreg accesses at EL2 Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-17  9:54   ` Auger Eric
2017-05-17  9:54     ` Auger Eric
2017-05-03 10:45 ` [PATCH 11/31] KVM: arm64: vgic-v3: Add ICV_BPR1_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-17 15:39   ` Auger Eric
2017-05-17 15:39     ` Auger Eric
2017-05-03 10:45 ` [PATCH 12/31] KVM: arm64: vgic-v3: Add ICV_IGRPEN1_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-17 15:39   ` Auger Eric
2017-05-17 15:39     ` Auger Eric
2017-05-03 10:45 ` [PATCH 13/31] KVM: arm64: vgic-v3: Add ICV_IAR1_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-18  7:41   ` Auger Eric
2017-05-18  7:41     ` Auger Eric
2017-05-22 17:52     ` Marc Zyngier
2017-05-22 17:52       ` Marc Zyngier
2017-05-23  7:22       ` Auger Eric
2017-05-23  7:22         ` Auger Eric
2017-05-23  9:26         ` Marc Zyngier
2017-05-23  9:26           ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 14/31] KVM: arm64: vgic-v3: Add ICV_EOIR1_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  7:48   ` Auger Eric
2017-05-30  7:48     ` Auger Eric
2017-05-30 14:24     ` Marc Zyngier
2017-05-30 14:24       ` Marc Zyngier
2017-05-31  6:33       ` Auger Eric
2017-05-31  6:33         ` Auger Eric
2017-05-31  6:46         ` Marc Zyngier
2017-05-31  6:46           ` Marc Zyngier
2017-05-31  6:46           ` Marc Zyngier
2017-05-31  7:26           ` Auger Eric
2017-05-31  7:26             ` Auger Eric
2017-05-31  7:54             ` Marc Zyngier
2017-05-31  7:54               ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 15/31] KVM: arm64: vgic-v3: Add ICV_AP1Rn_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  7:48   ` Auger Eric
2017-05-30  7:48     ` Auger Eric
2017-05-30  8:02     ` Auger Eric
2017-05-30  8:02       ` Auger Eric
2017-05-30 14:21       ` Marc Zyngier
2017-05-30 14:21         ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 16/31] KVM: arm64: vgic-v3: Add ICV_HPPIR1_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  8:05   ` Auger Eric
2017-05-30  8:05     ` Auger Eric
2017-05-03 10:45 ` [PATCH 17/31] KVM: arm64: vgic-v3: Enable trapping of Group-1 system registers Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  9:07   ` Auger Eric
2017-05-30  9:07     ` Auger Eric
2017-05-30 14:32     ` Marc Zyngier
2017-05-30 14:32       ` Marc Zyngier
2017-05-31  6:43       ` Auger Eric
2017-05-31  6:43         ` Auger Eric
2017-05-03 10:45 ` [PATCH 18/31] KVM: arm64: Enable GICv3 Group-1 sysreg trapping via command-line Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 19/31] KVM: arm64: vgic-v3: Add ICV_BPR0_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  9:48   ` Auger Eric
2017-05-30  9:48     ` Auger Eric
2017-05-03 10:45 ` [PATCH 20/31] KVM: arm64: vgic-v3: Add ICV_IGNREN0_EL1 handler Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  9:48   ` Auger Eric
2017-05-30  9:48     ` Auger Eric
2017-05-03 10:45 ` [PATCH 21/31] KVM: arm64: vgic-v3: Add misc Group-0 handlers Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  9:48   ` Auger Eric
2017-05-30  9:48     ` Auger Eric
2017-05-03 10:45 ` [PATCH 22/31] KVM: arm64: vgic-v3: Enable trapping of Group-0 system registers Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  9:48   ` Auger Eric
2017-05-30  9:48     ` Auger Eric
2017-05-03 10:45 ` [PATCH 23/31] KVM: arm64: Enable GICv3 Group-0 sysreg trapping via command-line Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-03 10:45 ` [PATCH 24/31] arm64: Add MIDR values for Cavium cn83XX SoCs Marc Zyngier
2017-05-03 10:45   ` Marc Zyngier
2017-05-30  9:56   ` Auger Eric
2017-05-30  9:56     ` Auger Eric
2017-06-09 10:39   ` Catalin Marinas
2017-06-09 10:39     ` Catalin Marinas
2017-05-03 10:46 ` [PATCH 25/31] arm64: Add workaround for Cavium Thunder erratum 30115 Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30  9:56   ` Auger Eric
2017-05-30  9:56     ` Auger Eric
2017-06-09 10:43   ` Catalin Marinas
2017-06-09 10:43     ` Catalin Marinas
2017-05-03 10:46 ` [PATCH 26/31] KVM: arm64: vgic-v3: Add ICV_DIR_EL1 handler Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30 10:15   ` Auger Eric
2017-05-30 10:15     ` Auger Eric
2017-05-30 14:45     ` Marc Zyngier
2017-05-30 14:45       ` Marc Zyngier
2017-05-03 10:46 ` [PATCH 27/31] KVM: arm64: vgic-v3: Add ICV_RPR_EL1 handler Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30 10:16   ` Auger Eric
2017-05-30 10:16     ` Auger Eric
2017-05-03 10:46 ` [PATCH 28/31] KVM: arm64: vgic-v3: Add ICV_CTLR_EL1 handler Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30 10:27   ` Auger Eric
2017-05-30 10:27     ` Auger Eric
2017-05-03 10:46 ` [PATCH 29/31] KVM: arm64: vgic-v3: Add ICV_PMR_EL1 handler Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30 10:34   ` Auger Eric
2017-05-30 10:34     ` Auger Eric
2017-05-03 10:46 ` [PATCH 30/31] KVM: arm64: Enable GICv3 common sysreg trapping via command-line Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30  9:56   ` Auger Eric
2017-05-30  9:56     ` Auger Eric
2017-05-30 14:41     ` Marc Zyngier
2017-05-30 14:41       ` Marc Zyngier
2017-05-03 10:46 ` [PATCH 31/31] KVM: arm64: vgic-v3: Log which GICv3 system registers are trapped Marc Zyngier
2017-05-03 10:46   ` Marc Zyngier
2017-05-30  9:56   ` Auger Eric
2017-05-30  9:56     ` Auger Eric
2017-05-09  0:05 ` [PATCH 00/31] arm64: KVM: Mediate access to GICv3 sysregs at EL2 David Daney
2017-05-09  0:05   ` David Daney
2017-05-09 17:39   ` Marc Zyngier
2017-05-09 17:39     ` 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.