From patchwork Thu Mar 21 22:07:59 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Xu X-Patchwork-Id: 13599413 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id 23C00C6FD1F for ; Thu, 21 Mar 2024 22:08:31 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 6950E6B00A2; Thu, 21 Mar 2024 18:08:28 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 61BE16B00A3; Thu, 21 Mar 2024 18:08:28 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 447FF6B00A4; Thu, 21 Mar 2024 18:08:28 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id 2F2436B00A2 for ; Thu, 21 Mar 2024 18:08:28 -0400 (EDT) Received: from smtpin12.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay02.hostedemail.com (Postfix) with ESMTP id 0C2B2120375 for ; Thu, 21 Mar 2024 22:08:28 +0000 (UTC) X-FDA: 81922435896.12.39CDA86 Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by imf03.hostedemail.com (Postfix) with ESMTP id EAC682000C for ; Thu, 21 Mar 2024 22:08:25 +0000 (UTC) Authentication-Results: imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=hB4+bvBN; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf03.hostedemail.com: domain of peterx@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=peterx@redhat.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1711058906; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=JwtVKmcef1NV2SEc6Dd7pe+XzH6c3RDiTdVw8lXpTc0=; b=QA8dNDWRSKtaB9WDMHPleZ1tCF4WMT0/ut/ZU9PnFsXUoEO3D26wqmL+uU24HfGuBWSQez GypLM6aQO7iNSMFPjlr0+hOltpG5UonGE4TJTaIre1E4uQcssTBrFVTe1CY7MoIqAWqJwU Ig/dOQygBFyYnlTPPL9xU9//HKW7He0= ARC-Authentication-Results: i=1; imf03.hostedemail.com; dkim=pass header.d=redhat.com header.s=mimecast20190719 header.b=hB4+bvBN; dmarc=pass (policy=none) header.from=redhat.com; spf=pass (imf03.hostedemail.com: domain of peterx@redhat.com designates 170.10.133.124 as permitted sender) smtp.mailfrom=peterx@redhat.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1711058906; a=rsa-sha256; cv=none; b=FRDEcFYtfMtUerWRFoY7wCpn0/ZB5r2b6tn/RxN2mvs0/RrZafYfLhSZlx4gJKqQoPoMMz 5J0YwrLt5UN9kye7ELXdKTSy5YsVxLbJNEXMniR1nuYS5KnFtCC4TQxs5VpuJKh89M5epV wjQb+zMRbn5CO92txo05R/1cnFyduDo= DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1711058905; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=JwtVKmcef1NV2SEc6Dd7pe+XzH6c3RDiTdVw8lXpTc0=; b=hB4+bvBNOg9naYc25t9fXECr0IEmJ1v/tdJ54roV7oq+7hRL2LFS6zyNOG/9q0tfZHUZAJ xxj7d+Hss6T3Jmyncrd3dP/naobb7ELqmMNdxt9+zeANP2Zned/3GRzziONicJ2bhIzsPl sjysMEO4CA6sU2kdOtFPaWjxhInum/w= Received: from mail-qv1-f69.google.com (mail-qv1-f69.google.com [209.85.219.69]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-128-dQZdK670PPSJNta5dgJs-w-1; Thu, 21 Mar 2024 18:08:23 -0400 X-MC-Unique: dQZdK670PPSJNta5dgJs-w-1 Received: by mail-qv1-f69.google.com with SMTP id 6a1803df08f44-6961a54234cso2674606d6.1 for ; Thu, 21 Mar 2024 15:08:23 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1711058903; x=1711663703; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JwtVKmcef1NV2SEc6Dd7pe+XzH6c3RDiTdVw8lXpTc0=; b=DG0Uqi3lEdyJFf0X1Z9riXQ3ACJ8uwj2wtlSjSFYhgcVzVMI/xiM9AuzGvl4oco47P MId6UmB1XqEgJ/4AykqLtzVx5c7CaleDQw5tJSvYweKV3j/O2TTKK1Iy9HtG5eLGb4Lg MC9TbQEnlFO4bnE02J9jN8iMJ1xwASMJ8m7LbP6BMuJytt1DGNzHylPCPlzgd2pWDCWa zIDmFWVGFyAVgq/6hLBW5KFv0cFTB+6w/q3wtbDCEmuJW0txNH98v+hW4fpEuMpuUUws nZAt3VcC0Hsu2AwQ36RVxKNScbcNKJeFQuz4kFVs3t7lCm1qHuU6YJn8zYqZBCUMKDPV E6yg== X-Gm-Message-State: AOJu0YzbskwkSgINt/9v/GJQ5bRaIvPe4MeM2cmbIoBaYvqGxczKUT5f PBLojXuIPQtuHCf9suy20B52o6LjPXrBRrkCjy6vUjqDjOu+xJ+l1Ym/GwhHj99y6v0P6t6NlVX DYq1ucRjEICYiMhw0qIYAJPOwVfDte0eKWfOgVOmWt823kRkdYaykFQCn6TqfEzBrnZAN/lnsBo Lr9+tf09lTr8N1OTaxB/lomKFrN3wtsw== X-Received: by 2002:a05:6214:4403:b0:690:b47e:60e3 with SMTP id oj3-20020a056214440300b00690b47e60e3mr171655qvb.5.1711058902850; Thu, 21 Mar 2024 15:08:22 -0700 (PDT) X-Google-Smtp-Source: AGHT+IFefVkn71VpIW4uNQ3LlUv67q0iftDvBfI3myHkSibZanv1/17GTXunJ1XxyTP0oQ7cl/tpbA== X-Received: by 2002:a05:6214:4403:b0:690:b47e:60e3 with SMTP id oj3-20020a056214440300b00690b47e60e3mr171615qvb.5.1711058902326; Thu, 21 Mar 2024 15:08:22 -0700 (PDT) Received: from x1n.redhat.com ([99.254.121.117]) by smtp.gmail.com with ESMTPSA id o6-20020a0562140e4600b00690baf5cde9sm351663qvc.118.2024.03.21.15.08.20 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 21 Mar 2024 15:08:21 -0700 (PDT) From: peterx@redhat.com To: linux-mm@kvack.org, linux-kernel@vger.kernel.org Cc: linuxppc-dev@lists.ozlabs.org, Michael Ellerman , Christophe Leroy , Matthew Wilcox , Rik van Riel , Lorenzo Stoakes , Axel Rasmussen , peterx@redhat.com, Yang Shi , John Hubbard , linux-arm-kernel@lists.infradead.org, "Kirill A . Shutemov" , Andrew Jones , Vlastimil Babka , Mike Rapoport , Andrew Morton , Muchun Song , Christoph Hellwig , linux-riscv@lists.infradead.org, James Houghton , David Hildenbrand , Jason Gunthorpe , Andrea Arcangeli , "Aneesh Kumar K . V" , Mike Kravetz Subject: [PATCH v3 09/12] mm/gup: Handle huge pud for follow_pud_mask() Date: Thu, 21 Mar 2024 18:07:59 -0400 Message-ID: <20240321220802.679544-10-peterx@redhat.com> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240321220802.679544-1-peterx@redhat.com> References: <20240321220802.679544-1-peterx@redhat.com> MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Rspamd-Queue-Id: EAC682000C X-Rspam-User: X-Rspamd-Server: rspam04 X-Stat-Signature: nb3f5cchzqy68fshaoy6p93fzwqxpxfj X-HE-Tag: 1711058905-978798 X-HE-Meta: U2FsdGVkX18IM25Emj0dCfLUGq0mcC4CFfDOQXTR+gCGDeI8WnYqO1MqequQtzBxQl2c7wNoJv44e1xTZBEO0XoNdrOuR23XU2GTb2lzNp7ENsY6dqzsNKpzMzREZeuJP/VS2aNHmiQwJLEkK2yahQ/bAq1rxUwwHo1joQso1ir5W7WqWCOM1BDuONHw6XT7AKFVH0TPbu3cnD95teAn2EgQVWBlhDuP8Shglt2e6eP58bXMHZT9gAHhNZ48TNMO/1U8VOOLp3LQmrqSheuWlyS/Ke6GhwJD5Ph+XA3r4m9VyF/Nw+YRmXt2PSfpR8MWMMya/RSHMnW9zJBg9iqbURgsfPrPp2qe2pabwJBV/xfXfq8sAEqvc43AnHCI3z7j4rdLhzEsdIMxnQ0qGuRbeGK829SMS70GHH6XEvORTYscbjGCTfKUkta+VHLcx6rVubddLA7GcKpO6/kmbawetaUkyY7I5cyvR850Koig/Y1TUvH9j+d1BHvkNRDwXNPlRZgItOSR0l0E0OGC+/d2D1HL4l+WyVLaNoknNnGn8EEpboaAwdlhJvepPfARkvmoSYvHxMWBcD9dXppG+W9qex7Lmv4dUJ7zedlTAy6I9mV6e0uMXB5dSa76kIcQ+K8Pc1n3y/NDVv+o+NVybdHWEEHqvyHDdacHEk4CH3WZXcYUvZhM8aT/grq5P3HC79+F9EuLAKFaj33M5082q7gP3yhekYyFXx8lQ0GHx+914XOFTsnONn8sFlSz1qXYV/m5R8qNtN7w/cJAioCRpPV9BvP2CiTY0vksl67E1F5RpfWZkFtwesiKMwggbd5v3pOkdRtlQ9yrU8ZooOdTwlCkTg1n5ObjOs4KAb/Mo4apB8zAvgQh+ebFbOerL2kLPYYtQcsCRm7p+doZRDfmUsXata0oUhqQrHG9BdLVjOFQgqWHt22Tr+0MyZveU7Olb+7bFAYMN/qdZ3+4uOnLTDF i1j8+0dP sB/BDI4Qqi25qOH+m4lPJ2vx9whhGKjCUUvgMUV2MO+CHFCKBYCTLKJE6Xzyl1R/7dTpMk5q2xpHxygZnxYg019TiqSrEGkBm9FTimb6lLVFvBD7TxHqknRv3PAN4adzLLrZRPnOBZMNlMitcOs5Z01XBcN1BoOhbhn9/UDeV+4TsCgY+O/hD/U4wfK7g3pUcT38H/jFEgGJZFmNrd9iuWtEw1xT32DHy2gBolEIAsHKj495/O6csTSv7U3cRQajThOtIMGLqrYgRMi53qo7hWhcv6PiLeafOrMOuf8tEm+nPG5H6J4Zegu9uCm7LU3nLHEKovdcgQ/vfUwEWG3ScAAx8ll2qqkXCtsVeES9SZNpzEQwDcjKxIv55OK8wUD/sq0bncCdubuWOAvT6dvadop9QXUpImKhr8NjA0p0MgD2iZh477hFjzD0M4cC1eX43loFWCB/5Bhj/5xo= X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: List-Subscribe: List-Unsubscribe: From: Peter Xu Teach follow_pud_mask() to be able to handle normal PUD pages like hugetlb. Rename follow_devmap_pud() to follow_huge_pud() so that it can process either huge devmap or hugetlb. Move it out of TRANSPARENT_HUGEPAGE_PUD and and huge_memory.c (which relies on CONFIG_THP). Switch to pud_leaf() to detect both cases in the slow gup. In the new follow_huge_pud(), taking care of possible CoR for hugetlb if necessary. touch_pud() needs to be moved out of huge_memory.c to be accessable from gup.c even if !THP. Since at it, optimize the non-present check by adding a pud_present() early check before taking the pgtable lock, failing the follow_page() early if PUD is not present: that is required by both devmap or hugetlb. Use pud_huge() to also cover the pud_devmap() case. One more trivial thing to mention is, introduce "pud_t pud" in the code paths along the way, so the code doesn't dereference *pudp multiple time. Not only because that looks less straightforward, but also because if the dereference really happened, it's not clear whether there can be race to see different *pudp values when it's being modified at the same time. Setting ctx->page_mask properly for a PUD entry. As a side effect, this patch should also be able to optimize devmap GUP on PUD to be able to jump over the whole PUD range, but not yet verified. Hugetlb already can do so prior to this patch. Reviewed-by: Jason Gunthorpe Signed-off-by: Peter Xu --- include/linux/huge_mm.h | 8 ----- mm/gup.c | 70 +++++++++++++++++++++++++++++++++++++++-- mm/huge_memory.c | 47 ++------------------------- mm/internal.h | 2 ++ 4 files changed, 71 insertions(+), 56 deletions(-) diff --git a/include/linux/huge_mm.h b/include/linux/huge_mm.h index 3bcdfc7e5d57..39195f7c5269 100644 --- a/include/linux/huge_mm.h +++ b/include/linux/huge_mm.h @@ -346,8 +346,6 @@ static inline bool folio_test_pmd_mappable(struct folio *folio) struct page *follow_devmap_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd, int flags, struct dev_pagemap **pgmap); -struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, - pud_t *pud, int flags, struct dev_pagemap **pgmap); vm_fault_t do_huge_pmd_numa_page(struct vm_fault *vmf); @@ -504,12 +502,6 @@ static inline struct page *follow_devmap_pmd(struct vm_area_struct *vma, return NULL; } -static inline struct page *follow_devmap_pud(struct vm_area_struct *vma, - unsigned long addr, pud_t *pud, int flags, struct dev_pagemap **pgmap) -{ - return NULL; -} - static inline bool thp_migration_supported(void) { return false; diff --git a/mm/gup.c b/mm/gup.c index a338944e4425..ae21afb9434e 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -525,6 +525,70 @@ static struct page *no_page_table(struct vm_area_struct *vma, return NULL; } +#ifdef CONFIG_PGTABLE_HAS_HUGE_LEAVES +static struct page *follow_huge_pud(struct vm_area_struct *vma, + unsigned long addr, pud_t *pudp, + int flags, struct follow_page_context *ctx) +{ + struct mm_struct *mm = vma->vm_mm; + struct page *page; + pud_t pud = *pudp; + unsigned long pfn = pud_pfn(pud); + int ret; + + assert_spin_locked(pud_lockptr(mm, pudp)); + + if ((flags & FOLL_WRITE) && !pud_write(pud)) + return NULL; + + if (!pud_present(pud)) + return NULL; + + pfn += (addr & ~PUD_MASK) >> PAGE_SHIFT; + + if (IS_ENABLED(CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD) && + pud_devmap(pud)) { + /* + * device mapped pages can only be returned if the caller + * will manage the page reference count. + * + * At least one of FOLL_GET | FOLL_PIN must be set, so + * assert that here: + */ + if (!(flags & (FOLL_GET | FOLL_PIN))) + return ERR_PTR(-EEXIST); + + if (flags & FOLL_TOUCH) + touch_pud(vma, addr, pudp, flags & FOLL_WRITE); + + ctx->pgmap = get_dev_pagemap(pfn, ctx->pgmap); + if (!ctx->pgmap) + return ERR_PTR(-EFAULT); + } + + page = pfn_to_page(pfn); + + if (!pud_devmap(pud) && !pud_write(pud) && + gup_must_unshare(vma, flags, page)) + return ERR_PTR(-EMLINK); + + ret = try_grab_page(page, flags); + if (ret) + page = ERR_PTR(ret); + else + ctx->page_mask = HPAGE_PUD_NR - 1; + + return page; +} +#else /* CONFIG_PGTABLE_HAS_HUGE_LEAVES */ +static struct page *follow_huge_pud(struct vm_area_struct *vma, + unsigned long addr, pud_t *pudp, + int flags, struct follow_page_context *ctx) +{ + return NULL; +} +#endif /* CONFIG_PGTABLE_HAS_HUGE_LEAVES */ + static int follow_pfn_pte(struct vm_area_struct *vma, unsigned long address, pte_t *pte, unsigned int flags) { @@ -760,11 +824,11 @@ static struct page *follow_pud_mask(struct vm_area_struct *vma, pudp = pud_offset(p4dp, address); pud = READ_ONCE(*pudp); - if (pud_none(pud)) + if (!pud_present(pud)) return no_page_table(vma, flags, address); - if (pud_devmap(pud)) { + if (pud_leaf(pud)) { ptl = pud_lock(mm, pudp); - page = follow_devmap_pud(vma, address, pudp, flags, &ctx->pgmap); + page = follow_huge_pud(vma, address, pudp, flags, ctx); spin_unlock(ptl); if (page) return page; diff --git a/mm/huge_memory.c b/mm/huge_memory.c index c77cedf45f3a..f8bd2012bc27 100644 --- a/mm/huge_memory.c +++ b/mm/huge_memory.c @@ -1363,8 +1363,8 @@ int copy_huge_pmd(struct mm_struct *dst_mm, struct mm_struct *src_mm, } #ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD -static void touch_pud(struct vm_area_struct *vma, unsigned long addr, - pud_t *pud, bool write) +void touch_pud(struct vm_area_struct *vma, unsigned long addr, + pud_t *pud, bool write) { pud_t _pud; @@ -1376,49 +1376,6 @@ static void touch_pud(struct vm_area_struct *vma, unsigned long addr, update_mmu_cache_pud(vma, addr, pud); } -struct page *follow_devmap_pud(struct vm_area_struct *vma, unsigned long addr, - pud_t *pud, int flags, struct dev_pagemap **pgmap) -{ - unsigned long pfn = pud_pfn(*pud); - struct mm_struct *mm = vma->vm_mm; - struct page *page; - int ret; - - assert_spin_locked(pud_lockptr(mm, pud)); - - if (flags & FOLL_WRITE && !pud_write(*pud)) - return NULL; - - if (pud_present(*pud) && pud_devmap(*pud)) - /* pass */; - else - return NULL; - - if (flags & FOLL_TOUCH) - touch_pud(vma, addr, pud, flags & FOLL_WRITE); - - /* - * device mapped pages can only be returned if the - * caller will manage the page reference count. - * - * At least one of FOLL_GET | FOLL_PIN must be set, so assert that here: - */ - if (!(flags & (FOLL_GET | FOLL_PIN))) - return ERR_PTR(-EEXIST); - - pfn += (addr & ~PUD_MASK) >> PAGE_SHIFT; - *pgmap = get_dev_pagemap(pfn, *pgmap); - if (!*pgmap) - return ERR_PTR(-EFAULT); - page = pfn_to_page(pfn); - - ret = try_grab_page(page, flags); - if (ret) - page = ERR_PTR(ret); - - return page; -} - int copy_huge_pud(struct mm_struct *dst_mm, struct mm_struct *src_mm, pud_t *dst_pud, pud_t *src_pud, unsigned long addr, struct vm_area_struct *vma) diff --git a/mm/internal.h b/mm/internal.h index f8b31234c130..63e4f6e001be 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -1102,6 +1102,8 @@ int __must_check try_grab_page(struct page *page, unsigned int flags); /* * mm/huge_memory.c */ +void touch_pud(struct vm_area_struct *vma, unsigned long addr, + pud_t *pud, bool write); struct page *follow_trans_huge_pmd(struct vm_area_struct *vma, unsigned long addr, pmd_t *pmd, unsigned int flags);