diff options
author | 2022-12-12 11:14:19 -0700 | |
---|---|---|
committer | 2024-07-29 18:15:05 +0200 | |
commit | 8f9e92b36972415b97abc598bbdf1908806b1882 (patch) | |
tree | efa8d96a10a6cbc587e1e4fc1befaf18402b8806 /mm/mempolicy.c | |
parent | minmax: simplify min()/max()/clamp() implementation (diff) | |
download | linux-rng-jd/vdso-skip-insn.tar.xz linux-rng-jd/vdso-skip-insn.zip |
x86: mm: Skip faulting instruction for VM_DROPPABLE faultsjd/vdso-skip-insn
VM_DROPPABLE allocations can, by definition, be dropped and then filled
with zeros at any time. For reads, this is working as intended:
userspace reads memory, and at some point it comes back as zeros.
Writes, however, are another story.
If the kernel has dropped the memory and userspace writes to those
addresses, the page fault handler traps, the memory is allocated, and
control is returned to userspace to retry the write, which succeeds.
But if the memory fails to be allocated when trapping, control is still
returned to userspace to retry the write, and the whole thing happens
again. And it doesn't make sense to kill the process for a droppable
mapping. Eventually hopefully there's enough memory and this succeeds.
However, that retry loop really is unnecessary. Instead, the write could
just be skipped, because skipping a write is the same as the write
succeeding and then immediately after the kernel dropping the page so
that subsequent reads return zeros.
So, rather than merely returning to userspace at the same write
instruction to be retried, skip that write instruction.
Implement it on x86, where instructions are variable size, by copying
userspace's %rip to a stack buffer of size MAX_INSN_SIZE, decoding it,
and then adding the length of the decoded instruction to userspace's
%rip. In the event any of these fail, just fallback to not advancing
%rip and trying again.
Cc: linux-mm@kvack.org
Cc: x86@kernel.org
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index b858e22b259d..d75e0ee19aa3 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c @@ -2306,7 +2306,7 @@ struct folio *vma_alloc_folio_noprof(gfp_t gfp, int order, struct vm_area_struct struct folio *folio; if (vma->vm_flags & VM_DROPPABLE) - gfp |= __GFP_NOWARN; + gfp |= __GFP_NOWARN | __GFP_NORETRY; pol = get_vma_policy(vma, addr, order, &ilx); folio = folio_alloc_mpol_noprof(gfp, order, pol, ilx, numa_node_id()); |