linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Jiri Slaby <jslaby@suse.cz>
To: stable@vger.kernel.org
Cc: linux-kernel@vger.kernel.org, Marc Zyngier <marc.zyngier@arm.com>,
	Shannon Zhao <shannon.zhao@linaro.org>,
	Jiri Slaby <jslaby@suse.cz>
Subject: [PATCH 3.12 21/63] arm64: KVM: flush VM pages before letting the guest enable caches
Date: Thu, 30 Apr 2015 14:11:50 +0200	[thread overview]
Message-ID: <053689a94fa5696e4beb2306872cec533abee998.1430387326.git.jslaby@suse.cz> (raw)
In-Reply-To: <45aaf85687dd6ac119c55c5ec0dbe0bef0e62235.1430387326.git.jslaby@suse.cz>
In-Reply-To: <cover.1430387326.git.jslaby@suse.cz>

From: Marc Zyngier <marc.zyngier@arm.com>

3.12-stable review patch.  If anyone has any objections, please let me know.

===============

commit 9d218a1fcf4c6b759d442ef702842fae92e1ea61 upstream.

When the guest runs with caches disabled (like in an early boot
sequence, for example), all the writes are diectly going to RAM,
bypassing the caches altogether.

Once the MMU and caches are enabled, whatever sits in the cache
becomes suddenly visible, which isn't what the guest expects.

A way to avoid this potential disaster is to invalidate the cache
when the MMU is being turned on. For this, we hook into the SCTLR_EL1
trapping code, and scan the stage-2 page tables, invalidating the
pages/sections that have already been mapped in.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Catalin Marinas <catalin.marinas@arm.com>
Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
---
 arch/arm/include/asm/kvm_mmu.h   |  2 +
 arch/arm/kvm/mmu.c               | 83 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/kvm_mmu.h |  2 +
 arch/arm64/kvm/sys_regs.c        |  5 ++-
 4 files changed, 91 insertions(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 5c946dfdcb94..0de650faf1af 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -143,6 +143,8 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
 
 #define kvm_flush_dcache_to_poc(a,l)	__cpuc_flush_dcache_area((a), (l))
 
+void stage2_flush_vm(struct kvm *kvm);
+
 #endif	/* !__ASSEMBLY__ */
 
 #endif /* __ARM_KVM_MMU_H__ */
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index e747dc10c033..61c5a92f6d9d 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -162,6 +162,89 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
 	}
 }
 
+static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
+			      phys_addr_t addr, phys_addr_t end)
+{
+	pte_t *pte;
+
+	pte = pte_offset_kernel(pmd, addr);
+	do {
+		if (!pte_none(*pte)) {
+			hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT);
+			kvm_flush_dcache_to_poc((void*)hva, PAGE_SIZE);
+		}
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud,
+			      phys_addr_t addr, phys_addr_t end)
+{
+	pmd_t *pmd;
+	phys_addr_t next;
+
+	pmd = pmd_offset(pud, addr);
+	do {
+		next = kvm_pmd_addr_end(addr, end);
+		if (!pmd_none(*pmd)) {
+			stage2_flush_ptes(kvm, pmd, addr, next);
+		}
+	} while (pmd++, addr = next, addr != end);
+}
+
+static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd,
+			      phys_addr_t addr, phys_addr_t end)
+{
+	pud_t *pud;
+	phys_addr_t next;
+
+	pud = pud_offset(pgd, addr);
+	do {
+		next = kvm_pud_addr_end(addr, end);
+		if (!pud_none(*pud)) {
+			stage2_flush_pmds(kvm, pud, addr, next);
+		}
+	} while (pud++, addr = next, addr != end);
+}
+
+static void stage2_flush_memslot(struct kvm *kvm,
+				 struct kvm_memory_slot *memslot)
+{
+	phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT;
+	phys_addr_t end = addr + PAGE_SIZE * memslot->npages;
+	phys_addr_t next;
+	pgd_t *pgd;
+
+	pgd = kvm->arch.pgd + pgd_index(addr);
+	do {
+		next = kvm_pgd_addr_end(addr, end);
+		stage2_flush_puds(kvm, pgd, addr, next);
+	} while (pgd++, addr = next, addr != end);
+}
+
+/**
+ * stage2_flush_vm - Invalidate cache for pages mapped in stage 2
+ * @kvm: The struct kvm pointer
+ *
+ * Go through the stage 2 page tables and invalidate any cache lines
+ * backing memory already mapped to the VM.
+ */
+void stage2_flush_vm(struct kvm *kvm)
+{
+	struct kvm_memslots *slots;
+	struct kvm_memory_slot *memslot;
+	int idx;
+
+	idx = srcu_read_lock(&kvm->srcu);
+	spin_lock(&kvm->mmu_lock);
+
+	slots = kvm_memslots(kvm);
+	kvm_for_each_memslot(memslot, slots)
+		stage2_flush_memslot(kvm, memslot);
+
+	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
+}
+
 /**
  * free_boot_hyp_pgd - free HYP boot page tables
  *
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 802bd971f1de..3b038b39ba9b 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -142,5 +142,7 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
 	}
 }
 
+void stage2_flush_vm(struct kvm *kvm);
+
 #endif /* __ASSEMBLY__ */
 #endif /* __ARM64_KVM_MMU_H__ */
diff --git a/arch/arm64/kvm/sys_regs.c b/arch/arm64/kvm/sys_regs.c
index 2097e5ecba42..03244582bc55 100644
--- a/arch/arm64/kvm/sys_regs.c
+++ b/arch/arm64/kvm/sys_regs.c
@@ -27,6 +27,7 @@
 #include <asm/kvm_host.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_mmu.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <trace/events/kvm.h>
@@ -154,8 +155,10 @@ static bool access_sctlr(struct kvm_vcpu *vcpu,
 {
 	access_vm_reg(vcpu, p, r);
 
-	if (vcpu_has_cache_enabled(vcpu))	/* MMU+Caches enabled? */
+	if (vcpu_has_cache_enabled(vcpu)) {	/* MMU+Caches enabled? */
 		vcpu->arch.hcr_el2 &= ~HCR_TVM;
+		stage2_flush_vm(vcpu->kvm);
+	}
 
 	return true;
 }
-- 
2.3.5


  parent reply	other threads:[~2015-04-30 12:21 UTC|newest]

Thread overview: 67+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-04-30 12:12 [PATCH 3.12 00/63] 3.12.42-stable review Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 01/63] KVM: ARM: Fix calculation of virtual CPU ID Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 02/63] KVM: ARM: fix the size of TTBCR_{T0SZ,T1SZ} masks Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 03/63] ARM: KVM: Yield CPU when vcpu executes a WFE Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 04/63] ARM: KVM: Fix MPIDR computing to support virtual clusters Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 05/63] KVM: ARM: Update comments for kvm_handle_wfi Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 06/63] ARM: KVM: fix L2CTLR to be per-cluster Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 07/63] arm/arm64: KVM: PSCI: use MPIDR to identify a target CPU Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 08/63] arm64: KVM: Yield CPU when vcpu executes a WFE Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 09/63] arm/arm64: KVM: arch_timer: Initialize cntvoff at kvm_init Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 10/63] ARM: KVM: Allow creating the VGIC after VCPUs Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 11/63] arm/arm64: kvm: Set vcpu->cpu to -1 on vcpu_put Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 12/63] arm64: KVM: Force undefined exception for Guest SMC intructions Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 13/63] arm: KVM: Don't return PSCI_INVAL if waitqueue is inactive Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 14/63] KVM: ARM: Remove duplicate include Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 15/63] arm: kvm: implement CPU PM notifier Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 16/63] arm/arm64: KVM: detect CPU reset on CPU_PM_EXIT Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 17/63] arm64: KVM: force cache clean on page fault when caches are off Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 18/63] arm64: KVM: allows discrimination of AArch32 sysreg access Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 19/63] arm64: KVM: trap VM system registers until MMU and caches are ON Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 20/63] ARM: KVM: introduce kvm_p*d_addr_end Jiri Slaby
2015-04-30 12:11 ` Jiri Slaby [this message]
2015-04-30 12:11 ` [PATCH 3.12 22/63] ARM: KVM: force cache clean on page fault when caches are off Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 23/63] ARM: KVM: fix handling of trapped 64bit coprocessor accesses Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 24/63] ARM: KVM: fix ordering of " Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 25/63] ARM: KVM: introduce per-vcpu HYP Configuration Register Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 26/63] ARM: KVM: add world-switch for AMAIR{0,1} Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 27/63] ARM: KVM: trap VM system registers until MMU and caches are ON Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 28/63] ARM: KVM: fix non-VGIC compilation Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 29/63] ARM: KVM: disable KVM in Kconfig on big-endian systems Jiri Slaby
2015-04-30 12:11 ` [PATCH 3.12 30/63] KVM: arm/arm64: vgic: fix GICD_ICFGR register accesses Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 31/63] KVM: ARM: vgic: Fix the overlap check action about setting the GICD & GICC base address Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 32/63] arm64: kvm: use inner-shareable barriers for inner-shareable maintenance Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 33/63] kvm: arm64: vgic: fix hyp panic with 64k pages on juno platform Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 34/63] arm/arm64: KVM: Fix and refactor unmap_range Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 35/63] ARM: KVM: Unmap IPA on memslot delete/move Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 36/63] ARM: KVM: user_mem_abort: support stage 2 MMIO page mapping Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 37/63] arm64: KVM: export demux regids as KVM_REG_ARM64 Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 38/63] ARM: virt: fix wrong HSCTLR.EE bit setting Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 39/63] ARM64: KVM: store kvm_vcpu_fault_info est_el2 as word Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 40/63] KVM: ARM/arm64: fix non-const declaration of function returning const Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 41/63] KVM: ARM/arm64: fix broken __percpu annotation Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 42/63] KVM: ARM/arm64: avoid returning negative error code as bool Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 43/63] KVM: vgic: return int instead of bool when checking I/O ranges Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 44/63] ARM/ARM64: KVM: Nuke Hyp-mode tlbs before enabling MMU Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 45/63] arm/arm64: KVM: Complete WFI/WFE instructions Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 46/63] ARM/arm64: KVM: fix use of WnR bit in kvm_is_write_fault() Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 47/63] KVM: ARM: vgic: plug irq injection race Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 48/63] arm/arm64: KVM: Fix VTTBR_BADDR_MASK and pgd alloc Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 49/63] arm: kvm: fix CPU hotplug Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 50/63] arm/arm64: KVM: Ensure memslots are within KVM_PHYS_SIZE Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 51/63] arm: kvm: STRICT_MM_TYPECHECKS fix for user_mem_abort Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 52/63] arm64/kvm: Fix assembler compatibility of macros Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 53/63] arm/arm64: kvm: drop inappropriate use of kvm_is_mmio_pfn() Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 54/63] arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 55/63] arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 56/63] arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 57/63] arm/arm64: KVM: Introduce stage2_unmap_vm Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 58/63] arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 59/63] arm/arm64: KVM: Require in-kernel vgic for the arch timers Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 60/63] arm64: KVM: Fix TLB invalidation by IPA/VMID Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 61/63] arm64: KVM: Fix HCR setting for 32bit guests Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 62/63] arm64: KVM: Do not use pgd_index to index stage-2 pgd Jiri Slaby
2015-04-30 12:12 ` [PATCH 3.12 63/63] arm/arm64: KVM: Keep elrsr/aisr in sync with software model Jiri Slaby
2015-04-30 13:12 ` [PATCH 3.12 00/63] 3.12.42-stable review Guenter Roeck
2015-05-04 13:27   ` Jiri Slaby
2015-04-30 14:26 ` Shuah Khan

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=053689a94fa5696e4beb2306872cec533abee998.1430387326.git.jslaby@suse.cz \
    --to=jslaby@suse.cz \
    --cc=linux-kernel@vger.kernel.org \
    --cc=marc.zyngier@arm.com \
    --cc=shannon.zhao@linaro.org \
    --cc=stable@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).