Message ID | 20190328133608.110805-6-marc.zyngier@arm.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | [GIT,PULL] KVM/ARM fixes for 5.1-rc3 | expand |
Hi Suzuki, On 3/28/19 2:36 PM, Marc Zyngier wrote: > From: Suzuki K Poulose <suzuki.poulose@arm.com> > > commit 6794ad5443a2118 ("KVM: arm/arm64: Fix unintended stage 2 PMD mappings") > made the checks to skip huge mappings, stricter. However it introduced > a bug where we still use huge mappings, ignoring the flag to > use PTE mappings, by not reseting the vma_pagesize to PAGE_SIZE. > > Also, the checks do not cover the PUD huge pages, that was > under review during the same period. This patch fixes both > the issues. I face a regression with this patch. My guest gets stuck. I am running on AMD Seattle. Reverting the patch makes things work again for me. I run with qemu. In this scenario I don't use hugepages. I use 64kB page size for both the host and guest. Thanks Eric > > Fixes : 6794ad5443a2118 ("KVM: arm/arm64: Fix unintended stage 2 PMD mappings") > Reported-by: Zenghui Yu <yuzenghui@huawei.com> > Cc: Zenghui Yu <yuzenghui@huawei.com> > Cc: Christoffer Dall <christoffer.dall@arm.com> > Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> > Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> > --- > virt/kvm/arm/mmu.c | 43 +++++++++++++++++++++---------------------- > 1 file changed, 21 insertions(+), 22 deletions(-) > > diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c > index ffd7acdceac7..bcdf978c0d1d 100644 > --- a/virt/kvm/arm/mmu.c > +++ b/virt/kvm/arm/mmu.c > @@ -1594,8 +1594,9 @@ static void kvm_send_hwpoison_signal(unsigned long address, > send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, current); > } > > -static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot, > - unsigned long hva) > +static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot, > + unsigned long hva, > + unsigned long map_size) > { > gpa_t gpa_start; > hva_t uaddr_start, uaddr_end; > @@ -1610,34 +1611,34 @@ static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot, > > /* > * Pages belonging to memslots that don't have the same alignment > - * within a PMD for userspace and IPA cannot be mapped with stage-2 > - * PMD entries, because we'll end up mapping the wrong pages. > + * within a PMD/PUD for userspace and IPA cannot be mapped with stage-2 > + * PMD/PUD entries, because we'll end up mapping the wrong pages. > * > * Consider a layout like the following: > * > * memslot->userspace_addr: > * +-----+--------------------+--------------------+---+ > - * |abcde|fgh Stage-1 PMD | Stage-1 PMD tv|xyz| > + * |abcde|fgh Stage-1 block | Stage-1 block tv|xyz| > * +-----+--------------------+--------------------+---+ > * > * memslot->base_gfn << PAGE_SIZE: > * +---+--------------------+--------------------+-----+ > - * |abc|def Stage-2 PMD | Stage-2 PMD |tvxyz| > + * |abc|def Stage-2 block | Stage-2 block |tvxyz| > * +---+--------------------+--------------------+-----+ > * > - * If we create those stage-2 PMDs, we'll end up with this incorrect > + * If we create those stage-2 blocks, we'll end up with this incorrect > * mapping: > * d -> f > * e -> g > * f -> h > */ > - if ((gpa_start & ~S2_PMD_MASK) != (uaddr_start & ~S2_PMD_MASK)) > + if ((gpa_start & (map_size - 1)) != (uaddr_start & (map_size - 1))) > return false; > > /* > * Next, let's make sure we're not trying to map anything not covered > - * by the memslot. This means we have to prohibit PMD size mappings > - * for the beginning and end of a non-PMD aligned and non-PMD sized > + * by the memslot. This means we have to prohibit block size mappings > + * for the beginning and end of a non-block aligned and non-block sized > * memory slot (illustrated by the head and tail parts of the > * userspace view above containing pages 'abcde' and 'xyz', > * respectively). > @@ -1646,8 +1647,8 @@ static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot, > * userspace_addr or the base_gfn, as both are equally aligned (per > * the check above) and equally sized. > */ > - return (hva & S2_PMD_MASK) >= uaddr_start && > - (hva & S2_PMD_MASK) + S2_PMD_SIZE <= uaddr_end; > + return (hva & ~(map_size - 1)) >= uaddr_start && > + (hva & ~(map_size - 1)) + map_size <= uaddr_end; > } > > static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > @@ -1676,12 +1677,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > return -EFAULT; > } > > - if (!fault_supports_stage2_pmd_mappings(memslot, hva)) > - force_pte = true; > - > - if (logging_active) > - force_pte = true; > - > /* Let's check if we will get back a huge page backed by hugetlbfs */ > down_read(¤t->mm->mmap_sem); > vma = find_vma_intersection(current->mm, hva, hva + 1); > @@ -1692,6 +1687,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > } > > vma_pagesize = vma_kernel_pagesize(vma); > + if (logging_active || > + !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { > + force_pte = true; > + vma_pagesize = PAGE_SIZE; > + } > + > /* > * The stage2 has a minimum of 2 level table (For arm64 see > * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can > @@ -1699,11 +1700,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > * As for PUD huge maps, we must make sure that we have at least > * 3 levels, i.e, PMD is not folded. > */ > - if ((vma_pagesize == PMD_SIZE || > - (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) && > - !force_pte) { > + if (vma_pagesize == PMD_SIZE || > + (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) > gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT; > - } > up_read(¤t->mm->mmap_sem); > > /* We need minimum second+third level pages */ >
On Mon, Apr 01, 2019 at 07:10:37PM +0200, Auger Eric wrote: > Hi Suzuki, > > On 3/28/19 2:36 PM, Marc Zyngier wrote: > > From: Suzuki K Poulose <suzuki.poulose@arm.com> > > > > commit 6794ad5443a2118 ("KVM: arm/arm64: Fix unintended stage 2 PMD mappings") > > made the checks to skip huge mappings, stricter. However it introduced > > a bug where we still use huge mappings, ignoring the flag to > > use PTE mappings, by not reseting the vma_pagesize to PAGE_SIZE. > > > > Also, the checks do not cover the PUD huge pages, that was > > under review during the same period. This patch fixes both > > the issues. > > I face a regression with this patch. My guest gets stuck. I am running > on AMD Seattle. Reverting the patch makes things work again for me. I > run with qemu. In this scenario I don't use hugepages. I use 64kB page > size for both the host and guest. Hi Eric, Thanks for the testing. Does the following patch fix the issue for you ? ---8>--- kvm: arm: Skip transparent huge pages in unaligned memslots We silently create stage2 huge mappings for a memslot with unaligned IPA and user address. Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> --- virt/kvm/arm/mmu.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index 27c9583..4a22f5b 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1412,7 +1412,9 @@ static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) * page accordingly. */ mask = PTRS_PER_PMD - 1; - VM_BUG_ON((gfn & mask) != (pfn & mask)); + /* Skip memslots with unaligned IPA and user address */ + if ((gfn & mask) != (pfn & mask)) + return false; if (pfn & mask) { *ipap &= PMD_MASK; kvm_release_pfn_clean(pfn);
Hi Suzuki, On 4/2/19 11:47 AM, Suzuki K Poulose wrote: > On Mon, Apr 01, 2019 at 07:10:37PM +0200, Auger Eric wrote: >> Hi Suzuki, >> >> On 3/28/19 2:36 PM, Marc Zyngier wrote: >>> From: Suzuki K Poulose <suzuki.poulose@arm.com> >>> >>> commit 6794ad5443a2118 ("KVM: arm/arm64: Fix unintended stage 2 PMD mappings") >>> made the checks to skip huge mappings, stricter. However it introduced >>> a bug where we still use huge mappings, ignoring the flag to >>> use PTE mappings, by not reseting the vma_pagesize to PAGE_SIZE. >>> >>> Also, the checks do not cover the PUD huge pages, that was >>> under review during the same period. This patch fixes both >>> the issues. >> >> I face a regression with this patch. My guest gets stuck. I am running >> on AMD Seattle. Reverting the patch makes things work again for me. I >> run with qemu. In this scenario I don't use hugepages. I use 64kB page >> size for both the host and guest. > > Hi Eric, > > Thanks for the testing. Does the following patch fix the issue for you ? Yes it does. Thanks Eric > > > ---8>--- > kvm: arm: Skip transparent huge pages in unaligned memslots > > We silently create stage2 huge mappings for a memslot with > unaligned IPA and user address. > > Signed-off-by: Suzuki K Poulose <suzuki.poulose@arm.com> > --- > virt/kvm/arm/mmu.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c > index 27c9583..4a22f5b 100644 > --- a/virt/kvm/arm/mmu.c > +++ b/virt/kvm/arm/mmu.c > @@ -1412,7 +1412,9 @@ static bool transparent_hugepage_adjust(kvm_pfn_t *pfnp, phys_addr_t *ipap) > * page accordingly. > */ > mask = PTRS_PER_PMD - 1; > - VM_BUG_ON((gfn & mask) != (pfn & mask)); > + /* Skip memslots with unaligned IPA and user address */ > + if ((gfn & mask) != (pfn & mask)) > + return false; > if (pfn & mask) { > *ipap &= PMD_MASK; > kvm_release_pfn_clean(pfn); >
On Tue, 02 Apr 2019 11:07:28 +0100, Auger Eric <eric.auger@redhat.com> wrote: > > Hi Suzuki, > > On 4/2/19 11:47 AM, Suzuki K Poulose wrote: > > On Mon, Apr 01, 2019 at 07:10:37PM +0200, Auger Eric wrote: > >> Hi Suzuki, > >> > >> On 3/28/19 2:36 PM, Marc Zyngier wrote: > >>> From: Suzuki K Poulose <suzuki.poulose@arm.com> > >>> > >>> commit 6794ad5443a2118 ("KVM: arm/arm64: Fix unintended stage 2 PMD mappings") > >>> made the checks to skip huge mappings, stricter. However it introduced > >>> a bug where we still use huge mappings, ignoring the flag to > >>> use PTE mappings, by not reseting the vma_pagesize to PAGE_SIZE. > >>> > >>> Also, the checks do not cover the PUD huge pages, that was > >>> under review during the same period. This patch fixes both > >>> the issues. > >> > >> I face a regression with this patch. My guest gets stuck. I am running > >> on AMD Seattle. Reverting the patch makes things work again for me. I > >> run with qemu. In this scenario I don't use hugepages. I use 64kB page > >> size for both the host and guest. > > > > Hi Eric, > > > > Thanks for the testing. Does the following patch fix the issue for you ? > > Yes it does. Thanks for testing this. Suzuki, can you please resend this with Eric's TB, and a Fixes: tag? I'll queue it right away. Thanks, M.
diff --git a/virt/kvm/arm/mmu.c b/virt/kvm/arm/mmu.c index ffd7acdceac7..bcdf978c0d1d 100644 --- a/virt/kvm/arm/mmu.c +++ b/virt/kvm/arm/mmu.c @@ -1594,8 +1594,9 @@ static void kvm_send_hwpoison_signal(unsigned long address, send_sig_mceerr(BUS_MCEERR_AR, (void __user *)address, lsb, current); } -static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot, - unsigned long hva) +static bool fault_supports_stage2_huge_mapping(struct kvm_memory_slot *memslot, + unsigned long hva, + unsigned long map_size) { gpa_t gpa_start; hva_t uaddr_start, uaddr_end; @@ -1610,34 +1611,34 @@ static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot, /* * Pages belonging to memslots that don't have the same alignment - * within a PMD for userspace and IPA cannot be mapped with stage-2 - * PMD entries, because we'll end up mapping the wrong pages. + * within a PMD/PUD for userspace and IPA cannot be mapped with stage-2 + * PMD/PUD entries, because we'll end up mapping the wrong pages. * * Consider a layout like the following: * * memslot->userspace_addr: * +-----+--------------------+--------------------+---+ - * |abcde|fgh Stage-1 PMD | Stage-1 PMD tv|xyz| + * |abcde|fgh Stage-1 block | Stage-1 block tv|xyz| * +-----+--------------------+--------------------+---+ * * memslot->base_gfn << PAGE_SIZE: * +---+--------------------+--------------------+-----+ - * |abc|def Stage-2 PMD | Stage-2 PMD |tvxyz| + * |abc|def Stage-2 block | Stage-2 block |tvxyz| * +---+--------------------+--------------------+-----+ * - * If we create those stage-2 PMDs, we'll end up with this incorrect + * If we create those stage-2 blocks, we'll end up with this incorrect * mapping: * d -> f * e -> g * f -> h */ - if ((gpa_start & ~S2_PMD_MASK) != (uaddr_start & ~S2_PMD_MASK)) + if ((gpa_start & (map_size - 1)) != (uaddr_start & (map_size - 1))) return false; /* * Next, let's make sure we're not trying to map anything not covered - * by the memslot. This means we have to prohibit PMD size mappings - * for the beginning and end of a non-PMD aligned and non-PMD sized + * by the memslot. This means we have to prohibit block size mappings + * for the beginning and end of a non-block aligned and non-block sized * memory slot (illustrated by the head and tail parts of the * userspace view above containing pages 'abcde' and 'xyz', * respectively). @@ -1646,8 +1647,8 @@ static bool fault_supports_stage2_pmd_mappings(struct kvm_memory_slot *memslot, * userspace_addr or the base_gfn, as both are equally aligned (per * the check above) and equally sized. */ - return (hva & S2_PMD_MASK) >= uaddr_start && - (hva & S2_PMD_MASK) + S2_PMD_SIZE <= uaddr_end; + return (hva & ~(map_size - 1)) >= uaddr_start && + (hva & ~(map_size - 1)) + map_size <= uaddr_end; } static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, @@ -1676,12 +1677,6 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, return -EFAULT; } - if (!fault_supports_stage2_pmd_mappings(memslot, hva)) - force_pte = true; - - if (logging_active) - force_pte = true; - /* Let's check if we will get back a huge page backed by hugetlbfs */ down_read(¤t->mm->mmap_sem); vma = find_vma_intersection(current->mm, hva, hva + 1); @@ -1692,6 +1687,12 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, } vma_pagesize = vma_kernel_pagesize(vma); + if (logging_active || + !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { + force_pte = true; + vma_pagesize = PAGE_SIZE; + } + /* * The stage2 has a minimum of 2 level table (For arm64 see * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can @@ -1699,11 +1700,9 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, * As for PUD huge maps, we must make sure that we have at least * 3 levels, i.e, PMD is not folded. */ - if ((vma_pagesize == PMD_SIZE || - (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) && - !force_pte) { + if (vma_pagesize == PMD_SIZE || + (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT; - } up_read(¤t->mm->mmap_sem); /* We need minimum second+third level pages */