* [PULL 00/13] KVM/ARM Fixes for v4.12-rc2
@ 2017-05-18 9:47 Christoffer Dall
2017-05-18 9:47 ` [PULL 01/13] ARM: KVM: Fix tracepoint generation after move to virt/kvm/arm/ Christoffer Dall
` (13 more replies)
0 siblings, 14 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
Hi Radim and Paolo,
Here is a fairly large set of fixes post -rc1 for KVM/ARM.
The fixes include:
- A fix for a build failure introduced in -rc1 when tracepoints are
enabled on 32-bit ARM.
- Disabling use of stack pointer protection in the hyp code which can
cause panics.
- A handful of VGIC fixes.
- A fix to the init of the redistributors on GICv3 systems that
prevented boot with kvmtool on GICv3 systems introduced in -rc1.
- A number of race conditions fixed in our MMU handling code.
- A fix for the guest being able to program the debug extensions for
the host on the 32-bit side.
The following changes since commit 2ea659a9ef488125eb46da6eb571de5eae5c43f6:
Linux 4.12-rc1 (2017-05-13 13:19:49 -0700)
are available in the git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm.git tags/kvm-arm-for-v4.12-rc2
for you to fetch changes up to fa472fa91a5a0b241f5ddae927d2e235d07545df:
KVM: arm/arm64: Hold slots_lock when unregistering kvm io bus devices (2017-05-18 11:18:16 +0200)
Thanks,
-Christoffer
Christoffer Dall (2):
KVM: arm/arm64: Fix bug when registering redist iodevs
KVM: arm/arm64: Hold slots_lock when unregistering kvm io bus devices
Marc Zyngier (6):
ARM: KVM: Fix tracepoint generation after move to virt/kvm/arm/
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
Suzuki K Poulose (3):
kvm: arm/arm64: Fix race in resetting stage2 PGD
kvm: arm/arm64: Force reading uncached stage2 PGD
kvm: arm/arm64: Fix use after free of stage2 page table
Zhichao Huang (2):
KVM: arm: plug potential guest hardware debug leakage
KVM: arm: rename pm_fake handler to trap_raz_wi
arch/arm/include/asm/kvm_coproc.h | 3 +-
arch/arm/kvm/coproc.c | 106 ++++++++++++++++++++++++++------------
arch/arm/kvm/handle_exit.c | 4 +-
arch/arm/kvm/hyp/Makefile | 2 +
arch/arm/kvm/hyp/switch.c | 4 +-
arch/arm/kvm/trace.h | 8 +--
arch/arm64/kvm/hyp/Makefile | 2 +
include/kvm/arm_vgic.h | 5 +-
virt/kvm/arm/hyp/vgic-v3-sr.c | 18 +++----
virt/kvm/arm/mmu.c | 33 +++++++-----
virt/kvm/arm/vgic/vgic-init.c | 5 +-
virt/kvm/arm/vgic/vgic-mmio-v3.c | 12 +++--
virt/kvm/arm/vgic/vgic-v2.c | 7 +++
virt/kvm/arm/vgic/vgic-v3.c | 7 +++
14 files changed, 150 insertions(+), 66 deletions(-)
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PULL 01/13] ARM: KVM: Fix tracepoint generation after move to virt/kvm/arm/
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 02/13] arm64: KVM: Do not use stack-protector to compile EL2 code Christoffer Dall
` (12 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
Moving most of the shared code to virt/kvm/arm had for consequence
that KVM/ARM doesn't build anymore, because the code that used to
define the tracepoints is now somewhere else.
Fix this by defining CREATE_TRACE_POINTS in coproc.c, and clean-up
trace.h as well.
Fixes: 35d2d5d490e2 ("KVM: arm/arm64: Move shared files to virt/kvm/arm")
Reported-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
arch/arm/kvm/coproc.c | 1 +
arch/arm/kvm/trace.h | 8 ++++----
2 files changed, 5 insertions(+), 4 deletions(-)
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 2c14b69..ac8d36d 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -32,6 +32,7 @@
#include <asm/vfp.h>
#include "../vfp/vfpinstr.h"
+#define CREATE_TRACE_POINTS
#include "trace.h"
#include "coproc.h"
diff --git a/arch/arm/kvm/trace.h b/arch/arm/kvm/trace.h
index fc09437..b0d1064 100644
--- a/arch/arm/kvm/trace.h
+++ b/arch/arm/kvm/trace.h
@@ -1,5 +1,5 @@
-#if !defined(_TRACE_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACE_KVM_H
+#if !defined(_TRACE_ARM_KVM_H) || defined(TRACE_HEADER_MULTI_READ)
+#define _TRACE_ARM_KVM_H
#include <linux/tracepoint.h>
@@ -74,10 +74,10 @@ TRACE_EVENT(kvm_hvc,
__entry->vcpu_pc, __entry->r0, __entry->imm)
);
-#endif /* _TRACE_KVM_H */
+#endif /* _TRACE_ARM_KVM_H */
#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH arch/arm/kvm
+#define TRACE_INCLUDE_PATH .
#undef TRACE_INCLUDE_FILE
#define TRACE_INCLUDE_FILE trace
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 02/13] arm64: KVM: Do not use stack-protector to compile EL2 code
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
2017-05-18 9:47 ` [PULL 01/13] ARM: KVM: Fix tracepoint generation after move to virt/kvm/arm/ Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 03/13] arm: KVM: Do not use stack-protector to compile HYP code Christoffer Dall
` (11 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
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>
Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
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 aaf42ae..14c4e3b 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.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 03/13] arm: KVM: Do not use stack-protector to compile HYP code
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
2017-05-18 9:47 ` [PULL 01/13] ARM: KVM: Fix tracepoint generation after move to virt/kvm/arm/ Christoffer Dall
2017-05-18 9:47 ` [PULL 02/13] arm64: KVM: Do not use stack-protector to compile EL2 code Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 04/13] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt Christoffer Dall
` (10 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
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>
Acked-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
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 3023bb5..8679405 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.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 04/13] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (2 preceding siblings ...)
2017-05-18 9:47 ` [PULL 03/13] arm: KVM: Do not use stack-protector to compile HYP code Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 05/13] KVM: arm/arm64: vgic-v3: " Christoffer Dall
` (9 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
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>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
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 a65757a..504b4bd 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.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 05/13] KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW interrupt
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (3 preceding siblings ...)
2017-05-18 9:47 ` [PULL 04/13] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 06/13] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers Christoffer Dall
` (8 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
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>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
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 8fa737e..6fe3f00 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.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 06/13] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (4 preceding siblings ...)
2017-05-18 9:47 ` [PULL 05/13] KVM: arm/arm64: vgic-v3: " Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 07/13] kvm: arm/arm64: Fix race in resetting stage2 PGD Christoffer Dall
` (7 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Marc Zyngier <marc.zyngier@arm.com>
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>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
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 bce6037..32c3295 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.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 07/13] kvm: arm/arm64: Fix race in resetting stage2 PGD
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (5 preceding siblings ...)
2017-05-18 9:47 ` [PULL 06/13] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 08/13] KVM: arm: plug potential guest hardware debug leakage Christoffer Dall
` (6 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com>
In kvm_free_stage2_pgd() we check the stage2 PGD before holding
the lock and proceed to take the lock if it is valid. And we unmap
the page tables, followed by releasing the lock. We reset the PGD
only after dropping this lock, which could cause a race condition
where another thread waiting on or even holding the lock, could
potentially see that the PGD is still valid and proceed to perform
a stage2 operation and later encounter a NULL PGD.
[223090.242280] Unable to handle kernel NULL pointer dereference at
virtual address 00000040
[223090.262330] PC is at unmap_stage2_range+0x8c/0x428
[223090.262332] LR is at kvm_unmap_hva_handler+0x2c/0x3c
[223090.262531] Call trace:
[223090.262533] [<ffff0000080adb78>] unmap_stage2_range+0x8c/0x428
[223090.262535] [<ffff0000080adf40>] kvm_unmap_hva_handler+0x2c/0x3c
[223090.262537] [<ffff0000080ace2c>] handle_hva_to_gpa+0xb0/0x104
[223090.262539] [<ffff0000080af988>] kvm_unmap_hva+0x5c/0xbc
[223090.262543] [<ffff0000080a2478>]
kvm_mmu_notifier_invalidate_page+0x50/0x8c
[223090.262547] [<ffff0000082274f8>]
__mmu_notifier_invalidate_page+0x5c/0x84
[223090.262551] [<ffff00000820b700>] try_to_unmap_one+0x1d0/0x4a0
[223090.262553] [<ffff00000820c5c8>] rmap_walk+0x1cc/0x2e0
[223090.262555] [<ffff00000820c90c>] try_to_unmap+0x74/0xa4
[223090.262557] [<ffff000008230ce4>] migrate_pages+0x31c/0x5ac
[223090.262561] [<ffff0000081f869c>] compact_zone+0x3fc/0x7ac
[223090.262563] [<ffff0000081f8ae0>] compact_zone_order+0x94/0xb0
[223090.262564] [<ffff0000081f91c0>] try_to_compact_pages+0x108/0x290
[223090.262569] [<ffff0000081d5108>] __alloc_pages_direct_compact+0x70/0x1ac
[223090.262571] [<ffff0000081d64a0>] __alloc_pages_nodemask+0x434/0x9f4
[223090.262572] [<ffff0000082256f0>] alloc_pages_vma+0x230/0x254
[223090.262574] [<ffff000008235e5c>] do_huge_pmd_anonymous_page+0x114/0x538
[223090.262576] [<ffff000008201bec>] handle_mm_fault+0xd40/0x17a4
[223090.262577] [<ffff0000081fb324>] __get_user_pages+0x12c/0x36c
[223090.262578] [<ffff0000081fb804>] get_user_pages_unlocked+0xa4/0x1b8
[223090.262579] [<ffff0000080a3ce8>] __gfn_to_pfn_memslot+0x280/0x31c
[223090.262580] [<ffff0000080a3dd0>] gfn_to_pfn_prot+0x4c/0x5c
[223090.262582] [<ffff0000080af3f8>] kvm_handle_guest_abort+0x240/0x774
[223090.262584] [<ffff0000080b2bac>] handle_exit+0x11c/0x1ac
[223090.262586] [<ffff0000080ab99c>] kvm_arch_vcpu_ioctl_run+0x31c/0x648
[223090.262587] [<ffff0000080a1d78>] kvm_vcpu_ioctl+0x378/0x768
[223090.262590] [<ffff00000825df5c>] do_vfs_ioctl+0x324/0x5a4
[223090.262591] [<ffff00000825e26c>] SyS_ioctl+0x90/0xa4
[223090.262595] [<ffff000008085d84>] el0_svc_naked+0x38/0x3c
This patch moves the stage2 PGD manipulation under the lock.
Reported-by: Alexander Graf <agraf@suse.de>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Kr?m?? <rkrcmar@redhat.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
virt/kvm/arm/mmu.c | 16 ++++++++--------
1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 313ee64..909a1a7 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -829,22 +829,22 @@ void stage2_unmap_vm(struct kvm *kvm)
* Walks the level-1 page table pointed to by kvm->arch.pgd and frees all
* underlying level-2 and level-3 tables before freeing the actual level-1 table
* and setting the struct pointer to NULL.
- *
- * Note we don't need locking here as this is only called when the VM is
- * destroyed, which can only be done once.
*/
void kvm_free_stage2_pgd(struct kvm *kvm)
{
- if (kvm->arch.pgd == NULL)
- return;
+ void *pgd = NULL;
spin_lock(&kvm->mmu_lock);
- unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+ if (kvm->arch.pgd) {
+ unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
+ pgd = kvm->arch.pgd;
+ kvm->arch.pgd = NULL;
+ }
spin_unlock(&kvm->mmu_lock);
/* Free the HW pgd, one page at a time */
- free_pages_exact(kvm->arch.pgd, S2_PGD_SIZE);
- kvm->arch.pgd = NULL;
+ if (pgd)
+ free_pages_exact(pgd, S2_PGD_SIZE);
}
static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache,
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 08/13] KVM: arm: plug potential guest hardware debug leakage
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (6 preceding siblings ...)
2017-05-18 9:47 ` [PULL 07/13] kvm: arm/arm64: Fix race in resetting stage2 PGD Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 09/13] KVM: arm: rename pm_fake handler to trap_raz_wi Christoffer Dall
` (5 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Zhichao Huang <zhichao.huang@linaro.org>
Hardware debugging in guests is not intercepted currently, it means
that a malicious guest can bring down the entire machine by writing
to the debug registers.
This patch enable trapping of all debug registers, preventing the
guests to access the debug registers. This includes access to the
debug mode(DBGDSCR) in the guest world all the time which could
otherwise mess with the host state. Reads return 0 and writes are
ignored (RAZ_WI).
The result is the guest cannot detect any working hardware based debug
support. As debug exceptions are still routed to the guest normal
debug using software based breakpoints still works.
To support debugging using hardware registers we need to implement a
debug register aware world switch as well as special trapping for
registers that may affect the host state.
Cc: stable at vger.kernel.org
Signed-off-by: Zhichao Huang <zhichao.huang@linaro.org>
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
arch/arm/include/asm/kvm_coproc.h | 3 +-
arch/arm/kvm/coproc.c | 77 ++++++++++++++++++++++++++++++---------
arch/arm/kvm/handle_exit.c | 4 +-
arch/arm/kvm/hyp/switch.c | 4 +-
4 files changed, 66 insertions(+), 22 deletions(-)
diff --git a/arch/arm/include/asm/kvm_coproc.h b/arch/arm/include/asm/kvm_coproc.h
index 4917c2f..e74ab0f 100644
--- a/arch/arm/include/asm/kvm_coproc.h
+++ b/arch/arm/include/asm/kvm_coproc.h
@@ -31,7 +31,8 @@ void kvm_register_target_coproc_table(struct kvm_coproc_target_table *table);
int kvm_handle_cp10_id(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_cp_0_13_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run);
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run);
int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run);
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index ac8d36d..1403ffb 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -112,12 +112,6 @@ int kvm_handle_cp14_load_store(struct kvm_vcpu *vcpu, struct kvm_run *run)
return 1;
}
-int kvm_handle_cp14_access(struct kvm_vcpu *vcpu, struct kvm_run *run)
-{
- kvm_inject_undefined(vcpu);
- return 1;
-}
-
static void reset_mpidr(struct kvm_vcpu *vcpu, const struct coproc_reg *r)
{
/*
@@ -533,12 +527,7 @@ static int emulate_cp15(struct kvm_vcpu *vcpu,
return 1;
}
-/**
- * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run: The kvm_run struct
- */
-int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static struct coproc_params decode_64bit_hsr(struct kvm_vcpu *vcpu)
{
struct coproc_params params;
@@ -552,9 +541,38 @@ int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
params.Rt2 = (kvm_vcpu_get_hsr(vcpu) >> 10) & 0xf;
params.CRm = 0;
+ return params;
+}
+
+/**
+ * kvm_handle_cp15_64 -- handles a mrrc/mcrr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run: The kvm_run struct
+ */
+int kvm_handle_cp15_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ struct coproc_params params = decode_64bit_hsr(vcpu);
+
return emulate_cp15(vcpu, ¶ms);
}
+/**
+ * kvm_handle_cp14_64 -- handles a mrrc/mcrr trap on a guest CP14 access
+ * @vcpu: The VCPU pointer
+ * @run: The kvm_run struct
+ */
+int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ struct coproc_params params = decode_64bit_hsr(vcpu);
+
+ /* raz_wi cp14 */
+ pm_fake(vcpu, ¶ms, NULL);
+
+ /* handled */
+ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+ return 1;
+}
+
static void reset_coproc_regs(struct kvm_vcpu *vcpu,
const struct coproc_reg *table, size_t num)
{
@@ -565,12 +583,7 @@ static void reset_coproc_regs(struct kvm_vcpu *vcpu,
table[i].reset(vcpu, &table[i]);
}
-/**
- * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
- * @vcpu: The VCPU pointer
- * @run: The kvm_run struct
- */
-int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+static struct coproc_params decode_32bit_hsr(struct kvm_vcpu *vcpu)
{
struct coproc_params params;
@@ -584,9 +597,37 @@ int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
params.Op2 = (kvm_vcpu_get_hsr(vcpu) >> 17) & 0x7;
params.Rt2 = 0;
+ return params;
+}
+
+/**
+ * kvm_handle_cp15_32 -- handles a mrc/mcr trap on a guest CP15 access
+ * @vcpu: The VCPU pointer
+ * @run: The kvm_run struct
+ */
+int kvm_handle_cp15_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ struct coproc_params params = decode_32bit_hsr(vcpu);
return emulate_cp15(vcpu, ¶ms);
}
+/**
+ * kvm_handle_cp14_32 -- handles a mrc/mcr trap on a guest CP14 access
+ * @vcpu: The VCPU pointer
+ * @run: The kvm_run struct
+ */
+int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
+{
+ struct coproc_params params = decode_32bit_hsr(vcpu);
+
+ /* raz_wi cp14 */
+ pm_fake(vcpu, ¶ms, NULL);
+
+ /* handled */
+ kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
+ return 1;
+}
+
/******************************************************************************
* Userspace API
*****************************************************************************/
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 5fd7968..f86a9aa 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -95,9 +95,9 @@ static exit_handle_fn arm_exit_handlers[] = {
[HSR_EC_WFI] = kvm_handle_wfx,
[HSR_EC_CP15_32] = kvm_handle_cp15_32,
[HSR_EC_CP15_64] = kvm_handle_cp15_64,
- [HSR_EC_CP14_MR] = kvm_handle_cp14_access,
+ [HSR_EC_CP14_MR] = kvm_handle_cp14_32,
[HSR_EC_CP14_LS] = kvm_handle_cp14_load_store,
- [HSR_EC_CP14_64] = kvm_handle_cp14_access,
+ [HSR_EC_CP14_64] = kvm_handle_cp14_64,
[HSR_EC_CP_0_13] = kvm_handle_cp_0_13_access,
[HSR_EC_CP10_ID] = kvm_handle_cp10_id,
[HSR_EC_HVC] = handle_hvc,
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c
index 92678b7..624a510 100644
--- a/arch/arm/kvm/hyp/switch.c
+++ b/arch/arm/kvm/hyp/switch.c
@@ -48,7 +48,9 @@ static void __hyp_text __activate_traps(struct kvm_vcpu *vcpu, u32 *fpexc_host)
write_sysreg(HSTR_T(15), HSTR);
write_sysreg(HCPTR_TTA | HCPTR_TCP(10) | HCPTR_TCP(11), HCPTR);
val = read_sysreg(HDCR);
- write_sysreg(val | HDCR_TPM | HDCR_TPMCR, HDCR);
+ val |= HDCR_TPM | HDCR_TPMCR; /* trap performance monitors */
+ val |= HDCR_TDRA | HDCR_TDOSA | HDCR_TDA; /* trap debug regs */
+ write_sysreg(val, HDCR);
}
static void __hyp_text __deactivate_traps(struct kvm_vcpu *vcpu)
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 09/13] KVM: arm: rename pm_fake handler to trap_raz_wi
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (7 preceding siblings ...)
2017-05-18 9:47 ` [PULL 08/13] KVM: arm: plug potential guest hardware debug leakage Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 10/13] kvm: arm/arm64: Force reading uncached stage2 PGD Christoffer Dall
` (4 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Zhichao Huang <zhichao.huang@linaro.org>
pm_fake doesn't quite describe what the handler does (ignoring writes
and returning 0 for reads).
As we're about to use it (a lot) in a different context, rename it
with a (admitedly cryptic) name that make sense for all users.
Signed-off-by: Zhichao Huang <zhichao.huang@linaro.org>
Reviewed-by: Alex Bennee <alex.bennee@linaro.org>
Acked-by: Christoffer Dall <christoffer.dall@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Alex Benn?e <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
arch/arm/kvm/coproc.c | 32 ++++++++++++++++----------------
1 file changed, 16 insertions(+), 16 deletions(-)
diff --git a/arch/arm/kvm/coproc.c b/arch/arm/kvm/coproc.c
index 1403ffb..6d1d2e2 100644
--- a/arch/arm/kvm/coproc.c
+++ b/arch/arm/kvm/coproc.c
@@ -279,7 +279,7 @@ static bool access_gic_sre(struct kvm_vcpu *vcpu,
* must always support PMCCNTR (the cycle counter): we just RAZ/WI for
* all PM registers, which doesn't crash the guest kernel at least.
*/
-static bool pm_fake(struct kvm_vcpu *vcpu,
+static bool trap_raz_wi(struct kvm_vcpu *vcpu,
const struct coproc_params *p,
const struct coproc_reg *r)
{
@@ -289,19 +289,19 @@ static bool pm_fake(struct kvm_vcpu *vcpu,
return read_zero(vcpu, p);
}
-#define access_pmcr pm_fake
-#define access_pmcntenset pm_fake
-#define access_pmcntenclr pm_fake
-#define access_pmovsr pm_fake
-#define access_pmselr pm_fake
-#define access_pmceid0 pm_fake
-#define access_pmceid1 pm_fake
-#define access_pmccntr pm_fake
-#define access_pmxevtyper pm_fake
-#define access_pmxevcntr pm_fake
-#define access_pmuserenr pm_fake
-#define access_pmintenset pm_fake
-#define access_pmintenclr pm_fake
+#define access_pmcr trap_raz_wi
+#define access_pmcntenset trap_raz_wi
+#define access_pmcntenclr trap_raz_wi
+#define access_pmovsr trap_raz_wi
+#define access_pmselr trap_raz_wi
+#define access_pmceid0 trap_raz_wi
+#define access_pmceid1 trap_raz_wi
+#define access_pmccntr trap_raz_wi
+#define access_pmxevtyper trap_raz_wi
+#define access_pmxevcntr trap_raz_wi
+#define access_pmuserenr trap_raz_wi
+#define access_pmintenset trap_raz_wi
+#define access_pmintenclr trap_raz_wi
/* Architected CP15 registers.
* CRn denotes the primary register number, but is copied to the CRm in the
@@ -566,7 +566,7 @@ int kvm_handle_cp14_64(struct kvm_vcpu *vcpu, struct kvm_run *run)
struct coproc_params params = decode_64bit_hsr(vcpu);
/* raz_wi cp14 */
- pm_fake(vcpu, ¶ms, NULL);
+ trap_raz_wi(vcpu, ¶ms, NULL);
/* handled */
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
@@ -621,7 +621,7 @@ int kvm_handle_cp14_32(struct kvm_vcpu *vcpu, struct kvm_run *run)
struct coproc_params params = decode_32bit_hsr(vcpu);
/* raz_wi cp14 */
- pm_fake(vcpu, ¶ms, NULL);
+ trap_raz_wi(vcpu, ¶ms, NULL);
/* handled */
kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 10/13] kvm: arm/arm64: Force reading uncached stage2 PGD
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (8 preceding siblings ...)
2017-05-18 9:47 ` [PULL 09/13] KVM: arm: rename pm_fake handler to trap_raz_wi Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 11/13] kvm: arm/arm64: Fix use after free of stage2 page table Christoffer Dall
` (3 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com>
Make sure we don't use a cached value of the KVM stage2 PGD while
resetting the PGD.
Cc: Marc Zyngier <marc.zyngier@arm.com>
Cc: stable at vger.kernel.org
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
virt/kvm/arm/mmu.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 909a1a7..704e35f 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -837,7 +837,7 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
spin_lock(&kvm->mmu_lock);
if (kvm->arch.pgd) {
unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
- pgd = kvm->arch.pgd;
+ pgd = READ_ONCE(kvm->arch.pgd);
kvm->arch.pgd = NULL;
}
spin_unlock(&kvm->mmu_lock);
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 11/13] kvm: arm/arm64: Fix use after free of stage2 page table
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (9 preceding siblings ...)
2017-05-18 9:47 ` [PULL 10/13] kvm: arm/arm64: Force reading uncached stage2 PGD Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 12/13] KVM: arm/arm64: Fix bug when registering redist iodevs Christoffer Dall
` (2 subsequent siblings)
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
From: Suzuki K Poulose <suzuki.poulose@arm.com>
We yield the kvm->mmu_lock occassionaly while performing an operation
(e.g, unmap or permission changes) on a large area of stage2 mappings.
However this could possibly cause another thread to clear and free up
the stage2 page tables while we were waiting for regaining the lock and
thus the original thread could end up in accessing memory that was
freed. This patch fixes the problem by making sure that the stage2
pagetable is still valid after we regain the lock. The fact that
mmu_notifer->release() could be called twice (via __mmu_notifier_release
and mmu_notifier_unregsister) enhances the possibility of hitting
this race where there are two threads trying to unmap the entire guest
shadow pages.
While at it, cleanup the redudant checks around cond_resched_lock in
stage2_wp_range(), as cond_resched_lock already does the same checks.
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Radim Kr?m?? <rkrcmar@redhat.com>
Cc: andreyknvl at google.com
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: stable at vger.kernel.org
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
---
virt/kvm/arm/mmu.c | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c
index 704e35f..a2d6324 100644
--- a/virt/kvm/arm/mmu.c
+++ b/virt/kvm/arm/mmu.c
@@ -295,6 +295,13 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
assert_spin_locked(&kvm->mmu_lock);
pgd = kvm->arch.pgd + stage2_pgd_index(addr);
do {
+ /*
+ * Make sure the page table is still active, as another thread
+ * could have possibly freed the page table, while we released
+ * the lock.
+ */
+ if (!READ_ONCE(kvm->arch.pgd))
+ break;
next = stage2_pgd_addr_end(addr, end);
if (!stage2_pgd_none(*pgd))
unmap_stage2_puds(kvm, pgd, addr, next);
@@ -1170,11 +1177,13 @@ static void stage2_wp_range(struct kvm *kvm, phys_addr_t addr, phys_addr_t end)
* large. Otherwise, we may see kernel panics with
* CONFIG_DETECT_HUNG_TASK, CONFIG_LOCKUP_DETECTOR,
* CONFIG_LOCKDEP. Additionally, holding the lock too long
- * will also starve other vCPUs.
+ * will also starve other vCPUs. We have to also make sure
+ * that the page tables are not freed while we released
+ * the lock.
*/
- if (need_resched() || spin_needbreak(&kvm->mmu_lock))
- cond_resched_lock(&kvm->mmu_lock);
-
+ cond_resched_lock(&kvm->mmu_lock);
+ if (!READ_ONCE(kvm->arch.pgd))
+ break;
next = stage2_pgd_addr_end(addr, end);
if (stage2_pgd_present(*pgd))
stage2_wp_puds(pgd, addr, next);
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 12/13] KVM: arm/arm64: Fix bug when registering redist iodevs
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (10 preceding siblings ...)
2017-05-18 9:47 ` [PULL 11/13] kvm: arm/arm64: Fix use after free of stage2 page table Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 9:47 ` [PULL 13/13] KVM: arm/arm64: Hold slots_lock when unregistering kvm io bus devices Christoffer Dall
2017-05-18 18:34 ` [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Radim Krčmář
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
If userspace creates the VCPUs after initializing the VGIC, then we end
up in a situation where we trigger a bug in kvm_vcpu_get_idx(), because
it is called prior to adding the VCPU into the vcpus array on the VM.
There is no tight coupling between the VCPU index and the area of the
redistributor region used for the VCPU, so we can simply ensure that all
creations of redistributors are serialized per VM, and increment an
offset when we successfully add a redistributor.
The vgic_register_redist_iodev() function can be called from two paths:
vgic_redister_all_redist_iodev() which is called via the kvm_vgic_addr()
device attribute handler. This patch already holds the kvm->lock mutex.
The other path is via kvm_vgic_vcpu_init, which is called through a
longer chain from kvm_vm_ioctl_create_vcpu(), which releases the
kvm->lock mutex just before calling kvm_arch_vcpu_create(), so we can
simply take this mutex again later for our purposes.
Fixes: ab6f468c10 ("KVM: arm/arm64: Register iodevs when setting redist base and creating VCPUs")
Signed-off-by: Christoffer Dall <cdall@linaro.org>
Tested-by: Jean-Philippe Brucker <jean-philippe.brucker@arm.com>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
---
include/kvm/arm_vgic.h | 5 ++++-
virt/kvm/arm/vgic/vgic-init.c | 5 ++++-
virt/kvm/arm/vgic/vgic-mmio-v3.c | 9 ++++++---
3 files changed, 14 insertions(+), 5 deletions(-)
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 97b8d37..ef71858 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -195,7 +195,10 @@ struct vgic_dist {
/* either a GICv2 CPU interface */
gpa_t vgic_cpu_base;
/* or a number of GICv3 redistributor regions */
- gpa_t vgic_redist_base;
+ struct {
+ gpa_t vgic_redist_base;
+ gpa_t vgic_redist_free_offset;
+ };
};
/* distributor enabled */
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
index dc68e2e..3a0b899 100644
--- a/virt/kvm/arm/vgic/vgic-init.c
+++ b/virt/kvm/arm/vgic/vgic-init.c
@@ -242,8 +242,11 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
* If we are creating a VCPU with a GICv3 we must also register the
* KVM io device for the redistributor that belongs to this VCPU.
*/
- if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+ if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
+ mutex_lock(&vcpu->kvm->lock);
ret = vgic_register_redist_iodev(vcpu);
+ mutex_unlock(&vcpu->kvm->lock);
+ }
return ret;
}
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 99da1a2..9b0f681 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -586,7 +586,7 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
if (!vgic_v3_check_base(kvm))
return -EINVAL;
- rd_base = vgic->vgic_redist_base + kvm_vcpu_get_idx(vcpu) * SZ_64K * 2;
+ rd_base = vgic->vgic_redist_base + vgic->vgic_redist_free_offset;
sgi_base = rd_base + SZ_64K;
kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops);
@@ -615,11 +615,14 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
SZ_64K, &sgi_dev->dev);
mutex_unlock(&kvm->slots_lock);
- if (ret)
+ if (ret) {
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
&rd_dev->dev);
+ return ret;
+ }
- return ret;
+ vgic->vgic_redist_free_offset += 2 * SZ_64K;
+ return 0;
}
static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 13/13] KVM: arm/arm64: Hold slots_lock when unregistering kvm io bus devices
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (11 preceding siblings ...)
2017-05-18 9:47 ` [PULL 12/13] KVM: arm/arm64: Fix bug when registering redist iodevs Christoffer Dall
@ 2017-05-18 9:47 ` Christoffer Dall
2017-05-18 18:34 ` [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Radim Krčmář
13 siblings, 0 replies; 15+ messages in thread
From: Christoffer Dall @ 2017-05-18 9:47 UTC (permalink / raw)
To: linux-arm-kernel
We were not holding the kvm->slots_lock as required when calling
kvm_io_bus_unregister_dev() as required.
This only affects the error path, but still, let's do our due
diligence.
Reported by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
Reviewed-by: Eric Auger <eric.auger@redhat.com>
---
virt/kvm/arm/vgic/vgic-mmio-v3.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c
index 9b0f681..201d5e2 100644
--- a/virt/kvm/arm/vgic/vgic-mmio-v3.c
+++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c
@@ -614,15 +614,16 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu)
mutex_lock(&kvm->slots_lock);
ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base,
SZ_64K, &sgi_dev->dev);
- mutex_unlock(&kvm->slots_lock);
if (ret) {
kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS,
&rd_dev->dev);
- return ret;
+ goto out;
}
vgic->vgic_redist_free_offset += 2 * SZ_64K;
- return 0;
+out:
+ mutex_unlock(&kvm->slots_lock);
+ return ret;
}
static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu)
@@ -647,10 +648,12 @@ static int vgic_register_all_redist_iodevs(struct kvm *kvm)
if (ret) {
/* The current c failed, so we start with the previous one. */
+ mutex_lock(&kvm->slots_lock);
for (c--; c >= 0; c--) {
vcpu = kvm_get_vcpu(kvm, c);
vgic_unregister_redist_iodev(vcpu);
}
+ mutex_unlock(&kvm->slots_lock);
}
return ret;
--
2.9.0
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [PULL 00/13] KVM/ARM Fixes for v4.12-rc2
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
` (12 preceding siblings ...)
2017-05-18 9:47 ` [PULL 13/13] KVM: arm/arm64: Hold slots_lock when unregistering kvm io bus devices Christoffer Dall
@ 2017-05-18 18:34 ` Radim Krčmář
13 siblings, 0 replies; 15+ messages in thread
From: Radim Krčmář @ 2017-05-18 18:34 UTC (permalink / raw)
To: linux-arm-kernel
2017-05-18 11:47+0200, Christoffer Dall:
> Hi Radim and Paolo,
>
> Here is a fairly large set of fixes post -rc1 for KVM/ARM.
>
> The fixes include:
> - A fix for a build failure introduced in -rc1 when tracepoints are
> enabled on 32-bit ARM.
> - Disabling use of stack pointer protection in the hyp code which can
> cause panics.
> - A handful of VGIC fixes.
> - A fix to the init of the redistributors on GICv3 systems that
> prevented boot with kvmtool on GICv3 systems introduced in -rc1.
> - A number of race conditions fixed in our MMU handling code.
> - A fix for the guest being able to program the debug extensions for
> the host on the 32-bit side.
Pulled, thanks.
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2017-05-18 18:34 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2017-05-18 9:47 [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Christoffer Dall
2017-05-18 9:47 ` [PULL 01/13] ARM: KVM: Fix tracepoint generation after move to virt/kvm/arm/ Christoffer Dall
2017-05-18 9:47 ` [PULL 02/13] arm64: KVM: Do not use stack-protector to compile EL2 code Christoffer Dall
2017-05-18 9:47 ` [PULL 03/13] arm: KVM: Do not use stack-protector to compile HYP code Christoffer Dall
2017-05-18 9:47 ` [PULL 04/13] KVM: arm/arm64: vgic-v2: Do not use Active+Pending state for a HW interrupt Christoffer Dall
2017-05-18 9:47 ` [PULL 05/13] KVM: arm/arm64: vgic-v3: " Christoffer Dall
2017-05-18 9:47 ` [PULL 06/13] KVM: arm/arm64: vgic-v3: Use PREbits to infer the number of ICH_APxRn_EL2 registers Christoffer Dall
2017-05-18 9:47 ` [PULL 07/13] kvm: arm/arm64: Fix race in resetting stage2 PGD Christoffer Dall
2017-05-18 9:47 ` [PULL 08/13] KVM: arm: plug potential guest hardware debug leakage Christoffer Dall
2017-05-18 9:47 ` [PULL 09/13] KVM: arm: rename pm_fake handler to trap_raz_wi Christoffer Dall
2017-05-18 9:47 ` [PULL 10/13] kvm: arm/arm64: Force reading uncached stage2 PGD Christoffer Dall
2017-05-18 9:47 ` [PULL 11/13] kvm: arm/arm64: Fix use after free of stage2 page table Christoffer Dall
2017-05-18 9:47 ` [PULL 12/13] KVM: arm/arm64: Fix bug when registering redist iodevs Christoffer Dall
2017-05-18 9:47 ` [PULL 13/13] KVM: arm/arm64: Hold slots_lock when unregistering kvm io bus devices Christoffer Dall
2017-05-18 18:34 ` [PULL 00/13] KVM/ARM Fixes for v4.12-rc2 Radim Krčmář
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).