* [PATCH 0/2] KVM: arm64: user_mem_abort() improvements
@ 2020-09-01 13:33 Alexandru Elisei
2020-09-01 13:33 ` [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported Alexandru Elisei
` (2 more replies)
0 siblings, 3 replies; 11+ messages in thread
From: Alexandru Elisei @ 2020-09-01 13:33 UTC (permalink / raw)
To: linux-arm-kernel, kvmarm
Cc: maz, james.morse, julien.thierry.kdev, suzuki.poulose
The first patch is a fix for a bug that I found by code inspection.
The second patch is an enhancement for the way user_mem_abort() handles
hugetlbfs backed VM memory.
Tested on a rockpro64 with 4K pages and hugetlbfs hugepagesz=1G (PUD sized
block mappings). First test, guest RAM starts at 0x8100 0000
(memslot->base_gfn not aligned to 1GB); second test, guest RAM starts at
0x8000 0000, but is only 512 MB. In both cases using PUD mappings is not
possible because either the memslot base address is not aligned, or the
mapping would extend beyond the memslot.
Without the changes, user_mem_abort() uses 4K pages to map the guest IPA.
With the patches, user_mem_abort() uses PMD block mappings (2MB) to map the
guest RAM, which means less TLB pressure and fewer stage 2 aborts.
Alexandru Elisei (2):
KVM: arm64: Update page shift if stage 2 block mapping not supported
KVM: arm64: Try PMD block mappings if PUD mappings are not supported
arch/arm64/kvm/mmu.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
--
2.28.0
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply [flat|nested] 11+ messages in thread* [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported 2020-09-01 13:33 [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Alexandru Elisei @ 2020-09-01 13:33 ` Alexandru Elisei 2020-09-02 0:57 ` Gavin Shan 2020-09-01 13:33 ` [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are " Alexandru Elisei 2020-09-04 10:18 ` [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Marc Zyngier 2 siblings, 1 reply; 11+ messages in thread From: Alexandru Elisei @ 2020-09-01 13:33 UTC (permalink / raw) To: linux-arm-kernel, kvmarm Cc: maz, james.morse, julien.thierry.kdev, suzuki.poulose Commit 196f878a7ac2e (" KVM: arm/arm64: Signal SIGBUS when stage2 discovers hwpoison memory") modifies user_mem_abort() to send a SIGBUS signal when the fault IPA maps to a hwpoisoned page. Commit 1559b7583ff6 ("KVM: arm/arm64: Re-check VMA on detecting a poisoned page") changed kvm_send_hwpoison_signal() to use the page shift instead of the VMA because at that point the code had already released the mmap lock, which means userspace could have modified the VMA. If userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to map the guest fault IPA using block mappings in stage 2. That is not always possible, if, for example, userspace uses dirty page logging for the VM. Update the page shift appropriately in those cases when we downgrade the stage 2 entry from a block mapping to a page. Fixes: 1559b7583ff6 ("KVM: arm/arm64: Re-check VMA on detecting a poisoned page") Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- arch/arm64/kvm/mmu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index ba00bcc0c884..25e7dc52c086 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1877,6 +1877,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { force_pte = true; vma_pagesize = PAGE_SIZE; + vma_shift = PAGE_SHIFT; } /* -- 2.28.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported 2020-09-01 13:33 ` [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported Alexandru Elisei @ 2020-09-02 0:57 ` Gavin Shan 0 siblings, 0 replies; 11+ messages in thread From: Gavin Shan @ 2020-09-02 0:57 UTC (permalink / raw) To: Alexandru Elisei, linux-arm-kernel, kvmarm; +Cc: maz On 9/1/20 11:33 PM, Alexandru Elisei wrote: > Commit 196f878a7ac2e (" KVM: arm/arm64: Signal SIGBUS when stage2 discovers > hwpoison memory") modifies user_mem_abort() to send a SIGBUS signal when > the fault IPA maps to a hwpoisoned page. Commit 1559b7583ff6 ("KVM: > arm/arm64: Re-check VMA on detecting a poisoned page") changed > kvm_send_hwpoison_signal() to use the page shift instead of the VMA because > at that point the code had already released the mmap lock, which means > userspace could have modified the VMA. > > If userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to > map the guest fault IPA using block mappings in stage 2. That is not always > possible, if, for example, userspace uses dirty page logging for the VM. > Update the page shift appropriately in those cases when we downgrade the > stage 2 entry from a block mapping to a page. > > Fixes: 1559b7583ff6 ("KVM: arm/arm64: Re-check VMA on detecting a poisoned page") > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> > --- Reviewed-by: Gavin Shan <gshan@redhat.com> > arch/arm64/kvm/mmu.c | 1 + > 1 file changed, 1 insertion(+) > > diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c > index ba00bcc0c884..25e7dc52c086 100644 > --- a/arch/arm64/kvm/mmu.c > +++ b/arch/arm64/kvm/mmu.c > @@ -1877,6 +1877,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { > force_pte = true; > vma_pagesize = PAGE_SIZE; > + vma_shift = PAGE_SHIFT; > } > > /* > _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-01 13:33 [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Alexandru Elisei 2020-09-01 13:33 ` [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported Alexandru Elisei @ 2020-09-01 13:33 ` Alexandru Elisei 2020-09-02 1:23 ` Gavin Shan 2020-09-04 9:58 ` Marc Zyngier 2020-09-04 10:18 ` [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Marc Zyngier 2 siblings, 2 replies; 11+ messages in thread From: Alexandru Elisei @ 2020-09-01 13:33 UTC (permalink / raw) To: linux-arm-kernel, kvmarm Cc: maz, james.morse, julien.thierry.kdev, suzuki.poulose When userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to use the same block size to map the faulting IPA in stage 2. If stage 2 cannot use the same size mapping because the block size doesn't fit in the memslot or the memslot is not properly aligned, user_mem_abort() will fall back to a page mapping, regardless of the block size. We can do better for PUD backed hugetlbfs by checking if a PMD block mapping is possible before deciding to use a page. vma_pagesize is an unsigned long, use 1UL instead of 1ULL when assigning its value. Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> --- arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c index 25e7dc52c086..f590f7355cda 100644 --- a/arch/arm64/kvm/mmu.c +++ b/arch/arm64/kvm/mmu.c @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, else vma_shift = PAGE_SHIFT; - vma_pagesize = 1ULL << vma_shift; if (logging_active || - (vma->vm_flags & VM_PFNMAP) || - !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { + (vma->vm_flags & VM_PFNMAP)) { force_pte = true; - vma_pagesize = PAGE_SIZE; vma_shift = PAGE_SHIFT; } + if (vma_shift == PUD_SHIFT && + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) + vma_shift = PMD_SHIFT; + + if (vma_shift == PMD_SHIFT && + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { + force_pte = true; + vma_shift = PAGE_SHIFT; + } + + vma_pagesize = 1UL << vma_shift; + /* * The stage2 has a minimum of 2 level table (For arm64 see * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, */ 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; + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; mmap_read_unlock(current->mm); /* We need minimum second+third level pages */ -- 2.28.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply related [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-01 13:33 ` [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are " Alexandru Elisei @ 2020-09-02 1:23 ` Gavin Shan 2020-09-02 9:01 ` Alexandru Elisei 2020-09-04 9:58 ` Marc Zyngier 1 sibling, 1 reply; 11+ messages in thread From: Gavin Shan @ 2020-09-02 1:23 UTC (permalink / raw) To: Alexandru Elisei, linux-arm-kernel, kvmarm; +Cc: maz Hi Alexandru, On 9/1/20 11:33 PM, Alexandru Elisei wrote: > When userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to > use the same block size to map the faulting IPA in stage 2. If stage 2 > cannot use the same size mapping because the block size doesn't fit in the > memslot or the memslot is not properly aligned, user_mem_abort() will fall > back to a page mapping, regardless of the block size. We can do better for > PUD backed hugetlbfs by checking if a PMD block mapping is possible before > deciding to use a page. > > vma_pagesize is an unsigned long, use 1UL instead of 1ULL when assigning > its value. > > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> > --- > arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- > 1 file changed, 14 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c > index 25e7dc52c086..f590f7355cda 100644 > --- a/arch/arm64/kvm/mmu.c > +++ b/arch/arm64/kvm/mmu.c > @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > else > vma_shift = PAGE_SHIFT; > > - vma_pagesize = 1ULL << vma_shift; > if (logging_active || > - (vma->vm_flags & VM_PFNMAP) || > - !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { > + (vma->vm_flags & VM_PFNMAP)) { > force_pte = true; > - vma_pagesize = PAGE_SIZE; > vma_shift = PAGE_SHIFT; > } > It looks incorrect because @vma_pagesize wasn't initialized when it's passed to fault_supports_stage2_huge_mapping() for the checking. It's assumed you missed the following changes according to the commit log: fault_supports_stage2_huge_mapping(memslot, hva, (1UL << vma_shift)) > + if (vma_shift == PUD_SHIFT && > + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) > + vma_shift = PMD_SHIFT; > + > + if (vma_shift == PMD_SHIFT && > + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { > + force_pte = true; > + vma_shift = PAGE_SHIFT; > + } > + > + vma_pagesize = 1UL << vma_shift; > +> /* > * The stage2 has a minimum of 2 level table (For arm64 see > * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can > @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > */ > 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; > + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; > mmap_read_unlock(current->mm); > > /* We need minimum second+third level pages */ > Thanks, Gavin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-02 1:23 ` Gavin Shan @ 2020-09-02 9:01 ` Alexandru Elisei 2020-09-03 0:06 ` Gavin Shan 0 siblings, 1 reply; 11+ messages in thread From: Alexandru Elisei @ 2020-09-02 9:01 UTC (permalink / raw) To: Gavin Shan, linux-arm-kernel, kvmarm; +Cc: maz Hi Gavin, Many thanks for having a look at the patches! On 9/2/20 2:23 AM, Gavin Shan wrote: > Hi Alexandru, > > On 9/1/20 11:33 PM, Alexandru Elisei wrote: >> When userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to >> use the same block size to map the faulting IPA in stage 2. If stage 2 >> cannot use the same size mapping because the block size doesn't fit in the >> memslot or the memslot is not properly aligned, user_mem_abort() will fall >> back to a page mapping, regardless of the block size. We can do better for >> PUD backed hugetlbfs by checking if a PMD block mapping is possible before >> deciding to use a page. >> >> vma_pagesize is an unsigned long, use 1UL instead of 1ULL when assigning >> its value. >> >> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> >> --- >> arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- >> 1 file changed, 14 insertions(+), 5 deletions(-) >> >> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c >> index 25e7dc52c086..f590f7355cda 100644 >> --- a/arch/arm64/kvm/mmu.c >> +++ b/arch/arm64/kvm/mmu.c >> @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, >> phys_addr_t fault_ipa, >> else >> vma_shift = PAGE_SHIFT; >> - vma_pagesize = 1ULL << vma_shift; >> if (logging_active || >> - (vma->vm_flags & VM_PFNMAP) || >> - !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { >> + (vma->vm_flags & VM_PFNMAP)) { >> force_pte = true; >> - vma_pagesize = PAGE_SIZE; >> vma_shift = PAGE_SHIFT; >> } >> > > It looks incorrect because @vma_pagesize wasn't initialized when > it's passed to fault_supports_stage2_huge_mapping() for the checking. > It's assumed you missed the following changes according to the commit > log: > > fault_supports_stage2_huge_mapping(memslot, hva, (1UL << vma_shift)) I'm not sure what you mean. Maybe you've misread the diff? Because the above call to fault_supports_stage2_huge_mapping() was removed by the patch. Thanks, Alex > >> + if (vma_shift == PUD_SHIFT && >> + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) >> + vma_shift = PMD_SHIFT; >> + >> + if (vma_shift == PMD_SHIFT && >> + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { >> + force_pte = true; >> + vma_shift = PAGE_SHIFT; >> + } >> + >> + vma_pagesize = 1UL << vma_shift; >> +> /* >> * The stage2 has a minimum of 2 level table (For arm64 see >> * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can >> @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, >> phys_addr_t fault_ipa, >> */ >> 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; >> + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; >> mmap_read_unlock(current->mm); >> /* We need minimum second+third level pages */ >> > > Thanks, > Gavin > _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-02 9:01 ` Alexandru Elisei @ 2020-09-03 0:06 ` Gavin Shan 0 siblings, 0 replies; 11+ messages in thread From: Gavin Shan @ 2020-09-03 0:06 UTC (permalink / raw) To: Alexandru Elisei, linux-arm-kernel, kvmarm; +Cc: maz Hi Alex, On 9/2/20 7:01 PM, Alexandru Elisei wrote: > On 9/2/20 2:23 AM, Gavin Shan wrote: >> On 9/1/20 11:33 PM, Alexandru Elisei wrote: >>> When userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to >>> use the same block size to map the faulting IPA in stage 2. If stage 2 >>> cannot use the same size mapping because the block size doesn't fit in the >>> memslot or the memslot is not properly aligned, user_mem_abort() will fall >>> back to a page mapping, regardless of the block size. We can do better for >>> PUD backed hugetlbfs by checking if a PMD block mapping is possible before >>> deciding to use a page. >>> >>> vma_pagesize is an unsigned long, use 1UL instead of 1ULL when assigning >>> its value. >>> >>> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> >>> --- >>> arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- >>> 1 file changed, 14 insertions(+), 5 deletions(-) >>> Reviewed-by: Gavin Shan <gshan@redhat.com> >>> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c >>> index 25e7dc52c086..f590f7355cda 100644 >>> --- a/arch/arm64/kvm/mmu.c >>> +++ b/arch/arm64/kvm/mmu.c >>> @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, >>> phys_addr_t fault_ipa, >>> else >>> vma_shift = PAGE_SHIFT; >>> - vma_pagesize = 1ULL << vma_shift; >>> if (logging_active || >>> - (vma->vm_flags & VM_PFNMAP) || >>> - !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { >>> + (vma->vm_flags & VM_PFNMAP)) { >>> force_pte = true; >>> - vma_pagesize = PAGE_SIZE; >>> vma_shift = PAGE_SHIFT; >>> } >>> >> >> It looks incorrect because @vma_pagesize wasn't initialized when >> it's passed to fault_supports_stage2_huge_mapping() for the checking. >> It's assumed you missed the following changes according to the commit >> log: >> >> fault_supports_stage2_huge_mapping(memslot, hva, (1UL << vma_shift)) > > I'm not sure what you mean. Maybe you've misread the diff? Because the above call > to fault_supports_stage2_huge_mapping() was removed by the patch. > Yeah, your guess is correct as I looked into the removed code :) >> >>> + if (vma_shift == PUD_SHIFT && >>> + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) >>> + vma_shift = PMD_SHIFT; >>> + >>> + if (vma_shift == PMD_SHIFT && >>> + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { >>> + force_pte = true; >>> + vma_shift = PAGE_SHIFT; >>> + } >>> + >>> + vma_pagesize = 1UL << vma_shift; >>> +> /* >>> * The stage2 has a minimum of 2 level table (For arm64 see >>> * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can >>> @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, >>> phys_addr_t fault_ipa, >>> */ >>> 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; >>> + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; >>> mmap_read_unlock(current->mm); >>> /* We need minimum second+third level pages */ >>> >> Thanks, Gavin _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-01 13:33 ` [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are " Alexandru Elisei 2020-09-02 1:23 ` Gavin Shan @ 2020-09-04 9:58 ` Marc Zyngier 2020-09-08 12:23 ` Alexandru Elisei 1 sibling, 1 reply; 11+ messages in thread From: Marc Zyngier @ 2020-09-04 9:58 UTC (permalink / raw) To: Alexandru Elisei Cc: julien.thierry.kdev, james.morse, kvmarm, linux-arm-kernel, suzuki.poulose Hi Alex, On Tue, 01 Sep 2020 14:33:57 +0100, Alexandru Elisei <alexandru.elisei@arm.com> wrote: > > When userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to > use the same block size to map the faulting IPA in stage 2. If stage 2 > cannot use the same size mapping because the block size doesn't fit in the > memslot or the memslot is not properly aligned, user_mem_abort() will fall > back to a page mapping, regardless of the block size. We can do better for > PUD backed hugetlbfs by checking if a PMD block mapping is possible before > deciding to use a page. > > vma_pagesize is an unsigned long, use 1UL instead of 1ULL when assigning > its value. > > Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> > --- > arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- > 1 file changed, 14 insertions(+), 5 deletions(-) > > diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c > index 25e7dc52c086..f590f7355cda 100644 > --- a/arch/arm64/kvm/mmu.c > +++ b/arch/arm64/kvm/mmu.c > @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > else > vma_shift = PAGE_SHIFT; > > - vma_pagesize = 1ULL << vma_shift; > if (logging_active || > - (vma->vm_flags & VM_PFNMAP) || > - !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { > + (vma->vm_flags & VM_PFNMAP)) { > force_pte = true; > - vma_pagesize = PAGE_SIZE; > vma_shift = PAGE_SHIFT; > } > > + if (vma_shift == PUD_SHIFT && > + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) > + vma_shift = PMD_SHIFT; > + > + if (vma_shift == PMD_SHIFT && > + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { > + force_pte = true; > + vma_shift = PAGE_SHIFT; > + } > + > + vma_pagesize = 1UL << vma_shift; > + > /* > * The stage2 has a minimum of 2 level table (For arm64 see > * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can > @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, > */ > 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; > + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; > mmap_read_unlock(current->mm); > > /* We need minimum second+third level pages */ Although this looks like a sensible change, I'm a reluctant to take it at this stage, given that we already have a bunch of patches from Will to change the way we deal with PTs. Could you look into how this could fit into the new code instead? Thanks, M. -- Without deviation from the norm, progress is not possible. _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-04 9:58 ` Marc Zyngier @ 2020-09-08 12:23 ` Alexandru Elisei 2020-09-08 12:41 ` Marc Zyngier 0 siblings, 1 reply; 11+ messages in thread From: Alexandru Elisei @ 2020-09-08 12:23 UTC (permalink / raw) To: Marc Zyngier Cc: julien.thierry.kdev, james.morse, kvmarm, linux-arm-kernel, suzuki.poulose Hi Marc, On 9/4/20 10:58 AM, Marc Zyngier wrote: > Hi Alex, > > On Tue, 01 Sep 2020 14:33:57 +0100, > Alexandru Elisei <alexandru.elisei@arm.com> wrote: >> When userspace uses hugetlbfs for the VM memory, user_mem_abort() tries to >> use the same block size to map the faulting IPA in stage 2. If stage 2 >> cannot use the same size mapping because the block size doesn't fit in the >> memslot or the memslot is not properly aligned, user_mem_abort() will fall >> back to a page mapping, regardless of the block size. We can do better for >> PUD backed hugetlbfs by checking if a PMD block mapping is possible before >> deciding to use a page. >> >> vma_pagesize is an unsigned long, use 1UL instead of 1ULL when assigning >> its value. >> >> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> >> --- >> arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- >> 1 file changed, 14 insertions(+), 5 deletions(-) >> >> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c >> index 25e7dc52c086..f590f7355cda 100644 >> --- a/arch/arm64/kvm/mmu.c >> +++ b/arch/arm64/kvm/mmu.c >> @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, >> else >> vma_shift = PAGE_SHIFT; >> >> - vma_pagesize = 1ULL << vma_shift; >> if (logging_active || >> - (vma->vm_flags & VM_PFNMAP) || >> - !fault_supports_stage2_huge_mapping(memslot, hva, vma_pagesize)) { >> + (vma->vm_flags & VM_PFNMAP)) { >> force_pte = true; >> - vma_pagesize = PAGE_SIZE; >> vma_shift = PAGE_SHIFT; >> } >> >> + if (vma_shift == PUD_SHIFT && >> + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) >> + vma_shift = PMD_SHIFT; >> + >> + if (vma_shift == PMD_SHIFT && >> + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { >> + force_pte = true; >> + vma_shift = PAGE_SHIFT; >> + } >> + >> + vma_pagesize = 1UL << vma_shift; >> + >> /* >> * The stage2 has a minimum of 2 level table (For arm64 see >> * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can >> @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa, >> */ >> 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; >> + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; >> mmap_read_unlock(current->mm); >> >> /* We need minimum second+third level pages */ > Although this looks like a sensible change, I'm a reluctant to take it > at this stage, given that we already have a bunch of patches from Will > to change the way we deal with PTs. > > Could you look into how this could fit into the new code instead? Sure, that sounds very sensible. I'm in the process of reviewing Will's series, and after I'm done I'll rebase this on top of his patches and send it as v2. Does that sound ok to you? Or do you want me to base this patch on one of your branches? Thanks, Alex _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are not supported 2020-09-08 12:23 ` Alexandru Elisei @ 2020-09-08 12:41 ` Marc Zyngier 0 siblings, 0 replies; 11+ messages in thread From: Marc Zyngier @ 2020-09-08 12:41 UTC (permalink / raw) To: Alexandru Elisei Cc: julien.thierry.kdev, james.morse, kvmarm, linux-arm-kernel, suzuki.poulose On 2020-09-08 13:23, Alexandru Elisei wrote: > Hi Marc, > > On 9/4/20 10:58 AM, Marc Zyngier wrote: >> Hi Alex, >> >> On Tue, 01 Sep 2020 14:33:57 +0100, >> Alexandru Elisei <alexandru.elisei@arm.com> wrote: >>> When userspace uses hugetlbfs for the VM memory, user_mem_abort() >>> tries to >>> use the same block size to map the faulting IPA in stage 2. If stage >>> 2 >>> cannot use the same size mapping because the block size doesn't fit >>> in the >>> memslot or the memslot is not properly aligned, user_mem_abort() will >>> fall >>> back to a page mapping, regardless of the block size. We can do >>> better for >>> PUD backed hugetlbfs by checking if a PMD block mapping is possible >>> before >>> deciding to use a page. >>> >>> vma_pagesize is an unsigned long, use 1UL instead of 1ULL when >>> assigning >>> its value. >>> >>> Signed-off-by: Alexandru Elisei <alexandru.elisei@arm.com> >>> --- >>> arch/arm64/kvm/mmu.c | 19 ++++++++++++++----- >>> 1 file changed, 14 insertions(+), 5 deletions(-) >>> >>> diff --git a/arch/arm64/kvm/mmu.c b/arch/arm64/kvm/mmu.c >>> index 25e7dc52c086..f590f7355cda 100644 >>> --- a/arch/arm64/kvm/mmu.c >>> +++ b/arch/arm64/kvm/mmu.c >>> @@ -1871,15 +1871,24 @@ static int user_mem_abort(struct kvm_vcpu >>> *vcpu, phys_addr_t fault_ipa, >>> else >>> vma_shift = PAGE_SHIFT; >>> >>> - vma_pagesize = 1ULL << vma_shift; >>> if (logging_active || >>> - (vma->vm_flags & VM_PFNMAP) || >>> - !fault_supports_stage2_huge_mapping(memslot, hva, >>> vma_pagesize)) { >>> + (vma->vm_flags & VM_PFNMAP)) { >>> force_pte = true; >>> - vma_pagesize = PAGE_SIZE; >>> vma_shift = PAGE_SHIFT; >>> } >>> >>> + if (vma_shift == PUD_SHIFT && >>> + !fault_supports_stage2_huge_mapping(memslot, hva, PUD_SIZE)) >>> + vma_shift = PMD_SHIFT; >>> + >>> + if (vma_shift == PMD_SHIFT && >>> + !fault_supports_stage2_huge_mapping(memslot, hva, PMD_SIZE)) { >>> + force_pte = true; >>> + vma_shift = PAGE_SHIFT; >>> + } >>> + >>> + vma_pagesize = 1UL << vma_shift; >>> + >>> /* >>> * The stage2 has a minimum of 2 level table (For arm64 see >>> * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can >>> @@ -1889,7 +1898,7 @@ static int user_mem_abort(struct kvm_vcpu >>> *vcpu, phys_addr_t fault_ipa, >>> */ >>> 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; >>> + gfn = (fault_ipa & ~(vma_pagesize - 1)) >> PAGE_SHIFT; >>> mmap_read_unlock(current->mm); >>> >>> /* We need minimum second+third level pages */ >> Although this looks like a sensible change, I'm a reluctant to take it >> at this stage, given that we already have a bunch of patches from Will >> to change the way we deal with PTs. >> >> Could you look into how this could fit into the new code instead? > > Sure, that sounds very sensible. I'm in the process of reviewing Will's > series, > and after I'm done I'll rebase this on top of his patches and send it > as v2. Does > that sound ok to you? Or do you want me to base this patch on one of > your branches? Either way is fine (kvmarm/next has his patches). Just let me know what this is based on when you post the patches. M. -- Jazz is not dead. It just smells funny... _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0/2] KVM: arm64: user_mem_abort() improvements 2020-09-01 13:33 [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Alexandru Elisei 2020-09-01 13:33 ` [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported Alexandru Elisei 2020-09-01 13:33 ` [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are " Alexandru Elisei @ 2020-09-04 10:18 ` Marc Zyngier 2 siblings, 0 replies; 11+ messages in thread From: Marc Zyngier @ 2020-09-04 10:18 UTC (permalink / raw) To: Alexandru Elisei, linux-arm-kernel, kvmarm On Tue, 1 Sep 2020 14:33:55 +0100, Alexandru Elisei wrote: > The first patch is a fix for a bug that I found by code inspection. > > The second patch is an enhancement for the way user_mem_abort() handles > hugetlbfs backed VM memory. > > Tested on a rockpro64 with 4K pages and hugetlbfs hugepagesz=1G (PUD sized > block mappings). First test, guest RAM starts at 0x8100 0000 > (memslot->base_gfn not aligned to 1GB); second test, guest RAM starts at > 0x8000 0000, but is only 512 MB. In both cases using PUD mappings is not > possible because either the memslot base address is not aligned, or the > mapping would extend beyond the memslot. > > [...] Applied to next, thanks! [1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported commit: 7b75cd5128421c673153efb1236705696a1a9812 Cheers, M. -- Without deviation from the norm, progress is not possible. _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2020-09-08 12:42 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2020-09-01 13:33 [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Alexandru Elisei 2020-09-01 13:33 ` [PATCH 1/2] KVM: arm64: Update page shift if stage 2 block mapping not supported Alexandru Elisei 2020-09-02 0:57 ` Gavin Shan 2020-09-01 13:33 ` [PATCH 2/2] KVM: arm64: Try PMD block mappings if PUD mappings are " Alexandru Elisei 2020-09-02 1:23 ` Gavin Shan 2020-09-02 9:01 ` Alexandru Elisei 2020-09-03 0:06 ` Gavin Shan 2020-09-04 9:58 ` Marc Zyngier 2020-09-08 12:23 ` Alexandru Elisei 2020-09-08 12:41 ` Marc Zyngier 2020-09-04 10:18 ` [PATCH 0/2] KVM: arm64: user_mem_abort() improvements Marc Zyngier
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).