Patch "arm64: KVM: Do not use pgd_index to index stage-2 pgd" has been added to the 3.19-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.19-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.19 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.
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
@@ -128,13 +128,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 (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)
arch/arm/kvm/mmu.c +3 -3
@@ -251,7 +251,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))
@@ -316,7 +316,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);
@@ -791,7 +791,7 @@ static pud_t *stage2_get_pud(struct kvmpgd_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 ;
arch/arm64/include/asm/kvm_mmu.h +2 -0
@@ -137,6 +137,8 @@ static inline void kvm_set_s2pmd_writabl#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
Patches currently in stable-queue which might be from [email protected] are
queue-3.19/arm64-kvm-do-not-use-pgd_index-to-index-stage-2-pgd.patch queue-3.19/arm-arm64-kvm-keep-elrsr-aisr-in-sync-with-software-model.patch queue-3.19/kvm-arm-arm64-check-irq-number-on-userland-injection.patch queue-3.19/arm64-kvm-fix-stage-2-pgd-allocation-to-have-per-page-refcounting.patch