Re: [PATCH v4 29/33] x86/mm: try VMA lock-based page fault handling first

From: Suren Baghdasaryan
Date: Thu Jun 29 2023 - 11:31:03 EST


On Thu, Jun 29, 2023 at 7:40 AM Jiri Slaby <jirislaby@xxxxxxxxxx> wrote:
>
> Hi,
>
> On 27. 02. 23, 18:36, Suren Baghdasaryan wrote:
> > Attempt VMA lock-based page fault handling first, and fall back to the
> > existing mmap_lock-based handling if that fails.
> >
> > Signed-off-by: Suren Baghdasaryan <surenb@xxxxxxxxxx>
> > ---
> > arch/x86/Kconfig | 1 +
> > arch/x86/mm/fault.c | 36 ++++++++++++++++++++++++++++++++++++
> > 2 files changed, 37 insertions(+)
> >
> > diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
> > index a825bf031f49..df21fba77db1 100644
> > --- a/arch/x86/Kconfig
> > +++ b/arch/x86/Kconfig
> > @@ -27,6 +27,7 @@ config X86_64
> > # Options that are inherently 64-bit kernel only:
> > select ARCH_HAS_GIGANTIC_PAGE
> > select ARCH_SUPPORTS_INT128 if CC_HAS_INT128
> > + select ARCH_SUPPORTS_PER_VMA_LOCK
> > select ARCH_USE_CMPXCHG_LOCKREF
> > select HAVE_ARCH_SOFT_DIRTY
> > select MODULES_USE_ELF_RELA
> > diff --git a/arch/x86/mm/fault.c b/arch/x86/mm/fault.c
> > index a498ae1fbe66..e4399983c50c 100644
> > --- a/arch/x86/mm/fault.c
> > +++ b/arch/x86/mm/fault.c
> > @@ -19,6 +19,7 @@
> > #include <linux/uaccess.h> /* faulthandler_disabled() */
> > #include <linux/efi.h> /* efi_crash_gracefully_on_page_fault()*/
> > #include <linux/mm_types.h>
> > +#include <linux/mm.h> /* find_and_lock_vma() */
> >
> > #include <asm/cpufeature.h> /* boot_cpu_has, ... */
> > #include <asm/traps.h> /* dotraplinkage, ... */
> > @@ -1333,6 +1334,38 @@ void do_user_addr_fault(struct pt_regs *regs,
> > }
> > #endif
> >
> > +#ifdef CONFIG_PER_VMA_LOCK
> > + if (!(flags & FAULT_FLAG_USER))
> > + goto lock_mmap;
> > +
> > + vma = lock_vma_under_rcu(mm, address);
> > + if (!vma)
> > + goto lock_mmap;
> > +
> > + if (unlikely(access_error(error_code, vma))) {
> > + vma_end_read(vma);
> > + goto lock_mmap;
> > + }
> > + fault = handle_mm_fault(vma, address, flags | FAULT_FLAG_VMA_LOCK, regs);
> > + vma_end_read(vma);
> > +
> > + if (!(fault & VM_FAULT_RETRY)) {
> > + count_vm_vma_lock_event(VMA_LOCK_SUCCESS);
> > + goto done;
> > + }
> > + count_vm_vma_lock_event(VMA_LOCK_RETRY);
>
> This is apparently not strong enough as it causes go build failures like:
>
> [ 409s] strconv
> [ 409s] releasep: m=0x579e2000 m->p=0x5781c600 p->m=0x0 p->status=2
> [ 409s] fatal error: releasep: invalid p state
> [ 409s]
>
> [ 325s] hash/adler32
> [ 325s] hash/crc32
> [ 325s] cmd/internal/codesign
> [ 336s] fatal error: runtime: out of memory

Hi Jiri,
Thanks for reporting! I'm not familiar with go builds. Could you
please explain the error to me or point me to some documentation to
decipher that error?
Thanks,
Suren.

>
> There are many kinds of similar errors. It happens in 1-3 out of 20
> builds only.
>
> If I revert the commit on top of 6.4, they all dismiss. Any idea?
>
> The downstream report:
> https://bugzilla.suse.com/show_bug.cgi?id=1212775
>
> > +
> > + /* Quick path to respond to signals */
> > + if (fault_signal_pending(fault, regs)) {
> > + if (!user_mode(regs))
> > + kernelmode_fixup_or_oops(regs, error_code, address,
> > + SIGBUS, BUS_ADRERR,
> > + ARCH_DEFAULT_PKEY);
> > + return;
> > + }
> > +lock_mmap:
> > +#endif /* CONFIG_PER_VMA_LOCK */
> > +
> > /*
> > * Kernel-mode access to the user address space should only occur
> > * on well-defined single instructions listed in the exception
> > @@ -1433,6 +1466,9 @@ void do_user_addr_fault(struct pt_regs *regs,
> > }
> >
> > mmap_read_unlock(mm);
> > +#ifdef CONFIG_PER_VMA_LOCK
> > +done:
> > +#endif
> > if (likely(!(fault & VM_FAULT_ERROR)))
> > return;
> >
>
> thanks,
> --
> js
> suse labs
>