From nobody Fri Dec 19 15:34:30 2025 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by smtp.subspace.kernel.org (Postfix) with ESMTP id E3FC6224B13 for ; Mon, 17 Feb 2025 14:08:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=217.140.110.172 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739801330; cv=none; b=Il51uU1KrY9pZU42wrkpcQ3Czq5xarYG5J2rQCASU8UWlacCuKU+g/YH1T3G6w8inLtL4+XVQLYWjtVMf8AHTARmP+3Fsu1Lppy9kRLtOsKT2e+ZS4xpMoCmv5nVO5L/RiopObMy/E7QdLd0vbMe0hggPWtoBxCiDuPpobuEBVI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1739801330; c=relaxed/simple; bh=ch6bZEi6Ht07fUCsXeDpY6YzkgLQvobbfQJbhDWQOGE=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QOmu74ZrAheccmKh56tvyd7RJXVnPfwyL6J0jvUwGQJol/iJRPMuoADPYattKnW1bPJBmdrFjjRHoTIgcSZ+6zWAbIXt5pELcuV9O1TA71JNJpIXbu9NvbrSTehvepySOJoWfrwaH9or9vhpoMTQLneowKSR/pgNQUPAMHg9sGk= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com; spf=pass smtp.mailfrom=arm.com; arc=none smtp.client-ip=217.140.110.172 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=arm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=arm.com Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 80BD71E5E; Mon, 17 Feb 2025 06:09:07 -0800 (PST) Received: from e125769.cambridge.arm.com (e125769.cambridge.arm.com [10.1.196.27]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 134433F6A8; Mon, 17 Feb 2025 06:08:45 -0800 (PST) From: Ryan Roberts To: Catalin Marinas , Will Deacon , Pasha Tatashin , Andrew Morton , Uladzislau Rezki , Christoph Hellwig , David Hildenbrand , "Matthew Wilcox (Oracle)" , Mark Rutland , Anshuman Khandual , Alexandre Ghiti , Kevin Brodsky Cc: Ryan Roberts , linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 11/14] mm/vmalloc: Batch arch_sync_kernel_mappings() more efficiently Date: Mon, 17 Feb 2025 14:08:03 +0000 Message-ID: <20250217140809.1702789-12-ryan.roberts@arm.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20250217140809.1702789-1-ryan.roberts@arm.com> References: <20250217140809.1702789-1-ryan.roberts@arm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" When page_shift is greater than PAGE_SIZE, __vmap_pages_range_noflush() will call vmap_range_noflush() for each individual huge page. But vmap_range_noflush() would previously call arch_sync_kernel_mappings() directly so this would end up being called for every huge page. We can do better than this; refactor the call into the outer __vmap_pages_range_noflush() so that it is only called once for the entire batch operation. This will benefit performance for arm64 which is about to opt-in to using the hook. Reviewed-by: Anshuman Khandual Signed-off-by: Ryan Roberts Reviewed-by: Catalin Marinas --- mm/vmalloc.c | 60 ++++++++++++++++++++++++++-------------------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 68950b1824d0..50fd44439875 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -285,40 +285,38 @@ static int vmap_p4d_range(pgd_t *pgd, unsigned long a= ddr, unsigned long end, =20 static int vmap_range_noflush(unsigned long addr, unsigned long end, phys_addr_t phys_addr, pgprot_t prot, - unsigned int max_page_shift) + unsigned int max_page_shift, pgtbl_mod_mask *mask) { pgd_t *pgd; - unsigned long start; unsigned long next; int err; - pgtbl_mod_mask mask =3D 0; =20 might_sleep(); BUG_ON(addr >=3D end); =20 - start =3D addr; pgd =3D pgd_offset_k(addr); do { next =3D pgd_addr_end(addr, end); err =3D vmap_p4d_range(pgd, addr, next, phys_addr, prot, - max_page_shift, &mask); + max_page_shift, mask); if (err) break; } while (pgd++, phys_addr +=3D (next - addr), addr =3D next, addr !=3D en= d); =20 - if (mask & ARCH_PAGE_TABLE_SYNC_MASK) - arch_sync_kernel_mappings(start, end); - return err; } =20 int vmap_page_range(unsigned long addr, unsigned long end, phys_addr_t phys_addr, pgprot_t prot) { + pgtbl_mod_mask mask =3D 0; int err; =20 err =3D vmap_range_noflush(addr, end, phys_addr, pgprot_nx(prot), - ioremap_max_page_shift); + ioremap_max_page_shift, &mask); + if (mask & ARCH_PAGE_TABLE_SYNC_MASK) + arch_sync_kernel_mappings(addr, end); + flush_cache_vmap(addr, end); if (!err) err =3D kmsan_ioremap_page_range(addr, end, phys_addr, prot, @@ -587,29 +585,24 @@ static int vmap_pages_p4d_range(pgd_t *pgd, unsigned = long addr, } =20 static int vmap_small_pages_range_noflush(unsigned long addr, unsigned lon= g end, - pgprot_t prot, struct page **pages) + pgprot_t prot, struct page **pages, pgtbl_mod_mask *mask) { - unsigned long start =3D addr; pgd_t *pgd; unsigned long next; int err =3D 0; int nr =3D 0; - pgtbl_mod_mask mask =3D 0; =20 BUG_ON(addr >=3D end); pgd =3D pgd_offset_k(addr); do { next =3D pgd_addr_end(addr, end); if (pgd_bad(*pgd)) - mask |=3D PGTBL_PGD_MODIFIED; - err =3D vmap_pages_p4d_range(pgd, addr, next, prot, pages, &nr, &mask); + *mask |=3D PGTBL_PGD_MODIFIED; + err =3D vmap_pages_p4d_range(pgd, addr, next, prot, pages, &nr, mask); if (err) break; } while (pgd++, addr =3D next, addr !=3D end); =20 - if (mask & ARCH_PAGE_TABLE_SYNC_MASK) - arch_sync_kernel_mappings(start, end); - return err; } =20 @@ -626,26 +619,33 @@ int __vmap_pages_range_noflush(unsigned long addr, un= signed long end, pgprot_t prot, struct page **pages, unsigned int page_shift) { unsigned int i, nr =3D (end - addr) >> PAGE_SHIFT; + unsigned long start =3D addr; + pgtbl_mod_mask mask =3D 0; + int err =3D 0; =20 WARN_ON(page_shift < PAGE_SHIFT); =20 if (!IS_ENABLED(CONFIG_HAVE_ARCH_HUGE_VMALLOC) || - page_shift =3D=3D PAGE_SHIFT) - return vmap_small_pages_range_noflush(addr, end, prot, pages); - - for (i =3D 0; i < nr; i +=3D 1U << (page_shift - PAGE_SHIFT)) { - int err; - - err =3D vmap_range_noflush(addr, addr + (1UL << page_shift), - page_to_phys(pages[i]), prot, - page_shift); - if (err) - return err; + page_shift =3D=3D PAGE_SHIFT) { + err =3D vmap_small_pages_range_noflush(addr, end, prot, pages, + &mask); + } else { + for (i =3D 0; i < nr; i +=3D 1U << (page_shift - PAGE_SHIFT)) { + err =3D vmap_range_noflush(addr, + addr + (1UL << page_shift), + page_to_phys(pages[i]), prot, + page_shift, &mask); + if (err) + break; =20 - addr +=3D 1UL << page_shift; + addr +=3D 1UL << page_shift; + } } =20 - return 0; + if (mask & ARCH_PAGE_TABLE_SYNC_MASK) + arch_sync_kernel_mappings(start, end); + + return err; } =20 int vmap_pages_range_noflush(unsigned long addr, unsigned long end, --=20 2.43.0