stable.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel
@ 2015-05-04  1:25 shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 01/22] kvm: add a memslot flag for incoherent memory regions shannon.zhao
                   ` (22 more replies)
  0 siblings, 23 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Shannon Zhao <shannon.zhao@linaro.org>

For KVM/ARM there are many fixes which have been applied upstream while
not committed to stable kernels. Here we backport the important fixes
to 3.18.y stable kernel.

We have compile-tested each patch on arm/arm64/x86 to make sure the
series are bisectable and have booted the resulting kernel on Fastmodel
and started 2 VMs for arm/arm64, and have boot-tested on TC2 and Juno,
and started a guest.

These patches are applied on the top of 3.18.12. They can be fetched
from following address:
https://git.linaro.org/people/shannon.zhao/linux-stable.git linux-3.18.y

Thanks,
Shannon

Ard Biesheuvel (2):
  kvm: add a memslot flag for incoherent memory regions
  arm, arm64: KVM: handle potential incoherency of readonly memslots

Christoffer Dall (9):
  arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag
  arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option
  arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu
  arm/arm64: KVM: Turn off vcpus on PSCI shutdown/reboot
  arm/arm64: KVM: Introduce stage2_unmap_vm
  arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized
  arm/arm64: KVM: Initialize the vgic on-demand when injecting IRQs
  arm/arm64: KVM: Require in-kernel vgic for the arch timers
  arm/arm64: KVM: Keep elrsr/aisr in sync with software model

Eric Auger (1):
  KVM: arm/arm64: vgic: vgic_init returns -ENODEV when no online vcpu

Jan Kiszka (1):
  ARM: KVM: Fix size check in __coherent_cache_guest_page

Laszlo Ersek (1):
  arm, arm64: KVM: allow forced dcache flush on page faults

Marc Zyngier (6):
  arm64: KVM: Fix TLB invalidation by IPA/VMID
  arm64: KVM: Fix HCR setting for 32bit guests
  arm/arm64: KVM: Invalidate data cache on unmap
  arm/arm64: KVM: Use kernel mapping to perform invalidation on page
    fault
  arm64: KVM: Fix stage-2 PGD allocation to have per-page refcounting
  arm64: KVM: Do not use pgd_index to index stage-2 pgd

Peter Maydell (1):
  arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps()

Shannon Zhao (1):
  arm/arm64: KVM: vgic: kick the specific vcpu instead of iterating
    through all

 Documentation/virtual/kvm/api.txt    |  12 +-
 arch/arm/include/asm/kvm_emulate.h   |   5 +
 arch/arm/include/asm/kvm_mmu.h       |  87 +++++++++---
 arch/arm/kvm/arm.c                   |  35 ++++-
 arch/arm/kvm/guest.c                 |   1 -
 arch/arm/kvm/mmu.c                   | 251 +++++++++++++++++++++++++++++------
 arch/arm/kvm/psci.c                  |  18 +++
 arch/arm64/include/asm/kvm_emulate.h |   7 +
 arch/arm64/include/asm/kvm_host.h    |   1 +
 arch/arm64/include/asm/kvm_mmu.h     |  81 +++++------
 arch/arm64/kvm/guest.c               |   1 -
 arch/arm64/kvm/hyp.S                 |   1 +
 arch/arm64/kvm/reset.c               |   1 -
 include/kvm/arm_arch_timer.h         |  10 +-
 include/kvm/arm_vgic.h               |   5 +-
 include/linux/kvm_host.h             |   1 +
 virt/kvm/arm/arch_timer.c            |  30 +++--
 virt/kvm/arm/vgic-v2.c               |   8 ++
 virt/kvm/arm/vgic-v3.c               |   8 ++
 virt/kvm/arm/vgic.c                  | 122 +++++++++--------
 20 files changed, 504 insertions(+), 181 deletions(-)

-- 
2.1.0


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

* [PATCH for 3.18.y stable 01/22] kvm: add a memslot flag for incoherent memory regions
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 02/22] arm, arm64: KVM: allow forced dcache flush on page faults shannon.zhao
                   ` (21 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Ard Biesheuvel,
	Marc Zyngier

From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

commit 1050dcda3052912984b26fb6d2695a3f41792000 upstream.

Memory regions may be incoherent with the caches, typically when the
guest has mapped a host system RAM backed memory region as uncached.
Add a flag KVM_MEMSLOT_INCOHERENT so that we can tag these memslots
and handle them appropriately when mapping them.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 include/linux/kvm_host.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index a6059bd..e4d8f70 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -43,6 +43,7 @@
  * include/linux/kvm_h.
  */
 #define KVM_MEMSLOT_INVALID	(1UL << 16)
+#define KVM_MEMSLOT_INCOHERENT	(1UL << 17)
 
 /* Two fragments for cross MMIO pages. */
 #define KVM_MAX_MMIO_FRAGMENTS	2
-- 
2.1.0


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

* [PATCH for 3.18.y stable 02/22] arm, arm64: KVM: allow forced dcache flush on page faults
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 01/22] kvm: add a memslot flag for incoherent memory regions shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 03/22] arm, arm64: KVM: handle potential incoherency of readonly memslots shannon.zhao
                   ` (20 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Laszlo Ersek,
	Ard Biesheuvel, Marc Zyngier

From: Laszlo Ersek <lersek@redhat.com>

commit 840f4bfbe03f1ce94ade8fdf84e8cd925ef15a48 upstream.

To allow handling of incoherent memslots in a subsequent patch, this
patch adds a paramater 'ipa_uncached' to cache_coherent_guest_page()
so that we can instruct it to flush the page's contents to DRAM even
if the guest has caching globally enabled.

Signed-off-by: Laszlo Ersek <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   | 5 +++--
 arch/arm/kvm/mmu.c               | 9 +++++++--
 arch/arm64/include/asm/kvm_mmu.h | 5 +++--
 3 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index acb0d57..f867060 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -161,9 +161,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 }
 
 static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
-					     unsigned long size)
+					     unsigned long size,
+					     bool ipa_uncached)
 {
-	if (!vcpu_has_cache_enabled(vcpu))
+	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
 		kvm_flush_dcache_to_poc((void *)hva, size);
 	
 	/*
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 8664ff1..8038e52 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -853,6 +853,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	struct vm_area_struct *vma;
 	pfn_t pfn;
 	pgprot_t mem_type = PAGE_S2;
+	bool fault_ipa_uncached;
 
 	write_fault = kvm_is_write_fault(vcpu);
 	if (fault_status == FSC_PERM && !write_fault) {
@@ -919,6 +920,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	if (!hugetlb && !force_pte)
 		hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
 
+	fault_ipa_uncached = false;
+
 	if (hugetlb) {
 		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
 		new_pmd = pmd_mkhuge(new_pmd);
@@ -926,7 +929,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			kvm_set_s2pmd_writable(&new_pmd);
 			kvm_set_pfn_dirty(pfn);
 		}
-		coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE);
+		coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE,
+					  fault_ipa_uncached);
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
 	} else {
 		pte_t new_pte = pfn_pte(pfn, mem_type);
@@ -934,7 +938,8 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			kvm_set_s2pte_writable(&new_pte);
 			kvm_set_pfn_dirty(pfn);
 		}
-		coherent_cache_guest_page(vcpu, hva, PAGE_SIZE);
+		coherent_cache_guest_page(vcpu, hva, PAGE_SIZE,
+					  fault_ipa_uncached);
 		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte,
 			pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE));
 	}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 0caf7a5..123b521 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -243,9 +243,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 }
 
 static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
-					     unsigned long size)
+					     unsigned long size,
+					     bool ipa_uncached)
 {
-	if (!vcpu_has_cache_enabled(vcpu))
+	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
 		kvm_flush_dcache_to_poc((void *)hva, size);
 
 	if (!icache_is_aliasing()) {		/* PIPT */
-- 
2.1.0


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

* [PATCH for 3.18.y stable 03/22] arm, arm64: KVM: handle potential incoherency of readonly memslots
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 01/22] kvm: add a memslot flag for incoherent memory regions shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 02/22] arm, arm64: KVM: allow forced dcache flush on page faults shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 04/22] arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag shannon.zhao
                   ` (19 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Ard Biesheuvel,
	Marc Zyngier

From: Ard Biesheuvel <ard.biesheuvel@linaro.org>

commit 849260c72c6b8bd53850cb00b80027db3a273c2c upstream.

Readonly memslots are often used to implement emulation of ROMs and
NOR flashes, in which case the guest may legally map these regions as
uncached.
To deal with the incoherency associated with uncached guest mappings,
treat all readonly memslots as incoherent, and ensure that pages that
belong to regions tagged as such are flushed to DRAM before being passed
to the guest.

Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/kvm/mmu.c | 20 +++++++++++++++-----
 1 file changed, 15 insertions(+), 5 deletions(-)

diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 8038e52..16ae5f0 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -920,7 +920,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 	if (!hugetlb && !force_pte)
 		hugetlb = transparent_hugepage_adjust(&pfn, &fault_ipa);
 
-	fault_ipa_uncached = false;
+	fault_ipa_uncached = memslot->flags & KVM_MEMSLOT_INCOHERENT;
 
 	if (hugetlb) {
 		pmd_t new_pmd = pfn_pmd(pfn, mem_type);
@@ -1299,11 +1299,12 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
 		hva = vm_end;
 	} while (hva < reg_end);
 
-	if (ret) {
-		spin_lock(&kvm->mmu_lock);
+	spin_lock(&kvm->mmu_lock);
+	if (ret)
 		unmap_stage2_range(kvm, mem->guest_phys_addr, mem->memory_size);
-		spin_unlock(&kvm->mmu_lock);
-	}
+	else
+		stage2_flush_memslot(kvm, memslot);
+	spin_unlock(&kvm->mmu_lock);
 	return ret;
 }
 
@@ -1315,6 +1316,15 @@ void kvm_arch_free_memslot(struct kvm *kvm, struct kvm_memory_slot *free,
 int kvm_arch_create_memslot(struct kvm *kvm, struct kvm_memory_slot *slot,
 			    unsigned long npages)
 {
+	/*
+	 * Readonly memslots are not incoherent with the caches by definition,
+	 * but in practice, they are used mostly to emulate ROMs or NOR flashes
+	 * that the guest may consider devices and hence map as uncached.
+	 * To prevent incoherency issues in these cases, tag all readonly
+	 * regions as incoherent.
+	 */
+	if (slot->flags & KVM_MEM_READONLY)
+		slot->flags |= KVM_MEMSLOT_INCOHERENT;
 	return 0;
 }
 
-- 
2.1.0


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

* [PATCH for 3.18.y stable 04/22] arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (2 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 03/22] arm, arm64: KVM: handle potential incoherency of readonly memslots shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 05/22] arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option shannon.zhao
                   ` (18 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit 03f1d4c17edb31b41b14ca3a749ae38d2dd6639d upstream.

If a VCPU was originally started with power off (typically to be brought
up by PSCI in SMP configurations), there is no need to clear the
POWER_OFF flag in the kernel, as this flag is only tested during the
init ioctl itself.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/kvm/arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 9e193c8..b160bea 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -661,7 +661,7 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	/*
 	 * Handle the "start in power-off" case by marking the VCPU as paused.
 	 */
-	if (__test_and_clear_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
+	if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
 		vcpu->arch.pause = true;
 
 	return 0;
-- 
2.1.0


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

* [PATCH for 3.18.y stable 05/22] arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (3 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 04/22] arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 06/22] arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu shannon.zhao
                   ` (17 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit 3ad8b3de526a76fbe9466b366059e4958957b88f upstream.

The implementation of KVM_ARM_VCPU_INIT is currently not doing what
userspace expects, namely making sure that a vcpu which may have been
turned off using PSCI is returned to its initial state, which would be
powered on if userspace does not set the KVM_ARM_VCPU_POWER_OFF flag.

Implement the expected functionality and clarify the ABI.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 Documentation/virtual/kvm/api.txt | 3 ++-
 arch/arm/kvm/arm.c                | 2 ++
 2 files changed, 4 insertions(+), 1 deletion(-)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index 7610eaa..bb82a90 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2455,7 +2455,8 @@ should be created before this ioctl is invoked.
 
 Possible features:
 	- KVM_ARM_VCPU_POWER_OFF: Starts the CPU in a power-off state.
-	  Depends on KVM_CAP_ARM_PSCI.
+	  Depends on KVM_CAP_ARM_PSCI.  If not set, the CPU will be powered on
+	  and execute guest code when KVM_RUN is called.
 	- KVM_ARM_VCPU_EL1_32BIT: Starts the CPU in a 32bit mode.
 	  Depends on KVM_CAP_ARM_EL1_32BIT (arm64 only).
 	- KVM_ARM_VCPU_PSCI_0_2: Emulate PSCI v0.2 for the CPU.
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index b160bea..edc1964 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -663,6 +663,8 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	 */
 	if (test_bit(KVM_ARM_VCPU_POWER_OFF, vcpu->arch.features))
 		vcpu->arch.pause = true;
+	else
+		vcpu->arch.pause = false;
 
 	return 0;
 }
-- 
2.1.0


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

* [PATCH for 3.18.y stable 06/22] arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (4 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 05/22] arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 07/22] arm/arm64: KVM: Turn off vcpus on PSCI shutdown/reboot shannon.zhao
                   ` (16 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit b856a59141b1066d3c896a0d0231f84dabd040af upstream.

When userspace resets the vcpu using KVM_ARM_VCPU_INIT, we should also
reset the HCR, because we now modify the HCR dynamically to
enable/disable trapping of guest accesses to the VM registers.

This is crucial for reboot of VMs working since otherwise we will not be
doing the necessary cache maintenance operations when faulting in pages
with the guest MMU off.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_emulate.h   | 5 +++++
 arch/arm/kvm/arm.c                   | 2 ++
 arch/arm/kvm/guest.c                 | 1 -
 arch/arm64/include/asm/kvm_emulate.h | 5 +++++
 arch/arm64/kvm/guest.c               | 1 -
 5 files changed, 12 insertions(+), 2 deletions(-)

diff --git a/arch/arm/include/asm/kvm_emulate.h b/arch/arm/include/asm/kvm_emulate.h
index b9db269..66ce176 100644
--- a/arch/arm/include/asm/kvm_emulate.h
+++ b/arch/arm/include/asm/kvm_emulate.h
@@ -33,6 +33,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu);
 void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
 void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
 
+static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.hcr = HCR_GUEST_MASK;
+}
+
 static inline bool vcpu_mode_is_32bit(struct kvm_vcpu *vcpu)
 {
 	return 1;
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index edc1964..24c9ca4 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -658,6 +658,8 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	if (ret)
 		return ret;
 
+	vcpu_reset_hcr(vcpu);
+
 	/*
 	 * Handle the "start in power-off" case by marking the VCPU as paused.
 	 */
diff --git a/arch/arm/kvm/guest.c b/arch/arm/kvm/guest.c
index cc0b787..8c97208 100644
--- a/arch/arm/kvm/guest.c
+++ b/arch/arm/kvm/guest.c
@@ -38,7 +38,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.hcr = HCR_GUEST_MASK;
 	return 0;
 }
 
diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 5674a55..8127e45 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -38,6 +38,11 @@ void kvm_inject_undefined(struct kvm_vcpu *vcpu);
 void kvm_inject_dabt(struct kvm_vcpu *vcpu, unsigned long addr);
 void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
 
+static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
+}
+
 static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
 {
 	return (unsigned long *)&vcpu_gp_regs(vcpu)->regs.pc;
diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 7679469..84d5959 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -38,7 +38,6 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
 
 int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
 	return 0;
 }
 
-- 
2.1.0


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

* [PATCH for 3.18.y stable 07/22] arm/arm64: KVM: Turn off vcpus on PSCI shutdown/reboot
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (5 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 06/22] arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 08/22] arm/arm64: KVM: Introduce stage2_unmap_vm shannon.zhao
                   ` (15 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit cf5d318865e25f887d49a0c6083bbc6dcd1905b1 upstream.

When a vcpu calls SYSTEM_OFF or SYSTEM_RESET with PSCI v0.2, the vcpus
should really be turned off for the VM adhering to the suggestions in
the PSCI spec, and it's the sane thing to do.

Also, clarify the behavior and expectations for exits to user space with
the KVM_EXIT_SYSTEM_EVENT case.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 Documentation/virtual/kvm/api.txt |  9 +++++++++
 arch/arm/kvm/psci.c               | 18 ++++++++++++++++++
 arch/arm64/include/asm/kvm_host.h |  1 +
 3 files changed, 28 insertions(+)

diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
index bb82a90..702bb25 100644
--- a/Documentation/virtual/kvm/api.txt
+++ b/Documentation/virtual/kvm/api.txt
@@ -2952,6 +2952,15 @@ HVC instruction based PSCI call from the vcpu. The 'type' field describes
 the system-level event type. The 'flags' field describes architecture
 specific flags for the system-level event.
 
+Valid values for 'type' are:
+  KVM_SYSTEM_EVENT_SHUTDOWN -- the guest has requested a shutdown of the
+   VM. Userspace is not obliged to honour this, and if it does honour
+   this does not need to destroy the VM synchronously (ie it may call
+   KVM_RUN again before shutdown finally occurs).
+  KVM_SYSTEM_EVENT_RESET -- the guest has requested a reset of the VM.
+   As with SHUTDOWN, userspace can choose to ignore the request, or
+   to schedule the reset to occur in the future and may call KVM_RUN again.
+
 		/* Fix the size of the union. */
 		char padding[256];
 	};
diff --git a/arch/arm/kvm/psci.c b/arch/arm/kvm/psci.c
index 09cf377..58cb324 100644
--- a/arch/arm/kvm/psci.c
+++ b/arch/arm/kvm/psci.c
@@ -15,6 +15,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include <linux/preempt.h>
 #include <linux/kvm_host.h>
 #include <linux/wait.h>
 
@@ -166,6 +167,23 @@ static unsigned long kvm_psci_vcpu_affinity_info(struct kvm_vcpu *vcpu)
 
 static void kvm_prepare_system_event(struct kvm_vcpu *vcpu, u32 type)
 {
+	int i;
+	struct kvm_vcpu *tmp;
+
+	/*
+	 * The KVM ABI specifies that a system event exit may call KVM_RUN
+	 * again and may perform shutdown/reboot at a later time that when the
+	 * actual request is made.  Since we are implementing PSCI and a
+	 * caller of PSCI reboot and shutdown expects that the system shuts
+	 * down or reboots immediately, let's make sure that VCPUs are not run
+	 * after this call is handled and before the VCPUs have been
+	 * re-initialized.
+	 */
+	kvm_for_each_vcpu(i, tmp, vcpu->kvm) {
+		tmp->arch.pause = true;
+		kvm_vcpu_kick(tmp);
+	}
+
 	memset(&vcpu->run->system_event, 0, sizeof(vcpu->run->system_event));
 	vcpu->run->system_event.type = type;
 	vcpu->run->exit_reason = KVM_EXIT_SYSTEM_EVENT;
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index 2012c4b..dbd3212 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -200,6 +200,7 @@ struct kvm_vcpu *kvm_arm_get_running_vcpu(void);
 struct kvm_vcpu * __percpu *kvm_get_running_vcpus(void);
 
 u64 kvm_call_hyp(void *hypfn, ...);
+void force_vm_exit(const cpumask_t *mask);
 
 int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
 		int exception_index);
-- 
2.1.0


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

* [PATCH for 3.18.y stable 08/22] arm/arm64: KVM: Introduce stage2_unmap_vm
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (6 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 07/22] arm/arm64: KVM: Turn off vcpus on PSCI shutdown/reboot shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 09/22] arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps() shannon.zhao
                   ` (14 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit 957db105c99792ae8ef61ffc9ae77d910f6471da upstream.

Introduce a new function to unmap user RAM regions in the stage2 page
tables.  This is needed on reboot (or when the guest turns off the MMU)
to ensure we fault in pages again and make the dcache, RAM, and icache
coherent.

Using unmap_stage2_range for the whole guest physical range does not
work, because that unmaps IO regions (such as the GIC) which will not be
recreated or in the best case faulted in on a page-by-page basis.

Call this function on secondary and subsequent calls to the
KVM_ARM_VCPU_INIT ioctl so that a reset VCPU will detect the guest
Stage-1 MMU is off when faulting in pages and make the caches coherent.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   |  1 +
 arch/arm/kvm/arm.c               |  7 +++++
 arch/arm/kvm/mmu.c               | 65 ++++++++++++++++++++++++++++++++++++++++
 arch/arm64/include/asm/kvm_mmu.h |  1 +
 4 files changed, 74 insertions(+)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index f867060..63e0ecc 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -52,6 +52,7 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
 void free_boot_hyp_pgd(void);
 void free_hyp_pgds(void);
 
+void stage2_unmap_vm(struct kvm *kvm);
 int kvm_alloc_stage2_pgd(struct kvm *kvm);
 void kvm_free_stage2_pgd(struct kvm *kvm);
 int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 24c9ca4..827ff48 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -658,6 +658,13 @@ static int kvm_arch_vcpu_ioctl_vcpu_init(struct kvm_vcpu *vcpu,
 	if (ret)
 		return ret;
 
+	/*
+	 * Ensure a rebooted VM will fault in RAM pages and detect if the
+	 * guest MMU is turned off and flush the caches as needed.
+	 */
+	if (vcpu->arch.has_run_once)
+		stage2_unmap_vm(vcpu->kvm);
+
 	vcpu_reset_hcr(vcpu);
 
 	/*
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 16ae5f0..1dc9778 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -612,6 +612,71 @@ static void unmap_stage2_range(struct kvm *kvm, phys_addr_t start, u64 size)
 	unmap_range(kvm, kvm->arch.pgd, start, size);
 }
 
+static void stage2_unmap_memslot(struct kvm *kvm,
+				 struct kvm_memory_slot *memslot)
+{
+	hva_t hva = memslot->userspace_addr;
+	phys_addr_t addr = memslot->base_gfn << PAGE_SHIFT;
+	phys_addr_t size = PAGE_SIZE * memslot->npages;
+	hva_t reg_end = hva + size;
+
+	/*
+	 * A memory region could potentially cover multiple VMAs, and any holes
+	 * between them, so iterate over all of them to find out if we should
+	 * unmap any of them.
+	 *
+	 *     +--------------------------------------------+
+	 * +---------------+----------------+   +----------------+
+	 * |   : VMA 1     |      VMA 2     |   |    VMA 3  :    |
+	 * +---------------+----------------+   +----------------+
+	 *     |               memory region                |
+	 *     +--------------------------------------------+
+	 */
+	do {
+		struct vm_area_struct *vma = find_vma(current->mm, hva);
+		hva_t vm_start, vm_end;
+
+		if (!vma || vma->vm_start >= reg_end)
+			break;
+
+		/*
+		 * Take the intersection of this VMA with the memory region
+		 */
+		vm_start = max(hva, vma->vm_start);
+		vm_end = min(reg_end, vma->vm_end);
+
+		if (!(vma->vm_flags & VM_PFNMAP)) {
+			gpa_t gpa = addr + (vm_start - memslot->userspace_addr);
+			unmap_stage2_range(kvm, gpa, vm_end - vm_start);
+		}
+		hva = vm_end;
+	} while (hva < reg_end);
+}
+
+/**
+ * stage2_unmap_vm - Unmap Stage-2 RAM mappings
+ * @kvm: The struct kvm pointer
+ *
+ * Go through the memregions and unmap any reguler RAM
+ * backing memory already mapped to the VM.
+ */
+void stage2_unmap_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_unmap_memslot(kvm, memslot);
+
+	spin_unlock(&kvm->mmu_lock);
+	srcu_read_unlock(&kvm->srcu, idx);
+}
+
 /**
  * kvm_free_stage2_pgd - free all stage-2 tables
  * @kvm:	The KVM struct pointer for the VM.
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 123b521..14a74f1 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -83,6 +83,7 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t);
 void free_boot_hyp_pgd(void);
 void free_hyp_pgds(void);
 
+void stage2_unmap_vm(struct kvm *kvm);
 int kvm_alloc_stage2_pgd(struct kvm *kvm);
 void kvm_free_stage2_pgd(struct kvm *kvm);
 int kvm_phys_addr_ioremap(struct kvm *kvm, phys_addr_t guest_ipa,
-- 
2.1.0


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

* [PATCH for 3.18.y stable 09/22] arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps()
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (7 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 08/22] arm/arm64: KVM: Introduce stage2_unmap_vm shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 10/22] arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized shannon.zhao
                   ` (13 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Peter Maydell

From: Peter Maydell <peter.maydell@linaro.org>

commit 6d3cfbe21bef5b66530b50ad16c88fdc71a04c35 upstream.

VGIC initialization currently happens in three phases:
 (1) kvm_vgic_create() (triggered by userspace GIC creation)
 (2) vgic_init_maps() (triggered by userspace GIC register read/write
     requests, or from kvm_vgic_init() if not already run)
 (3) kvm_vgic_init() (triggered by first VM run)

We were doing initialization of some state to correspond with the
state of a freshly-reset GIC in kvm_vgic_init(); this is too late,
since it will overwrite changes made by userspace using the
register access APIs before the VM is run. Move this initialization
earlier, into the vgic_init_maps() phase.

This fixes a bug where QEMU could successfully restore a saved
VM state snapshot into a VM that had already been run, but could
not restore it "from cold" using the -loadvm command line option
(the symptoms being that the restored VM would run but interrupts
were ignored).

Finally rename vgic_init_maps to vgic_init and renamed kvm_vgic_init to
kvm_vgic_map_resources.

  [ This patch is originally written by Peter Maydell, but I have
    modified it somewhat heavily, renaming various bits and moving code
    around.  If something is broken, I am to be blamed. - Christoffer ]

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/kvm/arm.c     |  6 ++--
 include/kvm/arm_vgic.h |  4 +--
 virt/kvm/arm/vgic.c    | 77 +++++++++++++++++++++-----------------------------
 3 files changed, 37 insertions(+), 50 deletions(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 827ff48..448314b 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -427,11 +427,11 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	vcpu->arch.has_run_once = true;
 
 	/*
-	 * Initialize the VGIC before running a vcpu the first time on
-	 * this VM.
+	 * Map the VGIC hardware resources before running a vcpu the first
+	 * time on this VM.
 	 */
 	if (unlikely(!vgic_initialized(vcpu->kvm))) {
-		ret = kvm_vgic_init(vcpu->kvm);
+		ret = kvm_vgic_map_resources(vcpu->kvm);
 		if (ret)
 			return ret;
 	}
diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index 206dcc3..fe9783b 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -274,7 +274,7 @@ struct kvm_exit_mmio;
 #ifdef CONFIG_KVM_ARM_VGIC
 int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr, bool write);
 int kvm_vgic_hyp_init(void);
-int kvm_vgic_init(struct kvm *kvm);
+int kvm_vgic_map_resources(struct kvm *kvm);
 int kvm_vgic_create(struct kvm *kvm);
 void kvm_vgic_destroy(struct kvm *kvm);
 void kvm_vgic_vcpu_destroy(struct kvm_vcpu *vcpu);
@@ -321,7 +321,7 @@ static inline int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64 *addr,
 	return -ENXIO;
 }
 
-static inline int kvm_vgic_init(struct kvm *kvm)
+static inline int kvm_vgic_map_resources(struct kvm *kvm)
 {
 	return 0;
 }
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index aacdb59..91e6bfc 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -91,6 +91,7 @@
 #define ACCESS_WRITE_VALUE	(3 << 1)
 #define ACCESS_WRITE_MASK(x)	((x) & (3 << 1))
 
+static int vgic_init(struct kvm *kvm);
 static void vgic_retire_disabled_irqs(struct kvm_vcpu *vcpu);
 static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu);
 static void vgic_update_state(struct kvm *kvm);
@@ -1726,39 +1727,14 @@ static int vgic_vcpu_init_maps(struct kvm_vcpu *vcpu, int nr_irqs)
 
 	int sz = (nr_irqs - VGIC_NR_PRIVATE_IRQS) / 8;
 	vgic_cpu->pending_shared = kzalloc(sz, GFP_KERNEL);
-	vgic_cpu->vgic_irq_lr_map = kzalloc(nr_irqs, GFP_KERNEL);
+	vgic_cpu->vgic_irq_lr_map = kmalloc(nr_irqs, GFP_KERNEL);
 
 	if (!vgic_cpu->pending_shared || !vgic_cpu->vgic_irq_lr_map) {
 		kvm_vgic_vcpu_destroy(vcpu);
 		return -ENOMEM;
 	}
 
-	return 0;
-}
-
-/**
- * kvm_vgic_vcpu_init - Initialize per-vcpu VGIC state
- * @vcpu: pointer to the vcpu struct
- *
- * Initialize the vgic_cpu struct and vgic_dist struct fields pertaining to
- * this vcpu and enable the VGIC for this VCPU
- */
-static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
-{
-	struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
-	struct vgic_dist *dist = &vcpu->kvm->arch.vgic;
-	int i;
-
-	for (i = 0; i < dist->nr_irqs; i++) {
-		if (i < VGIC_NR_PPIS)
-			vgic_bitmap_set_irq_val(&dist->irq_enabled,
-						vcpu->vcpu_id, i, 1);
-		if (i < VGIC_NR_PRIVATE_IRQS)
-			vgic_bitmap_set_irq_val(&dist->irq_cfg,
-						vcpu->vcpu_id, i, VGIC_CFG_EDGE);
-
-		vgic_cpu->vgic_irq_lr_map[i] = LR_EMPTY;
-	}
+	memset(vgic_cpu->vgic_irq_lr_map, LR_EMPTY, nr_irqs);
 
 	/*
 	 * Store the number of LRs per vcpu, so we don't have to go
@@ -1767,7 +1743,7 @@ static void kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
 	 */
 	vgic_cpu->nr_lr = vgic->nr_lr;
 
-	vgic_enable(vcpu);
+	return 0;
 }
 
 void kvm_vgic_destroy(struct kvm *kvm)
@@ -1804,12 +1780,12 @@ void kvm_vgic_destroy(struct kvm *kvm)
  * Allocate and initialize the various data structures. Must be called
  * with kvm->lock held!
  */
-static int vgic_init_maps(struct kvm *kvm)
+static int vgic_init(struct kvm *kvm)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
 	struct kvm_vcpu *vcpu;
 	int nr_cpus, nr_irqs;
-	int ret, i;
+	int ret, i, vcpu_id;
 
 	if (dist->nr_cpus)	/* Already allocated */
 		return 0;
@@ -1859,16 +1835,28 @@ static int vgic_init_maps(struct kvm *kvm)
 	if (ret)
 		goto out;
 
-	kvm_for_each_vcpu(i, vcpu, kvm) {
+	for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4)
+		vgic_set_target_reg(kvm, 0, i);
+
+	kvm_for_each_vcpu(vcpu_id, vcpu, kvm) {
 		ret = vgic_vcpu_init_maps(vcpu, nr_irqs);
 		if (ret) {
 			kvm_err("VGIC: Failed to allocate vcpu memory\n");
 			break;
 		}
-	}
 
-	for (i = VGIC_NR_PRIVATE_IRQS; i < dist->nr_irqs; i += 4)
-		vgic_set_target_reg(kvm, 0, i);
+		for (i = 0; i < dist->nr_irqs; i++) {
+			if (i < VGIC_NR_PPIS)
+				vgic_bitmap_set_irq_val(&dist->irq_enabled,
+							vcpu->vcpu_id, i, 1);
+			if (i < VGIC_NR_PRIVATE_IRQS)
+				vgic_bitmap_set_irq_val(&dist->irq_cfg,
+							vcpu->vcpu_id, i,
+							VGIC_CFG_EDGE);
+		}
+
+		vgic_enable(vcpu);
+	}
 
 out:
 	if (ret)
@@ -1878,18 +1866,16 @@ out:
 }
 
 /**
- * kvm_vgic_init - Initialize global VGIC state before running any VCPUs
+ * kvm_vgic_map_resources - Configure global VGIC state before running any VCPUs
  * @kvm: pointer to the kvm struct
  *
  * Map the virtual CPU interface into the VM before running any VCPUs.  We
  * can't do this at creation time, because user space must first set the
- * virtual CPU interface address in the guest physical address space.  Also
- * initialize the ITARGETSRn regs to 0 on the emulated distributor.
+ * virtual CPU interface address in the guest physical address space.
  */
-int kvm_vgic_init(struct kvm *kvm)
+int kvm_vgic_map_resources(struct kvm *kvm)
 {
-	struct kvm_vcpu *vcpu;
-	int ret = 0, i;
+	int ret = 0;
 
 	if (!irqchip_in_kernel(kvm))
 		return 0;
@@ -1906,7 +1892,11 @@ int kvm_vgic_init(struct kvm *kvm)
 		goto out;
 	}
 
-	ret = vgic_init_maps(kvm);
+	/*
+	 * Initialize the vgic if this hasn't already been done on demand by
+	 * accessing the vgic state from userspace.
+	 */
+	ret = vgic_init(kvm);
 	if (ret) {
 		kvm_err("Unable to allocate maps\n");
 		goto out;
@@ -1920,9 +1910,6 @@ int kvm_vgic_init(struct kvm *kvm)
 		goto out;
 	}
 
-	kvm_for_each_vcpu(i, vcpu, kvm)
-		kvm_vgic_vcpu_init(vcpu);
-
 	kvm->arch.vgic.ready = true;
 out:
 	if (ret)
@@ -2167,7 +2154,7 @@ static int vgic_attr_regs_access(struct kvm_device *dev,
 
 	mutex_lock(&dev->kvm->lock);
 
-	ret = vgic_init_maps(dev->kvm);
+	ret = vgic_init(dev->kvm);
 	if (ret)
 		goto out;
 
-- 
2.1.0


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

* [PATCH for 3.18.y stable 10/22] arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (8 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 09/22] arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps() shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 11/22] arm/arm64: KVM: vgic: kick the specific vcpu instead of iterating through all shannon.zhao
                   ` (12 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit 716139df2517fbc3f2306dbe8eba0fa88dca0189 upstream.

When the vgic initializes its internal state it does so based on the
number of VCPUs available at the time.  If we allow KVM to create more
VCPUs after the VGIC has been initialized, we are likely to error out in
unfortunate ways later, perform buffer overflows etc.

Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/kvm/arm.c | 5 +++++
 1 file changed, 5 insertions(+)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 448314b..546a12e 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -213,6 +213,11 @@ struct kvm_vcpu *kvm_arch_vcpu_create(struct kvm *kvm, unsigned int id)
 	int err;
 	struct kvm_vcpu *vcpu;
 
+	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm)) {
+		err = -EBUSY;
+		goto out;
+	}
+
 	vcpu = kmem_cache_zalloc(kvm_vcpu_cache, GFP_KERNEL);
 	if (!vcpu) {
 		err = -ENOMEM;
-- 
2.1.0


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

* [PATCH for 3.18.y stable 11/22] arm/arm64: KVM: vgic: kick the specific vcpu instead of iterating through all
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (9 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 10/22] arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 12/22] arm/arm64: KVM: Initialize the vgic on-demand when injecting IRQs shannon.zhao
                   ` (11 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Shannon Zhao,
	Marc Zyngier

From: Shannon Zhao <zhaoshenglong@huawei.com>

commit 016ed39c54b8a3db680e5c6a43419f806133caf2 upstream.

When call kvm_vgic_inject_irq to inject interrupt, we can known which
vcpu the interrupt for by the irq_num and the cpuid. So we should just
kick this vcpu to avoid iterating through all.

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <zhaoshenglong@huawei.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 virt/kvm/arm/vgic.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 91e6bfc..12c10f2 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1608,7 +1608,7 @@ static int vgic_validate_injection(struct kvm_vcpu *vcpu, int irq, int level)
 	}
 }
 
-static bool vgic_update_irq_pending(struct kvm *kvm, int cpuid,
+static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 				  unsigned int irq_num, bool level)
 {
 	struct vgic_dist *dist = &kvm->arch.vgic;
@@ -1673,7 +1673,7 @@ static bool vgic_update_irq_pending(struct kvm *kvm, int cpuid,
 out:
 	spin_unlock(&dist->lock);
 
-	return ret;
+	return ret ? cpuid : -EINVAL;
 }
 
 /**
@@ -1693,9 +1693,14 @@ out:
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level)
 {
-	if (likely(vgic_initialized(kvm)) &&
-	    vgic_update_irq_pending(kvm, cpuid, irq_num, level))
-		vgic_kick_vcpus(kvm);
+	int vcpu_id;
+
+	if (likely(vgic_initialized(kvm))) {
+		vcpu_id = vgic_update_irq_pending(kvm, cpuid, irq_num, level);
+		if (vcpu_id >= 0)
+			/* kick the specified vcpu */
+			kvm_vcpu_kick(kvm_get_vcpu(kvm, vcpu_id));
+	}
 
 	return 0;
 }
-- 
2.1.0


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

* [PATCH for 3.18.y stable 12/22] arm/arm64: KVM: Initialize the vgic on-demand when injecting IRQs
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (10 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 11/22] arm/arm64: KVM: vgic: kick the specific vcpu instead of iterating through all shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 13/22] arm/arm64: KVM: Require in-kernel vgic for the arch timers shannon.zhao
                   ` (10 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit ca7d9c829d419c06e450afa5f785d58198c37caa upstream.

Userspace assumes that it can wire up IRQ injections after having
created all VCPUs and after having created the VGIC, but potentially
before starting the first VCPU.  This can currently lead to lost IRQs
because the state of that IRQ injection is not stored anywhere and we
don't return an error to userspace.

We haven't seen this problem manifest itself yet, presumably because
guests reset the devices on boot, but this could cause issues with
migration and other non-standard startup configurations.

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 virt/kvm/arm/vgic.c | 22 ++++++++++++++++------
 1 file changed, 16 insertions(+), 6 deletions(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 12c10f2..9a8c183 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1693,16 +1693,26 @@ out:
 int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int irq_num,
 			bool level)
 {
+	int ret = 0;
 	int vcpu_id;
 
-	if (likely(vgic_initialized(kvm))) {
-		vcpu_id = vgic_update_irq_pending(kvm, cpuid, irq_num, level);
-		if (vcpu_id >= 0)
-			/* kick the specified vcpu */
-			kvm_vcpu_kick(kvm_get_vcpu(kvm, vcpu_id));
+	if (unlikely(!vgic_initialized(kvm))) {
+		mutex_lock(&kvm->lock);
+		ret = vgic_init(kvm);
+		mutex_unlock(&kvm->lock);
+
+		if (ret)
+			goto out;
 	}
 
-	return 0;
+	vcpu_id = vgic_update_irq_pending(kvm, cpuid, irq_num, level);
+	if (vcpu_id >= 0) {
+		/* kick the specified vcpu */
+		kvm_vcpu_kick(kvm_get_vcpu(kvm, vcpu_id));
+	}
+
+out:
+	return ret;
 }
 
 static irqreturn_t vgic_maintenance_handler(int irq, void *data)
-- 
2.1.0


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

* [PATCH for 3.18.y stable 13/22] arm/arm64: KVM: Require in-kernel vgic for the arch timers
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (11 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 12/22] arm/arm64: KVM: Initialize the vgic on-demand when injecting IRQs shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 14/22] KVM: arm/arm64: vgic: vgic_init returns -ENODEV when no online vcpu shannon.zhao
                   ` (9 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao

From: Christoffer Dall <christoffer.dall@linaro.org>

commit 05971120fca43e0357789a14b3386bb56eef2201 upstream.

It is curently possible to run a VM with architected timers support
without creating an in-kernel VGIC, which will result in interrupts from
the virtual timer going nowhere.

To address this issue, move the architected timers initialization to the
time when we run a VCPU for the first time, and then only initialize
(and enable) the architected timers if we have a properly created and
initialized in-kernel VGIC.

When injecting interrupts from the virtual timer to the vgic, the
current setup should ensure that this never calls an on-demand init of
the VGIC, which is the only call path that could return an error from
kvm_vgic_inject_irq(), so capture the return value and raise a warning
if there's an error there.

We also change the kvm_timer_init() function from returning an int to be
a void function, since the function always succeeds.

Reviewed-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/kvm/arm.c           | 13 +++++++++++--
 include/kvm/arm_arch_timer.h | 10 ++++------
 virt/kvm/arm/arch_timer.c    | 30 ++++++++++++++++++++++--------
 3 files changed, 37 insertions(+), 16 deletions(-)

diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 546a12e..20a7a38 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -424,6 +424,7 @@ static void update_vttbr(struct kvm *kvm)
 
 static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 {
+	struct kvm *kvm = vcpu->kvm;
 	int ret;
 
 	if (likely(vcpu->arch.has_run_once))
@@ -435,12 +436,20 @@ static int kvm_vcpu_first_run_init(struct kvm_vcpu *vcpu)
 	 * Map the VGIC hardware resources before running a vcpu the first
 	 * time on this VM.
 	 */
-	if (unlikely(!vgic_initialized(vcpu->kvm))) {
-		ret = kvm_vgic_map_resources(vcpu->kvm);
+	if (unlikely(!vgic_initialized(kvm))) {
+		ret = kvm_vgic_map_resources(kvm);
 		if (ret)
 			return ret;
 	}
 
+	/*
+	 * Enable the arch timers only if we have an in-kernel VGIC
+	 * and it has been properly initialized, since we cannot handle
+	 * interrupts from the virtual timer with a userspace gic.
+	 */
+	if (irqchip_in_kernel(kvm) && vgic_initialized(kvm))
+		kvm_timer_enable(kvm);
+
 	return 0;
 }
 
diff --git a/include/kvm/arm_arch_timer.h b/include/kvm/arm_arch_timer.h
index ad9db60..b3f45a5 100644
--- a/include/kvm/arm_arch_timer.h
+++ b/include/kvm/arm_arch_timer.h
@@ -60,7 +60,8 @@ struct arch_timer_cpu {
 
 #ifdef CONFIG_KVM_ARM_TIMER
 int kvm_timer_hyp_init(void);
-int kvm_timer_init(struct kvm *kvm);
+void kvm_timer_enable(struct kvm *kvm);
+void kvm_timer_init(struct kvm *kvm);
 void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 			  const struct kvm_irq_level *irq);
 void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu);
@@ -77,11 +78,8 @@ static inline int kvm_timer_hyp_init(void)
 	return 0;
 };
 
-static inline int kvm_timer_init(struct kvm *kvm)
-{
-	return 0;
-}
-
+static inline void kvm_timer_enable(struct kvm *kvm) {}
+static inline void kvm_timer_init(struct kvm *kvm) {}
 static inline void kvm_timer_vcpu_reset(struct kvm_vcpu *vcpu,
 					const struct kvm_irq_level *irq) {}
 static inline void kvm_timer_vcpu_init(struct kvm_vcpu *vcpu) {}
diff --git a/virt/kvm/arm/arch_timer.c b/virt/kvm/arm/arch_timer.c
index 22fa819..1c0772b 100644
--- a/virt/kvm/arm/arch_timer.c
+++ b/virt/kvm/arm/arch_timer.c
@@ -61,12 +61,14 @@ static void timer_disarm(struct arch_timer_cpu *timer)
 
 static void kvm_timer_inject_irq(struct kvm_vcpu *vcpu)
 {
+	int ret;
 	struct arch_timer_cpu *timer = &vcpu->arch.timer_cpu;
 
 	timer->cntv_ctl |= ARCH_TIMER_CTRL_IT_MASK;
-	kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
-			    timer->irq->irq,
-			    timer->irq->level);
+	ret = kvm_vgic_inject_irq(vcpu->kvm, vcpu->vcpu_id,
+				  timer->irq->irq,
+				  timer->irq->level);
+	WARN_ON(ret);
 }
 
 static irqreturn_t kvm_arch_timer_handler(int irq, void *dev_id)
@@ -307,12 +309,24 @@ void kvm_timer_vcpu_terminate(struct kvm_vcpu *vcpu)
 	timer_disarm(timer);
 }
 
-int kvm_timer_init(struct kvm *kvm)
+void kvm_timer_enable(struct kvm *kvm)
 {
-	if (timecounter && wqueue) {
-		kvm->arch.timer.cntvoff = kvm_phys_timer_read();
+	if (kvm->arch.timer.enabled)
+		return;
+
+	/*
+	 * There is a potential race here between VCPUs starting for the first
+	 * time, which may be enabling the timer multiple times.  That doesn't
+	 * hurt though, because we're just setting a variable to the same
+	 * variable that it already was.  The important thing is that all
+	 * VCPUs have the enabled variable set, before entering the guest, if
+	 * the arch timers are enabled.
+	 */
+	if (timecounter && wqueue)
 		kvm->arch.timer.enabled = 1;
-	}
+}
 
-	return 0;
+void kvm_timer_init(struct kvm *kvm)
+{
+	kvm->arch.timer.cntvoff = kvm_phys_timer_read();
 }
-- 
2.1.0


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

* [PATCH for 3.18.y stable 14/22] KVM: arm/arm64: vgic: vgic_init returns -ENODEV when no online vcpu
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (12 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 13/22] arm/arm64: KVM: Require in-kernel vgic for the arch timers shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 15/22] arm64: KVM: Fix TLB invalidation by IPA/VMID shannon.zhao
                   ` (8 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Eric Auger

From: Eric Auger <eric.auger@linaro.org>

commit 66b030e48af68fd4c22d343908bc057207a0a31e upstream.

To be more explicit on vgic initialization failure, -ENODEV is
returned by vgic_init when no online vcpus can be found at init.

Signed-off-by: Eric Auger <eric.auger@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 virt/kvm/arm/vgic.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 9a8c183..fc82307 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1807,7 +1807,7 @@ static int vgic_init(struct kvm *kvm)
 
 	nr_cpus = dist->nr_cpus = atomic_read(&kvm->online_vcpus);
 	if (!nr_cpus)		/* No vcpus? Can't be good... */
-		return -EINVAL;
+		return -ENODEV;
 
 	/*
 	 * If nobody configured the number of interrupts, use the
-- 
2.1.0


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

* [PATCH for 3.18.y stable 15/22] arm64: KVM: Fix TLB invalidation by IPA/VMID
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (13 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 14/22] KVM: arm/arm64: vgic: vgic_init returns -ENODEV when no online vcpu shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 16/22] arm64: KVM: Fix HCR setting for 32bit guests shannon.zhao
                   ` (7 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier,
	Paolo Bonzini

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

commit 55e858b75808347378e5117c3c2339f46cc03575 upstream.

It took about two years for someone to notice that the IPA passed
to TLBI IPAS2E1IS must be shifted by 12 bits. Clearly our reviewing
is not as good as it should be...

Paper bag time for me.

Reported-by: Mario Smarduch <m.smarduch@samsung.com>
Tested-by: Mario Smarduch <m.smarduch@samsung.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm64/kvm/hyp.S | 1 +
 1 file changed, 1 insertion(+)

diff --git a/arch/arm64/kvm/hyp.S b/arch/arm64/kvm/hyp.S
index b72aa9f..a767f6a 100644
--- a/arch/arm64/kvm/hyp.S
+++ b/arch/arm64/kvm/hyp.S
@@ -1014,6 +1014,7 @@ ENTRY(__kvm_tlb_flush_vmid_ipa)
 	 * Instead, we invalidate Stage-2 for this IPA, and the
 	 * whole of Stage-1. Weep...
 	 */
+	lsr	x1, x1, #12
 	tlbi	ipas2e1is, x1
 	/*
 	 * We have to ensure completion of the invalidation at Stage-2,
-- 
2.1.0


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

* [PATCH for 3.18.y stable 16/22] arm64: KVM: Fix HCR setting for 32bit guests
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (14 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 15/22] arm64: KVM: Fix TLB invalidation by IPA/VMID shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 17/22] arm/arm64: KVM: Invalidate data cache on unmap shannon.zhao
                   ` (6 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier,
	Paolo Bonzini

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

commit 801f6772cecea6cfc7da61aa197716ab64db5f9e upstream.

Commit b856a59141b1 (arm/arm64: KVM: Reset the HCR on each vcpu
when resetting the vcpu) moved the init of the HCR register to
happen later in the init of a vcpu, but left out the fixup
done in kvm_reset_vcpu when preparing for a 32bit guest.

As a result, the 32bit guest is run as a 64bit guest, but the
rest of the kernel still manages it as a 32bit. Fun follows.

Moving the fixup to vcpu_reset_hcr solves the problem for good.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm64/include/asm/kvm_emulate.h | 2 ++
 arch/arm64/kvm/reset.c               | 1 -
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/arch/arm64/include/asm/kvm_emulate.h b/arch/arm64/include/asm/kvm_emulate.h
index 8127e45..865a7e2 100644
--- a/arch/arm64/include/asm/kvm_emulate.h
+++ b/arch/arm64/include/asm/kvm_emulate.h
@@ -41,6 +41,8 @@ void kvm_inject_pabt(struct kvm_vcpu *vcpu, unsigned long addr);
 static inline void vcpu_reset_hcr(struct kvm_vcpu *vcpu)
 {
 	vcpu->arch.hcr_el2 = HCR_GUEST_FLAGS;
+	if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features))
+		vcpu->arch.hcr_el2 &= ~HCR_RW;
 }
 
 static inline unsigned long *vcpu_pc(const struct kvm_vcpu *vcpu)
diff --git a/arch/arm64/kvm/reset.c b/arch/arm64/kvm/reset.c
index 70a7816..0b43265 100644
--- a/arch/arm64/kvm/reset.c
+++ b/arch/arm64/kvm/reset.c
@@ -90,7 +90,6 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 			if (!cpu_has_32bit_el1())
 				return -EINVAL;
 			cpu_reset = &default_regs_reset32;
-			vcpu->arch.hcr_el2 &= ~HCR_RW;
 		} else {
 			cpu_reset = &default_regs_reset;
 		}
-- 
2.1.0


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

* [PATCH for 3.18.y stable 17/22] arm/arm64: KVM: Invalidate data cache on unmap
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (15 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 16/22] arm64: KVM: Fix HCR setting for 32bit guests shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 18/22] arm/arm64: KVM: Use kernel mapping to perform invalidation on page fault shannon.zhao
                   ` (5 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier

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

commit 363ef89f8e9bcedc28b976d0fe2d858fe139c122 upstream.

Let's assume a guest has created an uncached mapping, and written
to that page. Let's also assume that the host uses a cache-coherent
IO subsystem. Let's finally assume that the host is under memory
pressure and starts to swap things out.

Before this "uncached" page is evicted, we need to make sure
we invalidate potential speculated, clean cache lines that are
sitting there, or the IO subsystem is going to swap out the
cached view, loosing the data that has been written directly
into memory.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   | 31 +++++++++++++++
 arch/arm/kvm/mmu.c               | 82 ++++++++++++++++++++++++++++++++--------
 arch/arm64/include/asm/kvm_mmu.h | 18 +++++++++
 3 files changed, 116 insertions(+), 15 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 63e0ecc..2f78e22 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -44,6 +44,7 @@
 
 #ifndef __ASSEMBLY__
 
+#include <linux/highmem.h>
 #include <asm/cacheflush.h>
 #include <asm/pgalloc.h>
 
@@ -188,6 +189,36 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
 	}
 }
 
+static inline void __kvm_flush_dcache_pte(pte_t pte)
+{
+	void *va = kmap_atomic(pte_page(pte));
+
+	kvm_flush_dcache_to_poc(va, PAGE_SIZE);
+
+	kunmap_atomic(va);
+}
+
+static inline void __kvm_flush_dcache_pmd(pmd_t pmd)
+{
+	unsigned long size = PMD_SIZE;
+	pfn_t pfn = pmd_pfn(pmd);
+
+	while (size) {
+		void *va = kmap_atomic_pfn(pfn);
+
+		kvm_flush_dcache_to_poc(va, PAGE_SIZE);
+
+		pfn++;
+		size -= PAGE_SIZE;
+
+		kunmap_atomic(va);
+	}
+}
+
+static inline void __kvm_flush_dcache_pud(pud_t pud)
+{
+}
+
 #define kvm_virt_to_phys(x)		virt_to_idmap((unsigned long)(x))
 
 void stage2_flush_vm(struct kvm *kvm);
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 1dc9778..8c66163 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -58,6 +58,26 @@ static void kvm_tlb_flush_vmid_ipa(struct kvm *kvm, phys_addr_t ipa)
 		kvm_call_hyp(__kvm_tlb_flush_vmid_ipa, kvm, ipa);
 }
 
+/*
+ * D-Cache management functions. They take the page table entries by
+ * value, as they are flushing the cache using the kernel mapping (or
+ * kmap on 32bit).
+ */
+static void kvm_flush_dcache_pte(pte_t pte)
+{
+	__kvm_flush_dcache_pte(pte);
+}
+
+static void kvm_flush_dcache_pmd(pmd_t pmd)
+{
+	__kvm_flush_dcache_pmd(pmd);
+}
+
+static void kvm_flush_dcache_pud(pud_t pud)
+{
+	__kvm_flush_dcache_pud(pud);
+}
+
 static int mmu_topup_memory_cache(struct kvm_mmu_memory_cache *cache,
 				  int min, int max)
 {
@@ -119,6 +139,26 @@ static void clear_pmd_entry(struct kvm *kvm, pmd_t *pmd, phys_addr_t addr)
 	put_page(virt_to_page(pmd));
 }
 
+/*
+ * Unmapping vs dcache management:
+ *
+ * If a guest maps certain memory pages as uncached, all writes will
+ * bypass the data cache and go directly to RAM.  However, the CPUs
+ * can still speculate reads (not writes) and fill cache lines with
+ * data.
+ *
+ * Those cache lines will be *clean* cache lines though, so a
+ * clean+invalidate operation is equivalent to an invalidate
+ * operation, because no cache lines are marked dirty.
+ *
+ * Those clean cache lines could be filled prior to an uncached write
+ * by the guest, and the cache coherent IO subsystem would therefore
+ * end up writing old data to disk.
+ *
+ * This is why right after unmapping a page/section and invalidating
+ * the corresponding TLBs, we call kvm_flush_dcache_p*() to make sure
+ * the IO subsystem will never hit in the cache.
+ */
 static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
 		       phys_addr_t addr, phys_addr_t end)
 {
@@ -128,9 +168,16 @@ static void unmap_ptes(struct kvm *kvm, pmd_t *pmd,
 	start_pte = pte = pte_offset_kernel(pmd, addr);
 	do {
 		if (!pte_none(*pte)) {
+			pte_t old_pte = *pte;
+
 			kvm_set_pte(pte, __pte(0));
-			put_page(virt_to_page(pte));
 			kvm_tlb_flush_vmid_ipa(kvm, addr);
+
+			/* No need to invalidate the cache for device mappings */
+			if ((pte_val(old_pte) & PAGE_S2_DEVICE) != PAGE_S2_DEVICE)
+				kvm_flush_dcache_pte(old_pte);
+
+			put_page(virt_to_page(pte));
 		}
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 
@@ -149,8 +196,13 @@ static void unmap_pmds(struct kvm *kvm, pud_t *pud,
 		next = kvm_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
 			if (kvm_pmd_huge(*pmd)) {
+				pmd_t old_pmd = *pmd;
+
 				pmd_clear(pmd);
 				kvm_tlb_flush_vmid_ipa(kvm, addr);
+
+				kvm_flush_dcache_pmd(old_pmd);
+
 				put_page(virt_to_page(pmd));
 			} else {
 				unmap_ptes(kvm, pmd, addr, next);
@@ -173,8 +225,13 @@ static void unmap_puds(struct kvm *kvm, pgd_t *pgd,
 		next = kvm_pud_addr_end(addr, end);
 		if (!pud_none(*pud)) {
 			if (pud_huge(*pud)) {
+				pud_t old_pud = *pud;
+
 				pud_clear(pud);
 				kvm_tlb_flush_vmid_ipa(kvm, addr);
+
+				kvm_flush_dcache_pud(old_pud);
+
 				put_page(virt_to_page(pud));
 			} else {
 				unmap_pmds(kvm, pud, addr, next);
@@ -209,10 +266,9 @@ static void stage2_flush_ptes(struct kvm *kvm, pmd_t *pmd,
 
 	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);
-		}
+		if (!pte_none(*pte) &&
+		    (pte_val(*pte) & PAGE_S2_DEVICE) != PAGE_S2_DEVICE)
+			kvm_flush_dcache_pte(*pte);
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
@@ -226,12 +282,10 @@ static void stage2_flush_pmds(struct kvm *kvm, pud_t *pud,
 	do {
 		next = kvm_pmd_addr_end(addr, end);
 		if (!pmd_none(*pmd)) {
-			if (kvm_pmd_huge(*pmd)) {
-				hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT);
-				kvm_flush_dcache_to_poc((void*)hva, PMD_SIZE);
-			} else {
+			if (kvm_pmd_huge(*pmd))
+				kvm_flush_dcache_pmd(*pmd);
+			else
 				stage2_flush_ptes(kvm, pmd, addr, next);
-			}
 		}
 	} while (pmd++, addr = next, addr != end);
 }
@@ -246,12 +300,10 @@ static void stage2_flush_puds(struct kvm *kvm, pgd_t *pgd,
 	do {
 		next = kvm_pud_addr_end(addr, end);
 		if (!pud_none(*pud)) {
-			if (pud_huge(*pud)) {
-				hva_t hva = gfn_to_hva(kvm, addr >> PAGE_SHIFT);
-				kvm_flush_dcache_to_poc((void*)hva, PUD_SIZE);
-			} else {
+			if (pud_huge(*pud))
+				kvm_flush_dcache_pud(*pud);
+			else
 				stage2_flush_pmds(kvm, pud, addr, next);
-			}
 		}
 	} while (pud++, addr = next, addr != end);
 }
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 14a74f1..ea1bca2 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -258,6 +258,24 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
 	}
 }
 
+static inline void __kvm_flush_dcache_pte(pte_t pte)
+{
+	struct page *page = pte_page(pte);
+	kvm_flush_dcache_to_poc(page_address(page), PAGE_SIZE);
+}
+
+static inline void __kvm_flush_dcache_pmd(pmd_t pmd)
+{
+	struct page *page = pmd_page(pmd);
+	kvm_flush_dcache_to_poc(page_address(page), PMD_SIZE);
+}
+
+static inline void __kvm_flush_dcache_pud(pud_t pud)
+{
+	struct page *page = pud_page(pud);
+	kvm_flush_dcache_to_poc(page_address(page), PUD_SIZE);
+}
+
 #define kvm_virt_to_phys(x)		__virt_to_phys((unsigned long)(x))
 
 void stage2_flush_vm(struct kvm *kvm);
-- 
2.1.0


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

* [PATCH for 3.18.y stable 18/22] arm/arm64: KVM: Use kernel mapping to perform invalidation on page fault
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (16 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 17/22] arm/arm64: KVM: Invalidate data cache on unmap shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 19/22] ARM: KVM: Fix size check in __coherent_cache_guest_page shannon.zhao
                   ` (4 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier

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

commit 0d3e4d4fade6b04e933b11e69e80044f35e9cd60 upstream.

When handling a fault in stage-2, we need to resync I$ and D$, just
to be sure we don't leave any old cache line behind.

That's very good, except that we do so using the *user* address.
Under heavy load (swapping like crazy), we may end up in a situation
where the page gets mapped in stage-2 while being unmapped from
userspace by another CPU.

At that point, the DC/IC instructions can generate a fault, which
we handle with kvm->mmu_lock held. The box quickly deadlocks, user
is unhappy.

Instead, perform this invalidation through the kernel mapping,
which is guaranteed to be present. The box is much happier, and so
am I.

Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   | 43 +++++++++++++++++++++++++++++++---------
 arch/arm/kvm/mmu.c               | 12 +++++++----
 arch/arm64/include/asm/kvm_mmu.h | 13 +++++++-----
 3 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index 2f78e22..f95c124 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -162,13 +162,10 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 	return (vcpu->arch.cp15[c1_SCTLR] & 0b101) == 0b101;
 }
 
-static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
-					     unsigned long size,
-					     bool ipa_uncached)
+static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn,
+					       unsigned long size,
+					       bool ipa_uncached)
 {
-	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
-		kvm_flush_dcache_to_poc((void *)hva, size);
-	
 	/*
 	 * If we are going to insert an instruction page and the icache is
 	 * either VIPT or PIPT, there is a potential problem where the host
@@ -180,10 +177,38 @@ static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
 	 *
 	 * VIVT caches are tagged using both the ASID and the VMID and doesn't
 	 * need any kind of flushing (DDI 0406C.b - Page B3-1392).
+	 *
+	 * We need to do this through a kernel mapping (using the
+	 * user-space mapping has proved to be the wrong
+	 * solution). For that, we need to kmap one page at a time,
+	 * and iterate over the range.
 	 */
-	if (icache_is_pipt()) {
-		__cpuc_coherent_user_range(hva, hva + size);
-	} else if (!icache_is_vivt_asid_tagged()) {
+
+	bool need_flush = !vcpu_has_cache_enabled(vcpu) || ipa_uncached;
+
+	VM_BUG_ON(size & PAGE_MASK);
+
+	if (!need_flush && !icache_is_pipt())
+		goto vipt_cache;
+
+	while (size) {
+		void *va = kmap_atomic_pfn(pfn);
+
+		if (need_flush)
+			kvm_flush_dcache_to_poc(va, PAGE_SIZE);
+
+		if (icache_is_pipt())
+			__cpuc_coherent_user_range((unsigned long)va,
+						   (unsigned long)va + PAGE_SIZE);
+
+		size -= PAGE_SIZE;
+		pfn++;
+
+		kunmap_atomic(va);
+	}
+
+vipt_cache:
+	if (!icache_is_pipt() && !icache_is_vivt_asid_tagged()) {
 		/* any kind of VIPT cache */
 		__flush_icache_all();
 	}
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 8c66163..d78fcd8 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -957,6 +957,12 @@ static bool kvm_is_device_pfn(unsigned long pfn)
 	return !pfn_valid(pfn);
 }
 
+static void coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn,
+				      unsigned long size, bool uncached)
+{
+	__coherent_cache_guest_page(vcpu, pfn, size, uncached);
+}
+
 static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			  struct kvm_memory_slot *memslot, unsigned long hva,
 			  unsigned long fault_status)
@@ -1046,8 +1052,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			kvm_set_s2pmd_writable(&new_pmd);
 			kvm_set_pfn_dirty(pfn);
 		}
-		coherent_cache_guest_page(vcpu, hva & PMD_MASK, PMD_SIZE,
-					  fault_ipa_uncached);
+		coherent_cache_guest_page(vcpu, pfn, PMD_SIZE, fault_ipa_uncached);
 		ret = stage2_set_pmd_huge(kvm, memcache, fault_ipa, &new_pmd);
 	} else {
 		pte_t new_pte = pfn_pte(pfn, mem_type);
@@ -1055,8 +1060,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 			kvm_set_s2pte_writable(&new_pte);
 			kvm_set_pfn_dirty(pfn);
 		}
-		coherent_cache_guest_page(vcpu, hva, PAGE_SIZE,
-					  fault_ipa_uncached);
+		coherent_cache_guest_page(vcpu, pfn, PAGE_SIZE, fault_ipa_uncached);
 		ret = stage2_set_pte(kvm, memcache, fault_ipa, &new_pte,
 			pgprot_val(mem_type) == pgprot_val(PAGE_S2_DEVICE));
 	}
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index ea1bca2..4788440 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -243,15 +243,18 @@ static inline bool vcpu_has_cache_enabled(struct kvm_vcpu *vcpu)
 	return (vcpu_sys_reg(vcpu, SCTLR_EL1) & 0b101) == 0b101;
 }
 
-static inline void coherent_cache_guest_page(struct kvm_vcpu *vcpu, hva_t hva,
-					     unsigned long size,
-					     bool ipa_uncached)
+static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn,
+					       unsigned long size,
+					       bool ipa_uncached)
 {
+	void *va = page_address(pfn_to_page(pfn));
+
 	if (!vcpu_has_cache_enabled(vcpu) || ipa_uncached)
-		kvm_flush_dcache_to_poc((void *)hva, size);
+		kvm_flush_dcache_to_poc(va, size);
 
 	if (!icache_is_aliasing()) {		/* PIPT */
-		flush_icache_range(hva, hva + size);
+		flush_icache_range((unsigned long)va,
+				   (unsigned long)va + size);
 	} else if (!icache_is_aivivt()) {	/* non ASID-tagged VIVT */
 		/* any kind of VIPT cache */
 		__flush_icache_all();
-- 
2.1.0


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

* [PATCH for 3.18.y stable 19/22] ARM: KVM: Fix size check in __coherent_cache_guest_page
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (17 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 18/22] arm/arm64: KVM: Use kernel mapping to perform invalidation on page fault shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 20/22] arm64: KVM: Fix stage-2 PGD allocation to have per-page refcounting shannon.zhao
                   ` (3 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Jan Kiszka

From: Jan Kiszka <jan.kiszka@siemens.com>

commit a050dfb21cc22ac0c666d52531040c1bc48184cc upstream.

The check is supposed to catch page-unaligned sizes, not the inverse.

Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index f95c124..d409c9c 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -186,7 +186,7 @@ static inline void __coherent_cache_guest_page(struct kvm_vcpu *vcpu, pfn_t pfn,
 
 	bool need_flush = !vcpu_has_cache_enabled(vcpu) || ipa_uncached;
 
-	VM_BUG_ON(size & PAGE_MASK);
+	VM_BUG_ON(size & ~PAGE_MASK);
 
 	if (!need_flush && !icache_is_pipt())
 		goto vipt_cache;
-- 
2.1.0


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

* [PATCH for 3.18.y stable 20/22] arm64: KVM: Fix stage-2 PGD allocation to have per-page refcounting
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (18 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 19/22] ARM: KVM: Fix size check in __coherent_cache_guest_page shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 21/22] arm64: KVM: Do not use pgd_index to index stage-2 pgd shannon.zhao
                   ` (2 subsequent siblings)
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier

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

commit a987370f8e7a1677ae385042644326d9cd145a20 upstream.

We're using __get_free_pages with to allocate the guest's stage-2
PGD. The standard behaviour of this function is to return a set of
pages where only the head page has a valid refcount.

This behaviour gets us into trouble when we're trying to increment
the refcount on a non-head page:

page:ffff7c00cfb693c0 count:0 mapcount:0 mapping:          (null) index:0x0
flags: 0x4000000000000000()
page dumped because: VM_BUG_ON_PAGE((*({ __attribute__((unused)) typeof((&page->_count)->counter) __var = ( typeof((&page->_count)->counter)) 0; (volatile typeof((&page->_count)->counter) *)&((&page->_count)->counter); })) <= 0)
BUG: failure at include/linux/mm.h:548/get_page()!
Kernel panic - not syncing: BUG!
CPU: 1 PID: 1695 Comm: kvm-vcpu-0 Not tainted 4.0.0-rc1+ #3825
Hardware name: APM X-Gene Mustang board (DT)
Call trace:
[<ffff80000008a09c>] dump_backtrace+0x0/0x13c
[<ffff80000008a1e8>] show_stack+0x10/0x1c
[<ffff800000691da8>] dump_stack+0x74/0x94
[<ffff800000690d78>] panic+0x100/0x240
[<ffff8000000a0bc4>] stage2_get_pmd+0x17c/0x2bc
[<ffff8000000a1dc4>] kvm_handle_guest_abort+0x4b4/0x6b0
[<ffff8000000a420c>] handle_exit+0x58/0x180
[<ffff80000009e7a4>] kvm_arch_vcpu_ioctl_run+0x114/0x45c
[<ffff800000099df4>] kvm_vcpu_ioctl+0x2e0/0x754
[<ffff8000001c0a18>] do_vfs_ioctl+0x424/0x5c8
[<ffff8000001c0bfc>] SyS_ioctl+0x40/0x78
CPU0: stopping

A possible approach for this is to split the compound page using
split_page() at allocation time, and change the teardown path to
free one page at a time.  It turns out that alloc_pages_exact() and
free_pages_exact() does exactly that.

While we're at it, the PGD allocation code is reworked to reduce
duplication.

This has been tested on an X-Gene platform with a 4kB/48bit-VA host
kernel, and kvmtool hacked to place memory in the second page of
the hardware PGD (PUD for the host kernel). Also regression-tested
on a Cubietruck (Cortex-A7).

 [ Reworked to use alloc_pages_exact() and free_pages_exact() and to
   return pointers directly instead of by reference as arguments
    - Christoffer ]

Reported-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   | 10 +++---
 arch/arm/kvm/mmu.c               | 67 +++++++++++++++++++++++++++++-----------
 arch/arm64/include/asm/kvm_mmu.h | 46 +++------------------------
 3 files changed, 57 insertions(+), 66 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index d409c9c..f949cb6 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -141,16 +141,14 @@ static inline bool kvm_page_empty(void *ptr)
 
 #define KVM_PREALLOC_LEVEL	0
 
-static inline int kvm_prealloc_hwpgd(struct kvm *kvm, pgd_t *pgd)
+static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
-	return 0;
+	return kvm->arch.pgd;
 }
 
-static inline void kvm_free_hwpgd(struct kvm *kvm) { }
-
-static inline void *kvm_get_hwpgd(struct kvm *kvm)
+static inline unsigned int kvm_get_hwpgd_size(void)
 {
-	return kvm->arch.pgd;
+	return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
 struct kvm;
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index d78fcd8..203c5ac 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -593,6 +593,20 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
 				     __phys_to_pfn(phys_addr), PAGE_HYP_DEVICE);
 }
 
+/* Free the HW pgd, one page at a time */
+static void kvm_free_hwpgd(void *hwpgd)
+{
+	free_pages_exact(hwpgd, kvm_get_hwpgd_size());
+}
+
+/* Allocate the HW PGD, making sure that each page gets its own refcount */
+static void *kvm_alloc_hwpgd(void)
+{
+	unsigned int size = kvm_get_hwpgd_size();
+
+	return alloc_pages_exact(size, GFP_KERNEL | __GFP_ZERO);
+}
+
 /**
  * kvm_alloc_stage2_pgd - allocate level-1 table for stage-2 translation.
  * @kvm:	The KVM struct pointer for the VM.
@@ -606,15 +620,31 @@ int create_hyp_io_mappings(void *from, void *to, phys_addr_t phys_addr)
  */
 int kvm_alloc_stage2_pgd(struct kvm *kvm)
 {
-	int ret;
 	pgd_t *pgd;
+	void *hwpgd;
 
 	if (kvm->arch.pgd != NULL) {
 		kvm_err("kvm_arch already initialized?\n");
 		return -EINVAL;
 	}
 
+	hwpgd = kvm_alloc_hwpgd();
+	if (!hwpgd)
+		return -ENOMEM;
+
+	/* When the kernel uses more levels of page tables than the
+	 * guest, we allocate a fake PGD and pre-populate it to point
+	 * to the next-level page table, which will be the real
+	 * initial page table pointed to by the VTTBR.
+	 *
+	 * When KVM_PREALLOC_LEVEL==2, we allocate a single page for
+	 * the PMD and the kernel will use folded pud.
+	 * When KVM_PREALLOC_LEVEL==1, we allocate 2 consecutive PUD
+	 * pages.
+	 */
 	if (KVM_PREALLOC_LEVEL > 0) {
+		int i;
+
 		/*
 		 * Allocate fake pgd for the page table manipulation macros to
 		 * work.  This is not used by the hardware and we have no
@@ -622,30 +652,32 @@ int kvm_alloc_stage2_pgd(struct kvm *kvm)
 		 */
 		pgd = (pgd_t *)kmalloc(PTRS_PER_S2_PGD * sizeof(pgd_t),
 				       GFP_KERNEL | __GFP_ZERO);
+
+		if (!pgd) {
+			kvm_free_hwpgd(hwpgd);
+			return -ENOMEM;
+		}
+
+		/* Plug the HW PGD into the fake one. */
+		for (i = 0; i < PTRS_PER_S2_PGD; i++) {
+			if (KVM_PREALLOC_LEVEL == 1)
+				pgd_populate(NULL, pgd + i,
+					     (pud_t *)hwpgd + i * PTRS_PER_PUD);
+			else if (KVM_PREALLOC_LEVEL == 2)
+				pud_populate(NULL, pud_offset(pgd, 0) + i,
+					     (pmd_t *)hwpgd + i * PTRS_PER_PMD);
+		}
 	} else {
 		/*
 		 * Allocate actual first-level Stage-2 page table used by the
 		 * hardware for Stage-2 page table walks.
 		 */
-		pgd = (pgd_t *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, S2_PGD_ORDER);
+		pgd = (pgd_t *)hwpgd;
 	}
 
-	if (!pgd)
-		return -ENOMEM;
-
-	ret = kvm_prealloc_hwpgd(kvm, pgd);
-	if (ret)
-		goto out_err;
-
 	kvm_clean_pgd(pgd);
 	kvm->arch.pgd = pgd;
 	return 0;
-out_err:
-	if (KVM_PREALLOC_LEVEL > 0)
-		kfree(pgd);
-	else
-		free_pages((unsigned long)pgd, S2_PGD_ORDER);
-	return ret;
 }
 
 /**
@@ -746,11 +778,10 @@ void kvm_free_stage2_pgd(struct kvm *kvm)
 		return;
 
 	unmap_stage2_range(kvm, 0, KVM_PHYS_SIZE);
-	kvm_free_hwpgd(kvm);
+	kvm_free_hwpgd(kvm_get_hwpgd(kvm));
 	if (KVM_PREALLOC_LEVEL > 0)
 		kfree(kvm->arch.pgd);
-	else
-		free_pages((unsigned long)kvm->arch.pgd, S2_PGD_ORDER);
+
 	kvm->arch.pgd = NULL;
 }
 
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 4788440..93f1a4c 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -150,43 +150,6 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
 #define KVM_PREALLOC_LEVEL	(0)
 #endif
 
-/**
- * kvm_prealloc_hwpgd - allocate inital table for VTTBR
- * @kvm:	The KVM struct pointer for the VM.
- * @pgd:	The kernel pseudo pgd
- *
- * When the kernel uses more levels of page tables than the guest, we allocate
- * a fake PGD and pre-populate it to point to the next-level page table, which
- * will be the real initial page table pointed to by the VTTBR.
- *
- * When KVM_PREALLOC_LEVEL==2, we allocate a single page for the PMD and
- * the kernel will use folded pud.  When KVM_PREALLOC_LEVEL==1, we
- * allocate 2 consecutive PUD pages.
- */
-static inline int kvm_prealloc_hwpgd(struct kvm *kvm, pgd_t *pgd)
-{
-	unsigned int i;
-	unsigned long hwpgd;
-
-	if (KVM_PREALLOC_LEVEL == 0)
-		return 0;
-
-	hwpgd = __get_free_pages(GFP_KERNEL | __GFP_ZERO, PTRS_PER_S2_PGD_SHIFT);
-	if (!hwpgd)
-		return -ENOMEM;
-
-	for (i = 0; i < PTRS_PER_S2_PGD; i++) {
-		if (KVM_PREALLOC_LEVEL == 1)
-			pgd_populate(NULL, pgd + i,
-				     (pud_t *)hwpgd + i * PTRS_PER_PUD);
-		else if (KVM_PREALLOC_LEVEL == 2)
-			pud_populate(NULL, pud_offset(pgd, 0) + i,
-				     (pmd_t *)hwpgd + i * PTRS_PER_PMD);
-	}
-
-	return 0;
-}
-
 static inline void *kvm_get_hwpgd(struct kvm *kvm)
 {
 	pgd_t *pgd = kvm->arch.pgd;
@@ -203,12 +166,11 @@ static inline void *kvm_get_hwpgd(struct kvm *kvm)
 	return pmd_offset(pud, 0);
 }
 
-static inline void kvm_free_hwpgd(struct kvm *kvm)
+static inline unsigned int kvm_get_hwpgd_size(void)
 {
-	if (KVM_PREALLOC_LEVEL > 0) {
-		unsigned long hwpgd = (unsigned long)kvm_get_hwpgd(kvm);
-		free_pages(hwpgd, PTRS_PER_S2_PGD_SHIFT);
-	}
+	if (KVM_PREALLOC_LEVEL > 0)
+		return PTRS_PER_S2_PGD * PAGE_SIZE;
+	return PTRS_PER_S2_PGD * sizeof(pgd_t);
 }
 
 static inline bool kvm_page_empty(void *ptr)
-- 
2.1.0


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

* [PATCH for 3.18.y stable 21/22] arm64: KVM: Do not use pgd_index to index stage-2 pgd
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (19 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 20/22] arm64: KVM: Fix stage-2 PGD allocation to have per-page refcounting shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 22/22] arm/arm64: KVM: Keep elrsr/aisr in sync with software model shannon.zhao
  2015-05-11  9:40 ` [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel Shannon Zhao
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier

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

commit 04b8dc85bf4a64517e3cf20e409eeaa503b15cc1 upstream.

The kernel's pgd_index macro is designed to index a normal, page
sized array. KVM is a bit diffferent, as we can use concatenated
pages to have a bigger address space (for example 40bit IPA with
4kB pages gives us an 8kB PGD.

In the above case, the use of pgd_index will always return an index
inside the first 4kB, which makes a guest that has memory above
0x8000000000 rather unhappy, as it spins forever in a page fault,
whist the host happilly corrupts the lower pgd.

The obvious fix is to get our own kvm_pgd_index that does the right
thing(tm).

Tested on X-Gene with a hacked kvmtool that put memory at a stupidly
high address.

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 arch/arm/include/asm/kvm_mmu.h   | 3 ++-
 arch/arm/kvm/mmu.c               | 6 +++---
 arch/arm64/include/asm/kvm_mmu.h | 2 ++
 3 files changed, 7 insertions(+), 4 deletions(-)

diff --git a/arch/arm/include/asm/kvm_mmu.h b/arch/arm/include/asm/kvm_mmu.h
index f949cb6..16d9d78 100644
--- a/arch/arm/include/asm/kvm_mmu.h
+++ b/arch/arm/include/asm/kvm_mmu.h
@@ -128,13 +128,14 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
 	(__boundary - 1 < (end) - 1)? __boundary: (end);		\
 })
 
+#define kvm_pgd_index(addr)			pgd_index(addr)
+
 static inline bool kvm_page_empty(void *ptr)
 {
 	struct page *ptr_page = virt_to_page(ptr);
 	return page_count(ptr_page) == 1;
 }
 
-
 #define kvm_pte_table_empty(kvm, ptep) kvm_page_empty(ptep)
 #define kvm_pmd_table_empty(kvm, pmdp) kvm_page_empty(pmdp)
 #define kvm_pud_table_empty(kvm, pudp) (0)
diff --git a/arch/arm/kvm/mmu.c b/arch/arm/kvm/mmu.c
index 203c5ac..cba52cf 100644
--- a/arch/arm/kvm/mmu.c
+++ b/arch/arm/kvm/mmu.c
@@ -251,7 +251,7 @@ static void unmap_range(struct kvm *kvm, pgd_t *pgdp,
 	phys_addr_t addr = start, end = start + size;
 	phys_addr_t next;
 
-	pgd = pgdp + pgd_index(addr);
+	pgd = pgdp + kvm_pgd_index(addr);
 	do {
 		next = kvm_pgd_addr_end(addr, end);
 		if (!pgd_none(*pgd))
@@ -316,7 +316,7 @@ static void stage2_flush_memslot(struct kvm *kvm,
 	phys_addr_t next;
 	pgd_t *pgd;
 
-	pgd = kvm->arch.pgd + pgd_index(addr);
+	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
 	do {
 		next = kvm_pgd_addr_end(addr, end);
 		stage2_flush_puds(kvm, pgd, addr, next);
@@ -791,7 +791,7 @@ static pud_t *stage2_get_pud(struct kvm *kvm, struct kvm_mmu_memory_cache *cache
 	pgd_t *pgd;
 	pud_t *pud;
 
-	pgd = kvm->arch.pgd + pgd_index(addr);
+	pgd = kvm->arch.pgd + kvm_pgd_index(addr);
 	if (WARN_ON(pgd_none(*pgd))) {
 		if (!cache)
 			return NULL;
diff --git a/arch/arm64/include/asm/kvm_mmu.h b/arch/arm64/include/asm/kvm_mmu.h
index 93f1a4c..a205e95 100644
--- a/arch/arm64/include/asm/kvm_mmu.h
+++ b/arch/arm64/include/asm/kvm_mmu.h
@@ -137,6 +137,8 @@ static inline void kvm_set_s2pmd_writable(pmd_t *pmd)
 #define PTRS_PER_S2_PGD		(1 << PTRS_PER_S2_PGD_SHIFT)
 #define S2_PGD_ORDER		get_order(PTRS_PER_S2_PGD * sizeof(pgd_t))
 
+#define kvm_pgd_index(addr)	(((addr) >> PGDIR_SHIFT) & (PTRS_PER_S2_PGD - 1))
+
 /*
  * If we are concatenating first level stage-2 page tables, we would have less
  * than or equal to 16 pointers in the fake PGD, because that's what the
-- 
2.1.0


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

* [PATCH for 3.18.y stable 22/22] arm/arm64: KVM: Keep elrsr/aisr in sync with software model
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (20 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 21/22] arm64: KVM: Do not use pgd_index to index stage-2 pgd shannon.zhao
@ 2015-05-04  1:25 ` shannon.zhao
  2015-05-11  9:40 ` [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel Shannon Zhao
  22 siblings, 0 replies; 24+ messages in thread
From: shannon.zhao @ 2015-05-04  1:25 UTC (permalink / raw)
  To: stable
  Cc: sasha.levin, christoffer.dall, shannon.zhao, Marc Zyngier,
	Alex Bennée

From: Christoffer Dall <christoffer.dall@linaro.org>

commit ae705930fca6322600690df9dc1c7d0516145a93 upstream.

There is an interesting bug in the vgic code, which manifests itself
when the KVM run loop has a signal pending or needs a vmid generation
rollover after having disabled interrupts but before actually switching
to the guest.

In this case, we flush the vgic as usual, but we sync back the vgic
state and exit to userspace before entering the guest.  The consequence
is that we will be syncing the list registers back to the software model
using the GICH_ELRSR and GICH_EISR from the last execution of the guest,
potentially overwriting a list register containing an interrupt.

This showed up during migration testing where we would capture a state
where the VM has masked the arch timer but there were no interrupts,
resulting in a hung test.

Cc: Marc Zyngier <marc.zyngier@arm.com>
Reported-by: Alex Bennee <alex.bennee@linaro.org>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Shannon Zhao <shannon.zhao@linaro.org>
---
 include/kvm/arm_vgic.h |  1 +
 virt/kvm/arm/vgic-v2.c |  8 ++++++++
 virt/kvm/arm/vgic-v3.c |  8 ++++++++
 virt/kvm/arm/vgic.c    | 16 ++++++++++++++++
 4 files changed, 33 insertions(+)

diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
index fe9783b..3f73f6c 100644
--- a/include/kvm/arm_vgic.h
+++ b/include/kvm/arm_vgic.h
@@ -113,6 +113,7 @@ struct vgic_ops {
 	void	(*sync_lr_elrsr)(struct kvm_vcpu *, int, struct vgic_lr);
 	u64	(*get_elrsr)(const struct kvm_vcpu *vcpu);
 	u64	(*get_eisr)(const struct kvm_vcpu *vcpu);
+	void	(*clear_eisr)(struct kvm_vcpu *vcpu);
 	u32	(*get_interrupt_status)(const struct kvm_vcpu *vcpu);
 	void	(*enable_underflow)(struct kvm_vcpu *vcpu);
 	void	(*disable_underflow)(struct kvm_vcpu *vcpu);
diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c
index 2935405..b9d48e8 100644
--- a/virt/kvm/arm/vgic-v2.c
+++ b/virt/kvm/arm/vgic-v2.c
@@ -72,6 +72,8 @@ static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
 {
 	if (!(lr_desc.state & LR_STATE_MASK))
 		vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr |= (1ULL << lr);
+	else
+		vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr &= ~(1ULL << lr);
 }
 
 static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu)
@@ -84,6 +86,11 @@ static u64 vgic_v2_get_eisr(const struct kvm_vcpu *vcpu)
 	return vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr;
 }
 
+static void vgic_v2_clear_eisr(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.vgic_cpu.vgic_v2.vgic_eisr = 0;
+}
+
 static u32 vgic_v2_get_interrupt_status(const struct kvm_vcpu *vcpu)
 {
 	u32 misr = vcpu->arch.vgic_cpu.vgic_v2.vgic_misr;
@@ -148,6 +155,7 @@ static const struct vgic_ops vgic_v2_ops = {
 	.sync_lr_elrsr		= vgic_v2_sync_lr_elrsr,
 	.get_elrsr		= vgic_v2_get_elrsr,
 	.get_eisr		= vgic_v2_get_eisr,
+	.clear_eisr		= vgic_v2_clear_eisr,
 	.get_interrupt_status	= vgic_v2_get_interrupt_status,
 	.enable_underflow	= vgic_v2_enable_underflow,
 	.disable_underflow	= vgic_v2_disable_underflow,
diff --git a/virt/kvm/arm/vgic-v3.c b/virt/kvm/arm/vgic-v3.c
index 1c2c8ee..58b8af0 100644
--- a/virt/kvm/arm/vgic-v3.c
+++ b/virt/kvm/arm/vgic-v3.c
@@ -86,6 +86,8 @@ static void vgic_v3_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr,
 {
 	if (!(lr_desc.state & LR_STATE_MASK))
 		vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr |= (1U << lr);
+	else
+		vcpu->arch.vgic_cpu.vgic_v3.vgic_elrsr &= ~(1U << lr);
 }
 
 static u64 vgic_v3_get_elrsr(const struct kvm_vcpu *vcpu)
@@ -98,6 +100,11 @@ static u64 vgic_v3_get_eisr(const struct kvm_vcpu *vcpu)
 	return vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr;
 }
 
+static void vgic_v3_clear_eisr(struct kvm_vcpu *vcpu)
+{
+	vcpu->arch.vgic_cpu.vgic_v3.vgic_eisr = 0;
+}
+
 static u32 vgic_v3_get_interrupt_status(const struct kvm_vcpu *vcpu)
 {
 	u32 misr = vcpu->arch.vgic_cpu.vgic_v3.vgic_misr;
@@ -162,6 +169,7 @@ static const struct vgic_ops vgic_v3_ops = {
 	.sync_lr_elrsr		= vgic_v3_sync_lr_elrsr,
 	.get_elrsr		= vgic_v3_get_elrsr,
 	.get_eisr		= vgic_v3_get_eisr,
+	.clear_eisr		= vgic_v3_clear_eisr,
 	.get_interrupt_status	= vgic_v3_get_interrupt_status,
 	.enable_underflow	= vgic_v3_enable_underflow,
 	.disable_underflow	= vgic_v3_disable_underflow,
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index fc82307..28347fc 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1219,6 +1219,11 @@ static inline u64 vgic_get_eisr(struct kvm_vcpu *vcpu)
 	return vgic_ops->get_eisr(vcpu);
 }
 
+static inline void vgic_clear_eisr(struct kvm_vcpu *vcpu)
+{
+	vgic_ops->clear_eisr(vcpu);
+}
+
 static inline u32 vgic_get_interrupt_status(struct kvm_vcpu *vcpu)
 {
 	return vgic_ops->get_interrupt_status(vcpu);
@@ -1258,6 +1263,7 @@ static void vgic_retire_lr(int lr_nr, int irq, struct kvm_vcpu *vcpu)
 	vgic_set_lr(vcpu, lr_nr, vlr);
 	clear_bit(lr_nr, vgic_cpu->lr_used);
 	vgic_cpu->vgic_irq_lr_map[irq] = LR_EMPTY;
+	vgic_sync_lr_elrsr(vcpu, lr_nr, vlr);
 }
 
 /*
@@ -1313,6 +1319,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 			BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
 			vlr.state |= LR_STATE_PENDING;
 			vgic_set_lr(vcpu, lr, vlr);
+			vgic_sync_lr_elrsr(vcpu, lr, vlr);
 			return true;
 		}
 	}
@@ -1334,6 +1341,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
 		vlr.state |= LR_EOI_INT;
 
 	vgic_set_lr(vcpu, lr, vlr);
+	vgic_sync_lr_elrsr(vcpu, lr, vlr);
 
 	return true;
 }
@@ -1502,6 +1510,14 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
 	if (status & INT_STATUS_UNDERFLOW)
 		vgic_disable_underflow(vcpu);
 
+	/*
+	 * In the next iterations of the vcpu loop, if we sync the vgic state
+	 * after flushing it, but before entering the guest (this happens for
+	 * pending signals and vmid rollovers), then make sure we don't pick
+	 * up any old maintenance interrupts here.
+	 */
+	vgic_clear_eisr(vcpu);
+
 	return level_pending;
 }
 
-- 
2.1.0


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

* Re: [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel
  2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
                   ` (21 preceding siblings ...)
  2015-05-04  1:25 ` [PATCH for 3.18.y stable 22/22] arm/arm64: KVM: Keep elrsr/aisr in sync with software model shannon.zhao
@ 2015-05-11  9:40 ` Shannon Zhao
  22 siblings, 0 replies; 24+ messages in thread
From: Shannon Zhao @ 2015-05-11  9:40 UTC (permalink / raw)
  To: stable; +Cc: sasha.levin, christoffer.dall

Ping?

On 2015/5/4 9:25, shannon.zhao@linaro.org wrote:
> From: Shannon Zhao <shannon.zhao@linaro.org>
> 
> For KVM/ARM there are many fixes which have been applied upstream while
> not committed to stable kernels. Here we backport the important fixes
> to 3.18.y stable kernel.
> 
> We have compile-tested each patch on arm/arm64/x86 to make sure the
> series are bisectable and have booted the resulting kernel on Fastmodel
> and started 2 VMs for arm/arm64, and have boot-tested on TC2 and Juno,
> and started a guest.
> 
> These patches are applied on the top of 3.18.12. They can be fetched
> from following address:
> https://git.linaro.org/people/shannon.zhao/linux-stable.git linux-3.18.y
> 
> Thanks,
> Shannon
> 
> Ard Biesheuvel (2):
>   kvm: add a memslot flag for incoherent memory regions
>   arm, arm64: KVM: handle potential incoherency of readonly memslots
> 
> Christoffer Dall (9):
>   arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag
>   arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option
>   arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu
>   arm/arm64: KVM: Turn off vcpus on PSCI shutdown/reboot
>   arm/arm64: KVM: Introduce stage2_unmap_vm
>   arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized
>   arm/arm64: KVM: Initialize the vgic on-demand when injecting IRQs
>   arm/arm64: KVM: Require in-kernel vgic for the arch timers
>   arm/arm64: KVM: Keep elrsr/aisr in sync with software model
> 
> Eric Auger (1):
>   KVM: arm/arm64: vgic: vgic_init returns -ENODEV when no online vcpu
> 
> Jan Kiszka (1):
>   ARM: KVM: Fix size check in __coherent_cache_guest_page
> 
> Laszlo Ersek (1):
>   arm, arm64: KVM: allow forced dcache flush on page faults
> 
> Marc Zyngier (6):
>   arm64: KVM: Fix TLB invalidation by IPA/VMID
>   arm64: KVM: Fix HCR setting for 32bit guests
>   arm/arm64: KVM: Invalidate data cache on unmap
>   arm/arm64: KVM: Use kernel mapping to perform invalidation on page
>     fault
>   arm64: KVM: Fix stage-2 PGD allocation to have per-page refcounting
>   arm64: KVM: Do not use pgd_index to index stage-2 pgd
> 
> Peter Maydell (1):
>   arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps()
> 
> Shannon Zhao (1):
>   arm/arm64: KVM: vgic: kick the specific vcpu instead of iterating
>     through all
> 
>  Documentation/virtual/kvm/api.txt    |  12 +-
>  arch/arm/include/asm/kvm_emulate.h   |   5 +
>  arch/arm/include/asm/kvm_mmu.h       |  87 +++++++++---
>  arch/arm/kvm/arm.c                   |  35 ++++-
>  arch/arm/kvm/guest.c                 |   1 -
>  arch/arm/kvm/mmu.c                   | 251 +++++++++++++++++++++++++++++------
>  arch/arm/kvm/psci.c                  |  18 +++
>  arch/arm64/include/asm/kvm_emulate.h |   7 +
>  arch/arm64/include/asm/kvm_host.h    |   1 +
>  arch/arm64/include/asm/kvm_mmu.h     |  81 +++++------
>  arch/arm64/kvm/guest.c               |   1 -
>  arch/arm64/kvm/hyp.S                 |   1 +
>  arch/arm64/kvm/reset.c               |   1 -
>  include/kvm/arm_arch_timer.h         |  10 +-
>  include/kvm/arm_vgic.h               |   5 +-
>  include/linux/kvm_host.h             |   1 +
>  virt/kvm/arm/arch_timer.c            |  30 +++--
>  virt/kvm/arm/vgic-v2.c               |   8 ++
>  virt/kvm/arm/vgic-v3.c               |   8 ++
>  virt/kvm/arm/vgic.c                  | 122 +++++++++--------
>  20 files changed, 504 insertions(+), 181 deletions(-)
> 

-- 
Shannon

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

end of thread, other threads:[~2015-05-11  9:40 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-05-04  1:25 [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 01/22] kvm: add a memslot flag for incoherent memory regions shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 02/22] arm, arm64: KVM: allow forced dcache flush on page faults shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 03/22] arm, arm64: KVM: handle potential incoherency of readonly memslots shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 04/22] arm/arm64: KVM: Don't clear the VCPU_POWER_OFF flag shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 05/22] arm/arm64: KVM: Correct KVM_ARM_VCPU_INIT power off option shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 06/22] arm/arm64: KVM: Reset the HCR on each vcpu when resetting the vcpu shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 07/22] arm/arm64: KVM: Turn off vcpus on PSCI shutdown/reboot shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 08/22] arm/arm64: KVM: Introduce stage2_unmap_vm shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 09/22] arm/arm64: KVM: vgic: move reset initialization into vgic_init_maps() shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 10/22] arm/arm64: KVM: Don't allow creating VCPUs after vgic_initialized shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 11/22] arm/arm64: KVM: vgic: kick the specific vcpu instead of iterating through all shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 12/22] arm/arm64: KVM: Initialize the vgic on-demand when injecting IRQs shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 13/22] arm/arm64: KVM: Require in-kernel vgic for the arch timers shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 14/22] KVM: arm/arm64: vgic: vgic_init returns -ENODEV when no online vcpu shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 15/22] arm64: KVM: Fix TLB invalidation by IPA/VMID shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 16/22] arm64: KVM: Fix HCR setting for 32bit guests shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 17/22] arm/arm64: KVM: Invalidate data cache on unmap shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 18/22] arm/arm64: KVM: Use kernel mapping to perform invalidation on page fault shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 19/22] ARM: KVM: Fix size check in __coherent_cache_guest_page shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 20/22] arm64: KVM: Fix stage-2 PGD allocation to have per-page refcounting shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 21/22] arm64: KVM: Do not use pgd_index to index stage-2 pgd shannon.zhao
2015-05-04  1:25 ` [PATCH for 3.18.y stable 22/22] arm/arm64: KVM: Keep elrsr/aisr in sync with software model shannon.zhao
2015-05-11  9:40 ` [PATCH for 3.18.y stable 00/22] Backport fixes of KVM/ARM to 3.18.y stable kernel Shannon Zhao

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).