Patch "arm64: KVM: Do not use pgd_index to index stage-2 pgd" has been added to the 3.14-stable tree
Subsystems (4)
This is a note to let you know that I've just added the patch titled
arm64: KVM: Do not use pgd_index to index stage-2 pgd
to the 3.14-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
arm64-kvm-do-not-use-pgd_index-to-index-stage-2-pgd.patch
and it can be found in the queue-3.14 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
04b8dc85bf4a64517e3cf20e409eeaa503b15cc1Mon Sep 17 00:00:00 2001
From: Marc Zyngier <[email protected]>
Date: Tue, 10 Mar 2015 19:07:00 +0000
Subject: arm64: KVM: Do not use pgd_index to index stage-2 pgd
From: Marc Zyngier <[email protected]>
commit 04b8dc85bf4a64517e3cf20e409eeaa503b15cc1 upstream.
[Since we don't backport commit c647355 (KVM: arm: Add initial dirty page locking support) for linux-3.14.y, there is no stage2_wp_range in arch/arm/kvm/mmu.c. So ignore the change in stage2_wp_range introduced by this patch.]
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.
--- 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(-)
arch/arm/include/asm/kvm_mmu.h +2 -1
@@ -117,13 +117,14 @@ static inline void kvm_set_s2pmd_writabl (__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 (ptep) kvm_page_empty(ptep)#define kvm_pmd_table_empty (pmdp) kvm_page_empty(pmdp)#define kvm_pud_table_empty (pudp) (0)
arch/arm/kvm/mmu.c +3 -3
@@ -194,7 +194,7 @@ static void unmap_range(struct kvm *kvm,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))
@@ -264,7 +264,7 @@ static void stage2_flush_memslot(structphys_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);
@@ -649,7 +649,7 @@ static pmd_t *stage2_get_pmd(struct kvmpud_t *pud;pmd_t *pmd; - pgd = kvm->arch.pgd +pgd_index (addr); + pgd = kvm->arch.pgd +kvm_pgd_index (addr); pud =pud_offset (pgd, addr);if (pud_none (*pud)) {if (!cache)
arch/arm64/include/asm/kvm_mmu.h +2 -0
@@ -69,6 +69,8 @@#define PTRS_PER_S2_PGD (1 << (KVM_PHYS_SHIFT - PGDIR_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)) +int create_hyp_mappings (void *from,void *to);int create_hyp_io_mappings (void *from,void *to,phys_addr_t );void free_boot_hyp_pgd (void );
Patches currently in stable-queue which might be from [email protected] are
queue-3.14/arm64-kvm-fix-hcr-setting-for-32bit-guests.patch queue-3.14/arm64-kvm-do-not-use-pgd_index-to-index-stage-2-pgd.patch queue-3.14/arm64-kvm-fix-tlb-invalidation-by-ipa-vmid.patch queue-3.14/arm-arm64-kvm-keep-elrsr-aisr-in-sync-with-software-model.patch queue-3.14/arm-arm64-kvm-require-in-kernel-vgic-for-the-arch-timers.patch queue-3.14/arm-kvm-force-execution-of-hcptr-access-on-vm-exit.patch